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.11
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
5085UA_StatusCode connectSync(UA_Client *client); /* Only exposed for unit tests */
5086void notifyClientState(UA_Client *client);
5087void processERRResponse(UA_Client *client, const UA_ByteString *chunk);
5088void processACKResponse(UA_Client *client, const UA_ByteString *chunk);
5089void processOPNResponse(UA_Client *client, const UA_ByteString *message);
5090void closeSecureChannel(UA_Client *client);
5091
5092UA_StatusCode
5093connectIterate(UA_Client *client, UA_UInt32 timeout);
5094
5095UA_StatusCode
5096receiveResponseAsync(UA_Client *client, UA_UInt32 timeout);
5097
5098void
5099Client_warnEndpointsResult(UA_Client *client,
5100 const UA_GetEndpointsResponse *response,
5101 const UA_String *endpointUrl);
5102
5103_UA_END_DECLS
5104
5105
5106/**** amalgamated original file "/src/pubsub/ua_pubsub_config.h" ****/
5107
5108/* This Source Code Form is subject to the terms of the Mozilla Public
5109 * License, v. 2.0. If a copy of the MPL was not distributed with this
5110 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5111 *
5112 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
5113 * Copyright (c) 2020 Thomas Fischer, Siemens AG
5114 */
5115
5116#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
5117
5118
5119
5120/* Decodes the information from the ByteString. If the decoded content is a
5121 * PubSubConfiguration in a UABinaryFileDataType-object. It will overwrite the
5122 * current PubSub configuration from the server. */
5123UA_StatusCode
5124UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
5125 const UA_ByteString buffer);
5126
5127/* Saves the current PubSub configuration of a server in a byteString. */
5128UA_StatusCode
5129UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
5130 UA_ByteString *buffer);
5131
5132
5133#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
5134
5135/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.h" ****/
5136
5137/* WARNING: This is a generated file.
5138 * Any manual changes will be overwritten. */
5139
5140#ifndef NAMESPACE0_GENERATED_H_
5141#define NAMESPACE0_GENERATED_H_
5142
5143
5144#ifdef UA_ENABLE_AMALGAMATION
5145
5146/* The following declarations are in the open62541.c file so here's needed when compiling nodesets externally */
5147
5148# ifndef UA_INTERNAL //this definition is needed to hide this code in the amalgamated .c file
5149
5150typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos,
5151 const UA_Byte **bufEnd);
5152
5153UA_StatusCode
5154UA_encodeBinary(const void *src, const UA_DataType *type,
5155 UA_Byte **bufPos, const UA_Byte **bufEnd,
5156 UA_exchangeEncodeBuffer exchangeCallback,
5157 void *exchangeHandle) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
5158
5159UA_StatusCode
5160UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst,
5161 const UA_DataType *type, size_t customTypesSize,
5162 const UA_DataType *customTypes) UA_FUNC_ATTR_WARN_UNUSED_RESULT;
5163
5164size_t
5165UA_calcSizeBinary(void *p, const UA_DataType *type);
5166
5167const UA_DataType *
5168UA_findDataTypeByBinary(const UA_NodeId *typeId);
5169
5170# endif // UA_INTERNAL
5171
5172#else // UA_ENABLE_AMALGAMATION
5173#endif
5174
5175
5176
5177
5178_UA_BEGIN_DECLS
5179
5180extern UA_StatusCode namespace0_generated(UA_Server *server);
5181
5182_UA_END_DECLS
5183
5184#endif /* NAMESPACE0_GENERATED_H_ */
5185
5186/**** amalgamated original file "/src/ua_types.c" ****/
5187
5188/* This Source Code Form is subject to the terms of the Mozilla Public
5189 * License, v. 2.0. If a copy of the MPL was not distributed with this
5190 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5191 *
5192 * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner)
5193 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
5194 * Copyright 2014, 2016-2017 (c) Florian Palm
5195 * Copyright 2014-2016 (c) Sten Grüner
5196 * Copyright 2014 (c) Leon Urbas
5197 * Copyright 2015 (c) Chris Iatrou
5198 * Copyright 2015 (c) Markus Graube
5199 * Copyright 2015 (c) Reza Ebrahimi
5200 * Copyright 2015-2016 (c) Oleksiy Vasylyev
5201 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
5202 * Copyright 2016 (c) Lorenz Haas
5203 */
5204
5205
5206
5207#define UA_MAX_ARRAY_DIMS 100 /* Max dimensions of an array */
5208
5209/* Datatype Handling
5210 * -----------------
5211 * This file contains handling functions for the builtin types and functions
5212 * handling of structured types and arrays. These need type descriptions in a
5213 * UA_DataType structure. The UA_DataType structures as well as all non-builtin
5214 * datatypes are autogenerated. */
5215
5216/* Global definition of NULL type instances. These are always zeroed out, as
5217 * mandated by the C/C++ standard for global values with no initializer. */
5218const UA_String UA_STRING_NULL = {0};
5219const UA_ByteString UA_BYTESTRING_NULL = {0};
5220const UA_Guid UA_GUID_NULL = {0};
5221const UA_NodeId UA_NODEID_NULL = {0};
5222const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {0};
5223
5224typedef UA_StatusCode
5225(*UA_copySignature)(const void *src, void *dst, const UA_DataType *type);
5226extern const UA_copySignature copyJumpTable[UA_DATATYPEKINDS];
5227
5228typedef void (*UA_clearSignature)(void *p, const UA_DataType *type);
5229extern const UA_clearSignature clearJumpTable[UA_DATATYPEKINDS];
5230
5231typedef UA_Order
5232(*UA_orderSignature)(const void *p1, const void *p2, const UA_DataType *type);
5233extern const UA_orderSignature orderJumpTable[UA_DATATYPEKINDS];
5234
5235const UA_DataType *
5236UA_findDataTypeWithCustom(const UA_NodeId *typeId,
5237 const UA_DataTypeArray *customTypes) {
5238 /* Always look in built-in types first (may contain data types from all
5239 * namespaces).
5240 *
5241 * TODO: The standard-defined types are ordered. See if binary search is
5242 * more efficient. */
5243 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
5244 if(UA_NodeId_equal(n1: &UA_TYPES[i].typeId, n2: typeId))
5245 return &UA_TYPES[i];
5246 }
5247
5248 /* Search in the customTypes */
5249 while(customTypes) {
5250 for(size_t i = 0; i < customTypes->typesSize; ++i) {
5251 if(UA_NodeId_equal(n1: &customTypes->types[i].typeId, n2: typeId))
5252 return &customTypes->types[i];
5253 }
5254 customTypes = customTypes->next;
5255 }
5256
5257 return NULL;
5258}
5259
5260const UA_DataType *
5261UA_findDataType(const UA_NodeId *typeId) {
5262 return UA_findDataTypeWithCustom(typeId, NULL);
5263}
5264
5265/***************************/
5266/* Random Number Generator */
5267/***************************/
5268
5269//TODO is this safe for multithreading?
5270static pcg32_random_t UA_rng = PCG32_INITIALIZER;
5271
5272void
5273UA_random_seed(u64 seed) {
5274 pcg32_srandom_r(rng: &UA_rng, initial_state: seed, initseq: (u64)UA_DateTime_now());
5275}
5276
5277u32
5278UA_UInt32_random(void) {
5279 return (u32)pcg32_random_r(rng: &UA_rng);
5280}
5281
5282/*****************/
5283/* Builtin Types */
5284/*****************/
5285
5286UA_String
5287UA_String_fromChars(const char *src) {
5288 UA_String s; s.length = 0; s.data = NULL;
5289 if(!src)
5290 return s;
5291 s.length = strlen(s: src);
5292 if(s.length > 0) {
5293 s.data = (u8*)UA_malloc(size: s.length);
5294 if(UA_UNLIKELY(!s.data)) {
5295 s.length = 0;
5296 return s;
5297 }
5298 memcpy(dest: s.data, src: src, n: s.length);
5299 } else {
5300 s.data = (u8*)UA_EMPTY_ARRAY_SENTINEL;
5301 }
5302 return s;
5303}
5304
5305static UA_Order
5306stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type);
5307static UA_Order
5308guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type);
5309static UA_Order
5310qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
5311 const UA_DataType *type);
5312
5313UA_Boolean
5314UA_String_equal(const UA_String *s1, const UA_String *s2) {
5315 return (stringOrder(p1: s1, p2: s2, NULL) == UA_ORDER_EQ);
5316}
5317
5318/* Do not expose UA_String_equal_ignorecase to public API as it currently only handles
5319 * ASCII strings, and not UTF8! */
5320UA_Boolean
5321UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2) {
5322 if(s1->length != s2->length)
5323 return false;
5324 if(s1->length == 0)
5325 return true;
5326 if(s2->data == NULL)
5327 return false;
5328
5329 //FIXME this currently does not handle UTF8
5330 return UA_strncasecmp(s1: (const char*)s1->data, s2: (const char*)s2->data, n: s1->length) == 0;
5331}
5332
5333static UA_StatusCode
5334String_copy(UA_String const *src, UA_String *dst, const UA_DataType *_) {
5335 UA_StatusCode res =
5336 UA_Array_copy(src: src->data, size: src->length, dst: (void**)&dst->data,
5337 type: &UA_TYPES[UA_TYPES_BYTE]);
5338 if(res == UA_STATUSCODE_GOOD)
5339 dst->length = src->length;
5340 return res;
5341}
5342
5343static void
5344String_clear(UA_String *s, const UA_DataType *_) {
5345 UA_Array_delete(p: s->data, size: s->length, type: &UA_TYPES[UA_TYPES_BYTE]);
5346}
5347
5348/* QualifiedName */
5349static UA_StatusCode
5350QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst,
5351 const UA_DataType *_) {
5352 dst->namespaceIndex = src->namespaceIndex;
5353 return String_copy(src: &src->name, dst: &dst->name, NULL);
5354}
5355
5356static void
5357QualifiedName_clear(UA_QualifiedName *p, const UA_DataType *_) {
5358 String_clear(s: &p->name, NULL);
5359}
5360
5361u32
5362UA_QualifiedName_hash(const UA_QualifiedName *q) {
5363 return UA_ByteString_hash(initialHashValue: q->namespaceIndex,
5364 data: q->name.data, size: q->name.length);
5365}
5366
5367UA_Boolean
5368UA_QualifiedName_equal(const UA_QualifiedName *qn1,
5369 const UA_QualifiedName *qn2) {
5370 return (qualifiedNameOrder(p1: qn1, p2: qn2, NULL) == UA_ORDER_EQ);
5371}
5372
5373/* DateTime */
5374UA_DateTimeStruct
5375UA_DateTime_toStruct(UA_DateTime t) {
5376 /* Divide, then subtract -> avoid underflow. Also, negative numbers are
5377 * rounded up, not down. */
5378 long long secSinceUnixEpoch = (long long)(t / UA_DATETIME_SEC)
5379 - (long long)(UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC);
5380
5381 /* Negative fractions of a second? Remove one full second from the epoch
5382 * distance and allow only a positive fraction. */
5383 UA_DateTime frac = t % UA_DATETIME_SEC;
5384 if(frac < 0) {
5385 secSinceUnixEpoch--;
5386 frac += UA_DATETIME_SEC;
5387 }
5388
5389 struct mytm ts;
5390 memset(s: &ts, c: 0, n: sizeof(struct mytm));
5391 __secs_to_tm(t: secSinceUnixEpoch, tm: &ts);
5392
5393 UA_DateTimeStruct dateTimeStruct;
5394 dateTimeStruct.year = (i16)(ts.tm_year + 1900);
5395 dateTimeStruct.month = (u16)(ts.tm_mon + 1);
5396 dateTimeStruct.day = (u16)ts.tm_mday;
5397 dateTimeStruct.hour = (u16)ts.tm_hour;
5398 dateTimeStruct.min = (u16)ts.tm_min;
5399 dateTimeStruct.sec = (u16)ts.tm_sec;
5400 dateTimeStruct.milliSec = (u16)((frac % 10000000) / 10000);
5401 dateTimeStruct.microSec = (u16)((frac % 10000) / 10);
5402 dateTimeStruct.nanoSec = (u16)((frac % 10) * 100);
5403 return dateTimeStruct;
5404}
5405
5406UA_DateTime
5407UA_DateTime_fromStruct(UA_DateTimeStruct ts) {
5408 /* Seconds since the Unix epoch */
5409 struct mytm tm;
5410 memset(s: &tm, c: 0, n: sizeof(struct mytm));
5411 tm.tm_year = ts.year - 1900;
5412 tm.tm_mon = ts.month - 1;
5413 tm.tm_mday = ts.day;
5414 tm.tm_hour = ts.hour;
5415 tm.tm_min = ts.min;
5416 tm.tm_sec = ts.sec;
5417 long long sec_epoch = __tm_to_secs(tm: &tm);
5418
5419 UA_DateTime t = UA_DATETIME_UNIX_EPOCH;
5420 t += sec_epoch * UA_DATETIME_SEC;
5421 t += ts.milliSec * UA_DATETIME_MSEC;
5422 t += ts.microSec * UA_DATETIME_USEC;
5423 t += ts.nanoSec / 100;
5424 return t;
5425}
5426
5427/* Guid */
5428UA_Boolean
5429UA_Guid_equal(const UA_Guid *g1, const UA_Guid *g2) {
5430 return (guidOrder(p1: g1, p2: g2, NULL) == UA_ORDER_EQ);
5431}
5432
5433UA_Guid
5434UA_Guid_random(void) {
5435 UA_Guid result;
5436 result.data1 = (u32)pcg32_random_r(rng: &UA_rng);
5437 u32 r = (u32)pcg32_random_r(rng: &UA_rng);
5438 result.data2 = (u16) r;
5439 result.data3 = (u16) (r >> 16);
5440 r = (u32)pcg32_random_r(rng: &UA_rng);
5441 result.data4[0] = (u8)r;
5442 result.data4[1] = (u8)(r >> 4);
5443 result.data4[2] = (u8)(r >> 8);
5444 result.data4[3] = (u8)(r >> 12);
5445 r = (u32)pcg32_random_r(rng: &UA_rng);
5446 result.data4[4] = (u8)r;
5447 result.data4[5] = (u8)(r >> 4);
5448 result.data4[6] = (u8)(r >> 8);
5449 result.data4[7] = (u8)(r >> 12);
5450 return result;
5451}
5452
5453/* ByteString */
5454UA_StatusCode
5455UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) {
5456 UA_ByteString_init(p: bs);
5457 if(length == 0)
5458 return UA_STATUSCODE_GOOD;
5459 bs->data = (u8*)UA_malloc(size: length);
5460 if(UA_UNLIKELY(!bs->data))
5461 return UA_STATUSCODE_BADOUTOFMEMORY;
5462 bs->length = length;
5463 return UA_STATUSCODE_GOOD;
5464}
5465
5466/* NodeId */
5467static void
5468NodeId_clear(UA_NodeId *p, const UA_DataType *_) {
5469 switch(p->identifierType) {
5470 case UA_NODEIDTYPE_STRING:
5471 case UA_NODEIDTYPE_BYTESTRING:
5472 String_clear(s: &p->identifier.string, NULL);
5473 break;
5474 default: break;
5475 }
5476}
5477
5478static UA_StatusCode
5479NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_DataType *_) {
5480 UA_StatusCode retval = UA_STATUSCODE_GOOD;
5481 switch(src->identifierType) {
5482 case UA_NODEIDTYPE_NUMERIC:
5483 *dst = *src;
5484 return UA_STATUSCODE_GOOD;
5485 case UA_NODEIDTYPE_STRING:
5486 case UA_NODEIDTYPE_BYTESTRING:
5487 retval |= String_copy(src: &src->identifier.string,
5488 dst: &dst->identifier.string, NULL);
5489 break;
5490 case UA_NODEIDTYPE_GUID:
5491 dst->identifier.guid = src->identifier.guid;
5492 break;
5493 default:
5494 return UA_STATUSCODE_BADINTERNALERROR;
5495 }
5496 dst->namespaceIndex = src->namespaceIndex;
5497 dst->identifierType = src->identifierType;
5498 return retval;
5499}
5500
5501UA_Boolean
5502UA_NodeId_isNull(const UA_NodeId *p) {
5503 if(p->namespaceIndex != 0)
5504 return false;
5505 switch (p->identifierType) {
5506 case UA_NODEIDTYPE_NUMERIC:
5507 return (p->identifier.numeric == 0);
5508 case UA_NODEIDTYPE_STRING:
5509 case UA_NODEIDTYPE_BYTESTRING:
5510 return (p->identifier.string.length == 0); /* Null and empty string */
5511 case UA_NODEIDTYPE_GUID:
5512 return UA_Guid_equal(g1: &p->identifier.guid, g2: &UA_GUID_NULL);
5513 }
5514 return false;
5515}
5516
5517/* Absolute ordering for NodeIds */
5518UA_Order
5519UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2) {
5520 /* Compare namespaceIndex */
5521 if(n1->namespaceIndex != n2->namespaceIndex)
5522 return (n1->namespaceIndex < n2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
5523
5524 /* Compare identifierType */
5525 if(n1->identifierType != n2->identifierType)
5526 return (n1->identifierType < n2->identifierType) ? UA_ORDER_LESS : UA_ORDER_MORE;
5527
5528 /* Compare the identifier */
5529 switch(n1->identifierType) {
5530 case UA_NODEIDTYPE_NUMERIC:
5531 default:
5532 if(n1->identifier.numeric != n2->identifier.numeric)
5533 return (n1->identifier.numeric < n2->identifier.numeric) ?
5534 UA_ORDER_LESS : UA_ORDER_MORE;
5535 return UA_ORDER_EQ;
5536
5537 case UA_NODEIDTYPE_GUID:
5538 return guidOrder(p1: &n1->identifier.guid, p2: &n2->identifier.guid, NULL);
5539
5540 case UA_NODEIDTYPE_STRING:
5541 case UA_NODEIDTYPE_BYTESTRING:
5542 return stringOrder(p1: &n1->identifier.string, p2: &n2->identifier.string, NULL);
5543 }
5544}
5545
5546/* sdbm-hash (http://www.cse.yorku.ca/~oz/hash.html) */
5547u32
5548UA_ByteString_hash(u32 initialHashValue,
5549 const u8 *data, size_t size) {
5550 u32 h = initialHashValue;
5551 for(size_t i = 0; i < size; i++)
5552 h = data[i] + (h << 6) + (h << 16) - h;
5553 return h;
5554}
5555
5556u32
5557UA_NodeId_hash(const UA_NodeId *n) {
5558 switch(n->identifierType) {
5559 case UA_NODEIDTYPE_NUMERIC:
5560 default:
5561 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.numeric,
5562 size: sizeof(UA_UInt32));
5563 case UA_NODEIDTYPE_STRING:
5564 case UA_NODEIDTYPE_BYTESTRING:
5565 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: n->identifier.string.data,
5566 size: n->identifier.string.length);
5567 case UA_NODEIDTYPE_GUID:
5568 return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.guid,
5569 size: sizeof(UA_Guid));
5570 }
5571}
5572
5573/* ExpandedNodeId */
5574static void
5575ExpandedNodeId_clear(UA_ExpandedNodeId *p, const UA_DataType *_) {
5576 NodeId_clear(p: &p->nodeId, _);
5577 String_clear(s: &p->namespaceUri, NULL);
5578}
5579
5580static UA_StatusCode
5581ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst,
5582 const UA_DataType *_) {
5583 UA_StatusCode retval = NodeId_copy(src: &src->nodeId, dst: &dst->nodeId, NULL);
5584 retval |= String_copy(src: &src->namespaceUri, dst: &dst->namespaceUri, NULL);
5585 dst->serverIndex = src->serverIndex;
5586 return retval;
5587}
5588
5589UA_Boolean
5590UA_ExpandedNodeId_isLocal(const UA_ExpandedNodeId *n) {
5591 return (n->namespaceUri.length == 0 && n->serverIndex == 0);
5592}
5593
5594UA_Order
5595UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1,
5596 const UA_ExpandedNodeId *n2) {
5597 if(n1->serverIndex != n2->serverIndex)
5598 return (n1->serverIndex < n2->serverIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
5599 UA_Order o = stringOrder(p1: &n1->namespaceUri, p2: &n2->namespaceUri, NULL);
5600 if(o != UA_ORDER_EQ)
5601 return o;
5602 return UA_NodeId_order(n1: &n1->nodeId, n2: &n2->nodeId);
5603}
5604
5605u32
5606UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n) {
5607 u32 h = UA_NodeId_hash(n: &n->nodeId);
5608 if(n->serverIndex != 0)
5609 h = UA_ByteString_hash(initialHashValue: h, data: (const UA_Byte*)&n->serverIndex, size: 4);
5610 if(n->namespaceUri.length != 0)
5611 h = UA_ByteString_hash(initialHashValue: h, data: n->namespaceUri.data, size: n->namespaceUri.length);
5612 return h;
5613}
5614
5615/* ExtensionObject */
5616static void
5617ExtensionObject_clear(UA_ExtensionObject *p, const UA_DataType *_) {
5618 switch(p->encoding) {
5619 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
5620 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
5621 case UA_EXTENSIONOBJECT_ENCODED_XML:
5622 NodeId_clear(p: &p->content.encoded.typeId, NULL);
5623 String_clear(s: &p->content.encoded.body, NULL);
5624 break;
5625 case UA_EXTENSIONOBJECT_DECODED:
5626 if(p->content.decoded.data)
5627 UA_delete(p: p->content.decoded.data, type: p->content.decoded.type);
5628 break;
5629 default:
5630 break;
5631 }
5632}
5633
5634static UA_StatusCode
5635ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst,
5636 const UA_DataType *_) {
5637 UA_StatusCode retval = UA_STATUSCODE_GOOD;
5638 switch(src->encoding) {
5639 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
5640 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
5641 case UA_EXTENSIONOBJECT_ENCODED_XML:
5642 dst->encoding = src->encoding;
5643 retval = NodeId_copy(src: &src->content.encoded.typeId,
5644 dst: &dst->content.encoded.typeId, NULL);
5645 /* ByteString -> copy as string */
5646 retval |= String_copy(src: &src->content.encoded.body,
5647 dst: &dst->content.encoded.body, NULL);
5648 break;
5649 case UA_EXTENSIONOBJECT_DECODED:
5650 case UA_EXTENSIONOBJECT_DECODED_NODELETE:
5651 if(!src->content.decoded.type || !src->content.decoded.data)
5652 return UA_STATUSCODE_BADINTERNALERROR;
5653 dst->encoding = UA_EXTENSIONOBJECT_DECODED;
5654 dst->content.decoded.type = src->content.decoded.type;
5655 retval = UA_Array_copy(src: src->content.decoded.data, size: 1,
5656 dst: &dst->content.decoded.data, type: src->content.decoded.type);
5657 break;
5658 default:
5659 break;
5660 }
5661 return retval;
5662}
5663
5664void
5665UA_ExtensionObject_setValue(UA_ExtensionObject *eo,
5666 void * UA_RESTRICT p,
5667 const UA_DataType *type) {
5668 UA_ExtensionObject_init(p: eo);
5669 eo->content.decoded.data = p;
5670 eo->content.decoded.type = type;
5671 eo->encoding = UA_EXTENSIONOBJECT_DECODED;
5672}
5673
5674void
5675UA_ExtensionObject_setValueNoDelete(UA_ExtensionObject *eo,
5676 void * UA_RESTRICT p,
5677 const UA_DataType *type) {
5678 UA_ExtensionObject_init(p: eo);
5679 eo->content.decoded.data = p;
5680 eo->content.decoded.type = type;
5681 eo->encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
5682}
5683
5684UA_StatusCode
5685UA_ExtensionObject_setValueCopy(UA_ExtensionObject *eo,
5686 void * UA_RESTRICT p,
5687 const UA_DataType *type) {
5688 UA_ExtensionObject_init(p: eo);
5689
5690 /* Make a copy of the value */
5691 void *val = UA_malloc(size: type->memSize);
5692 if(UA_UNLIKELY(!val))
5693 return UA_STATUSCODE_BADOUTOFMEMORY;
5694 UA_StatusCode res = UA_copy(src: p, dst: val, type);
5695 if(UA_UNLIKELY(res != UA_STATUSCODE_GOOD)) {
5696 UA_free(ptr: val);
5697 return res;
5698 }
5699
5700 /* Set the ExtensionObject */
5701 eo->content.decoded.data = val;
5702 eo->content.decoded.type = type;
5703 eo->encoding = UA_EXTENSIONOBJECT_DECODED;
5704 return UA_STATUSCODE_GOOD;
5705}
5706
5707/* Variant */
5708static void
5709Variant_clear(UA_Variant *p, const UA_DataType *_) {
5710 /* The content is "borrowed" */
5711 if(p->storageType == UA_VARIANT_DATA_NODELETE)
5712 return;
5713
5714 /* Delete the value */
5715 if(p->type && p->data > UA_EMPTY_ARRAY_SENTINEL) {
5716 if(p->arrayLength == 0)
5717 p->arrayLength = 1;
5718 UA_Array_delete(p: p->data, size: p->arrayLength, type: p->type);
5719 p->data = NULL;
5720 }
5721
5722 /* Delete the array dimensions */
5723 if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL)
5724 UA_free(ptr: p->arrayDimensions);
5725}
5726
5727static UA_StatusCode
5728Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) {
5729 size_t length = src->arrayLength;
5730 if(UA_Variant_isScalar(v: src))
5731 length = 1;
5732 UA_StatusCode retval = UA_Array_copy(src: src->data, size: length,
5733 dst: &dst->data, type: src->type);
5734 if(retval != UA_STATUSCODE_GOOD)
5735 return retval;
5736 dst->arrayLength = src->arrayLength;
5737 dst->type = src->type;
5738 if(src->arrayDimensions) {
5739 retval = UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize,
5740 dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]);
5741 if(retval != UA_STATUSCODE_GOOD)
5742 return retval;
5743 dst->arrayDimensionsSize = src->arrayDimensionsSize;
5744 }
5745 return UA_STATUSCODE_GOOD;
5746}
5747
5748void
5749UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p,
5750 const UA_DataType *type) {
5751 UA_Variant_init(p: v);
5752 v->type = type;
5753 v->arrayLength = 0;
5754 v->data = p;
5755}
5756
5757UA_StatusCode
5758UA_Variant_setScalarCopy(UA_Variant *v, const void * UA_RESTRICT p,
5759 const UA_DataType *type) {
5760 void *n = UA_malloc(size: type->memSize);
5761 if(UA_UNLIKELY(!n))
5762 return UA_STATUSCODE_BADOUTOFMEMORY;
5763 UA_StatusCode retval = UA_copy(src: p, dst: n, type);
5764 if(UA_UNLIKELY(retval != UA_STATUSCODE_GOOD)) {
5765 UA_free(ptr: n);
5766 //cppcheck-suppress memleak
5767 return retval;
5768 }
5769 UA_Variant_setScalar(v, p: n, type);
5770 //cppcheck-suppress memleak
5771 return UA_STATUSCODE_GOOD;
5772}
5773
5774void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array,
5775 size_t arraySize, const UA_DataType *type) {
5776 UA_Variant_init(p: v);
5777 v->data = array;
5778 v->arrayLength = arraySize;
5779 v->type = type;
5780}
5781
5782UA_StatusCode
5783UA_Variant_setArrayCopy(UA_Variant *v, const void * UA_RESTRICT array,
5784 size_t arraySize, const UA_DataType *type) {
5785 UA_Variant_init(p: v);
5786 UA_StatusCode retval = UA_Array_copy(src: array, size: arraySize, dst: &v->data, type);
5787 if(retval != UA_STATUSCODE_GOOD)
5788 return retval;
5789 v->arrayLength = arraySize;
5790 v->type = type;
5791 return UA_STATUSCODE_GOOD;
5792}
5793
5794/* Test if a range is compatible with a variant. This may adjust the upper bound
5795 * (max) in order to fit the variant. */
5796static UA_StatusCode
5797checkAdjustRange(const UA_Variant *v, UA_NumericRange *range) {
5798 /* Test for max array size (64bit only) */
5799#if (SIZE_MAX > 0xffffffff)
5800 if(v->arrayLength > UA_UINT32_MAX)
5801 return UA_STATUSCODE_BADINTERNALERROR;
5802#endif
5803 u32 arrayLength = (u32)v->arrayLength;
5804
5805 /* Assume one array dimension if none defined */
5806 const u32 *dims = v->arrayDimensions;
5807 size_t dims_count = v->arrayDimensionsSize;
5808 if(v->arrayDimensionsSize == 0) {
5809 dims_count = 1;
5810 dims = &arrayLength;
5811 }
5812
5813 /* Does the range match the dimension of the variant? */
5814 if(range->dimensionsSize != dims_count)
5815 return UA_STATUSCODE_BADINDEXRANGENODATA;
5816
5817 /* Check that the number of elements in the variant matches the array
5818 * dimensions */
5819 size_t elements = 1;
5820 for(size_t i = 0; i < dims_count; ++i)
5821 elements *= dims[i];
5822 if(elements != v->arrayLength)
5823 return UA_STATUSCODE_BADINTERNALERROR;
5824
5825 /* Test the integrity of the range and compute the max index used for every
5826 * dimension. The standard says in Part 4, Section 7.22:
5827 *
5828 * When reading a value, the indexes may not specify a range that is within
5829 * the bounds of the array. The Server shall return a partial result if some
5830 * elements exist within the range. */
5831 for(size_t i = 0; i < dims_count; ++i) {
5832 if(range->dimensions[i].min > range->dimensions[i].max)
5833 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5834 if(range->dimensions[i].min >= dims[i])
5835 return UA_STATUSCODE_BADINDEXRANGENODATA;
5836
5837 /* Reduce the max to fit the variant */
5838 if(range->dimensions[i].max >= dims[i])
5839 range->dimensions[i].max = dims[i] - 1;
5840 }
5841
5842 return UA_STATUSCODE_GOOD;
5843}
5844
5845/* Computes the stride for copying the range elements.
5846 * - total: how many elements are in the range
5847 * - block: how big is each contiguous block of elements in the variant that
5848 * maps into the range
5849 * - stride: how many elements are between the blocks (beginning to beginning)
5850 * - first: where does the first block begin */
5851static void
5852computeStrides(const UA_Variant *v, const UA_NumericRange range,
5853 size_t *total, size_t *block, size_t *stride, size_t *first) {
5854 /* Number of total elements to be copied */
5855 size_t count = 1;
5856 for(size_t i = 0; i < range.dimensionsSize; ++i)
5857 count *= (range.dimensions[i].max - range.dimensions[i].min) + 1;
5858 *total = count;
5859
5860 /* Assume one array dimension if none defined */
5861 u32 arrayLength = (u32)v->arrayLength;
5862 const u32 *dims = v->arrayDimensions;
5863 size_t dims_count = v->arrayDimensionsSize;
5864 if(v->arrayDimensionsSize == 0) {
5865 dims_count = 1;
5866 dims = &arrayLength;
5867 }
5868
5869 /* Compute the stride length and the position of the first element */
5870 *block = count; /* Assume the range describes the entire array. */
5871 *stride = v->arrayLength; /* So it can be copied as a contiguous block. */
5872 *first = 0;
5873 size_t running_dimssize = 1;
5874 UA_Boolean found_contiguous = false;
5875 for(size_t k = dims_count; k > 0;) {
5876 --k;
5877 size_t dimrange = 1 + range.dimensions[k].max - range.dimensions[k].min;
5878 if(!found_contiguous && dimrange != dims[k]) {
5879 /* Found the maximum block that can be copied contiguously */
5880 found_contiguous = true;
5881 *block = running_dimssize * dimrange;
5882 *stride = running_dimssize * dims[k];
5883 }
5884 *first += running_dimssize * range.dimensions[k].min;
5885 running_dimssize *= dims[k];
5886 }
5887}
5888
5889/* Is the type string-like? */
5890static UA_Boolean
5891isStringLike(const UA_DataType *type) {
5892 if(type == &UA_TYPES[UA_TYPES_STRING] ||
5893 type == &UA_TYPES[UA_TYPES_BYTESTRING] ||
5894 type == &UA_TYPES[UA_TYPES_XMLELEMENT])
5895 return true;
5896 return false;
5897}
5898
5899/* Returns the part of the string that lies within the rangedimension */
5900static UA_StatusCode
5901copySubString(const UA_String *src, UA_String *dst,
5902 const UA_NumericRangeDimension *dim) {
5903 if(dim->min > dim->max)
5904 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5905 if(dim->min >= src->length)
5906 return UA_STATUSCODE_BADINDEXRANGENODATA;
5907
5908 size_t length;
5909 if(dim->max < src->length)
5910 length = dim->max - dim->min + 1;
5911 else
5912 length = src->length - dim->min;
5913
5914 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: dst, length);
5915 if(retval != UA_STATUSCODE_GOOD)
5916 return retval;
5917
5918 memcpy(dest: dst->data, src: &src->data[dim->min], n: length);
5919 return UA_STATUSCODE_GOOD;
5920}
5921
5922UA_StatusCode
5923UA_Variant_copyRange(const UA_Variant *src, UA_Variant * UA_RESTRICT dst,
5924 const UA_NumericRange range) {
5925 if(!src->type)
5926 return UA_STATUSCODE_BADINVALIDARGUMENT;
5927
5928 UA_Boolean isScalar = UA_Variant_isScalar(v: src);
5929 UA_Boolean stringLike = isStringLike(type: src->type);
5930
5931 /* Upper bound of the dimensions for stack-allocation */
5932 if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
5933 return UA_STATUSCODE_BADINTERNALERROR;
5934
5935 /* Copy the const range to a mutable stack location */
5936 UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
5937 memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
5938 UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
5939
5940 UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */
5941 UA_NumericRange nextrange = {0, NULL};
5942
5943 /* Extract the range for copying at this level. The remaining range is dealt
5944 * with in the "scalar" type that may define an array by itself (string,
5945 * variant, ...). */
5946 UA_Variant arraySrc;
5947 if(isScalar) {
5948 /* Replace scalar src with array of length 1 */
5949 arraySrc = *src;
5950 arraySrc.arrayLength = 1;
5951 src = &arraySrc;
5952 /* Deal with all range dimensions within the scalar */
5953 thisrange.dimensions = &scalarThisDimension;
5954 thisrange.dimensionsSize = 1;
5955 nextrange = range;
5956 } else {
5957 /* Deal with as many range dimensions as possible right now */
5958 size_t dims = src->arrayDimensionsSize;
5959 if(dims == 0)
5960 dims = 1;
5961 if(dims > range.dimensionsSize)
5962 return UA_STATUSCODE_BADINDEXRANGEINVALID;
5963 thisrange.dimensionsSize = dims;
5964 nextrange.dimensions = &range.dimensions[dims];
5965 nextrange.dimensionsSize = range.dimensionsSize - dims;
5966 }
5967
5968 UA_StatusCode retval = checkAdjustRange(v: src, range: &thisrange);
5969 if(retval != UA_STATUSCODE_GOOD)
5970 return retval;
5971
5972 /* Compute the strides */
5973 size_t count, block, stride, first;
5974 computeStrides(v: src, range: thisrange, total: &count, block: &block, stride: &stride, first: &first);
5975
5976 /* Allocate the array */
5977 UA_Variant_init(p: dst);
5978 dst->data = UA_Array_new(size: count, type: src->type);
5979 if(!dst->data)
5980 return UA_STATUSCODE_BADOUTOFMEMORY;
5981
5982 /* Copy the range */
5983 size_t block_count = count / block;
5984 size_t elem_size = src->type->memSize;
5985 uintptr_t nextdst = (uintptr_t)dst->data;
5986 uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first);
5987 if(nextrange.dimensionsSize == 0) {
5988 /* no nextrange */
5989 if(src->type->pointerFree) {
5990 for(size_t i = 0; i < block_count; ++i) {
5991 memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block);
5992 nextdst += block * elem_size;
5993 nextsrc += stride * elem_size;
5994 }
5995 } else {
5996 for(size_t i = 0; i < block_count; ++i) {
5997 for(size_t j = 0; j < block; ++j) {
5998 retval = UA_copy(src: (const void*)nextsrc,
5999 dst: (void*)nextdst, type: src->type);
6000 nextdst += elem_size;
6001 nextsrc += elem_size;
6002 }
6003 nextsrc += (stride - block) * elem_size;
6004 }
6005 }
6006 } else {
6007 /* nextrange can only be used for variants and stringlike with remaining
6008 * range of dimension 1 */
6009 if(src->type != &UA_TYPES[UA_TYPES_VARIANT]) {
6010 if(!stringLike)
6011 retval = UA_STATUSCODE_BADINDEXRANGENODATA;
6012 if(nextrange.dimensionsSize != 1)
6013 retval = UA_STATUSCODE_BADINDEXRANGENODATA;
6014 }
6015
6016 /* Copy the content */
6017 for(size_t i = 0; i < block_count; ++i) {
6018 for(size_t j = 0; j < block && retval == UA_STATUSCODE_GOOD; ++j) {
6019 if(stringLike)
6020 retval = copySubString(src: (const UA_String*)nextsrc,
6021 dst: (UA_String*)nextdst,
6022 dim: nextrange.dimensions);
6023 else
6024 retval = UA_Variant_copyRange(src: (const UA_Variant*)nextsrc,
6025 dst: (UA_Variant*)nextdst,
6026 range: nextrange);
6027 nextdst += elem_size;
6028 nextsrc += elem_size;
6029 }
6030 nextsrc += (stride - block) * elem_size;
6031 }
6032 }
6033
6034 /* Clean up if copying failed */
6035 if(retval != UA_STATUSCODE_GOOD) {
6036 UA_Array_delete(p: dst->data, size: count, type: src->type);
6037 dst->data = NULL;
6038 return retval;
6039 }
6040
6041 /* Done if scalar */
6042 dst->type = src->type;
6043 if(isScalar)
6044 return retval;
6045
6046 /* Copy array dimensions */
6047 dst->arrayLength = count;
6048 if(src->arrayDimensionsSize > 0) {
6049 dst->arrayDimensions =
6050 (u32*)UA_Array_new(size: thisrange.dimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
6051 if(!dst->arrayDimensions) {
6052 Variant_clear(p: dst, NULL);
6053 return UA_STATUSCODE_BADOUTOFMEMORY;
6054 }
6055 dst->arrayDimensionsSize = thisrange.dimensionsSize;
6056 for(size_t k = 0; k < thisrange.dimensionsSize; ++k)
6057 dst->arrayDimensions[k] =
6058 thisrange.dimensions[k].max - thisrange.dimensions[k].min + 1;
6059 }
6060 return UA_STATUSCODE_GOOD;
6061}
6062
6063/* TODO: Allow ranges to reach inside a scalars that are array-like, e.g.
6064 * variant and strings. This is already possible for reading... */
6065static UA_StatusCode
6066Variant_setRange(UA_Variant *v, void *array, size_t arraySize,
6067 const UA_NumericRange range, UA_Boolean copy) {
6068 if(!v->type)
6069 return UA_STATUSCODE_BADINVALIDARGUMENT;
6070
6071 /* Upper bound of the dimensions for stack-allocation */
6072 if(range.dimensionsSize > UA_MAX_ARRAY_DIMS)
6073 return UA_STATUSCODE_BADINTERNALERROR;
6074
6075 /* Copy the const range to a mutable stack location */
6076 UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS];
6077 memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize);
6078 UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims};
6079
6080 UA_StatusCode retval = checkAdjustRange(v, range: &thisrange);
6081 if(retval != UA_STATUSCODE_GOOD)
6082 return retval;
6083
6084 /* Compute the strides */
6085 size_t count, block, stride, first;
6086 computeStrides(v, range, total: &count, block: &block, stride: &stride, first: &first);
6087 if(count != arraySize)
6088 return UA_STATUSCODE_BADINDEXRANGEINVALID;
6089
6090 /* Move/copy the elements */
6091 size_t block_count = count / block;
6092 size_t elem_size = v->type->memSize;
6093 uintptr_t nextdst = (uintptr_t)v->data + (first * elem_size);
6094 uintptr_t nextsrc = (uintptr_t)array;
6095 if(v->type->pointerFree || !copy) {
6096 for(size_t i = 0; i < block_count; ++i) {
6097 memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block);
6098 nextsrc += block * elem_size;
6099 nextdst += stride * elem_size;
6100 }
6101 } else {
6102 for(size_t i = 0; i < block_count; ++i) {
6103 for(size_t j = 0; j < block; ++j) {
6104 clearJumpTable[v->type->typeKind]((void*)nextdst, v->type);
6105 retval |= UA_copy(src: (void*)nextsrc, dst: (void*)nextdst, type: v->type);
6106 nextdst += elem_size;
6107 nextsrc += elem_size;
6108 }
6109 nextdst += (stride - block) * elem_size;
6110 }
6111 }
6112
6113 /* If members were moved, initialize original array to prevent reuse */
6114 if(!copy && !v->type->pointerFree)
6115 memset(s: array, c: 0, n: sizeof(elem_size)*arraySize);
6116
6117 return retval;
6118}
6119
6120UA_StatusCode
6121UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array,
6122 size_t arraySize, const UA_NumericRange range) {
6123 return Variant_setRange(v, array, arraySize, range, false);
6124}
6125
6126UA_StatusCode
6127UA_Variant_setRangeCopy(UA_Variant *v, const void * UA_RESTRICT array,
6128 size_t arraySize, const UA_NumericRange range) {
6129 return Variant_setRange(v, array: (void*)(uintptr_t)array,
6130 arraySize, range, true);
6131}
6132
6133/* LocalizedText */
6134static void
6135LocalizedText_clear(UA_LocalizedText *p, const UA_DataType *_) {
6136 String_clear(s: &p->locale, NULL);
6137 String_clear(s: &p->text, NULL);
6138}
6139
6140static UA_StatusCode
6141LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst,
6142 const UA_DataType *_) {
6143 UA_StatusCode retval = String_copy(src: &src->locale, dst: &dst->locale, NULL);
6144 retval |= String_copy(src: &src->text, dst: &dst->text, NULL);
6145 return retval;
6146}
6147
6148/* DataValue */
6149static void
6150DataValue_clear(UA_DataValue *p, const UA_DataType *_) {
6151 Variant_clear(p: &p->value, NULL);
6152}
6153
6154static UA_StatusCode
6155DataValue_copy(UA_DataValue const *src, UA_DataValue *dst,
6156 const UA_DataType *_) {
6157 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
6158 UA_Variant_init(p: &dst->value);
6159 UA_StatusCode retval = Variant_copy(src: &src->value, dst: &dst->value, NULL);
6160 if(retval != UA_STATUSCODE_GOOD)
6161 DataValue_clear(p: dst, NULL);
6162 return retval;
6163}
6164
6165UA_StatusCode
6166UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst,
6167 const UA_NumericRange range) {
6168 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
6169 UA_Variant_init(p: &dst->value);
6170 UA_StatusCode retval = UA_Variant_copyRange(src: &src->value, dst: &dst->value, range);
6171 if(retval != UA_STATUSCODE_GOOD)
6172 DataValue_clear(p: dst, NULL);
6173 return retval;
6174}
6175
6176/* DiagnosticInfo */
6177static void
6178DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) {
6179 String_clear(s: &p->additionalInfo, NULL);
6180 if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) {
6181 DiagnosticInfo_clear(p: p->innerDiagnosticInfo, NULL);
6182 UA_free(ptr: p->innerDiagnosticInfo);
6183 }
6184}
6185
6186static UA_StatusCode
6187DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst,
6188 const UA_DataType *_) {
6189 memcpy(dest: dst, src: src, n: sizeof(UA_DiagnosticInfo));
6190 UA_String_init(p: &dst->additionalInfo);
6191 dst->innerDiagnosticInfo = NULL;
6192 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6193 if(src->hasAdditionalInfo)
6194 retval = String_copy(src: &src->additionalInfo, dst: &dst->additionalInfo, NULL);
6195 if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) {
6196 dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
6197 UA_malloc(size: sizeof(UA_DiagnosticInfo));
6198 if(UA_LIKELY(dst->innerDiagnosticInfo != NULL)) {
6199 retval |= DiagnosticInfo_copy(src: src->innerDiagnosticInfo,
6200 dst: dst->innerDiagnosticInfo, NULL);
6201 dst->hasInnerDiagnosticInfo = true;
6202 } else {
6203 dst->hasInnerDiagnosticInfo = false;
6204 retval |= UA_STATUSCODE_BADOUTOFMEMORY;
6205 }
6206 }
6207 return retval;
6208}
6209
6210/********************/
6211/* Structured Types */
6212/********************/
6213
6214void *
6215UA_new(const UA_DataType *type) {
6216 void *p = UA_calloc(nmemb: 1, size: type->memSize);
6217 return p;
6218}
6219
6220static UA_StatusCode
6221copyByte(const u8 *src, u8 *dst, const UA_DataType *_) {
6222 *dst = *src;
6223 return UA_STATUSCODE_GOOD;
6224}
6225
6226static UA_StatusCode
6227copy2Byte(const u16 *src, u16 *dst, const UA_DataType *_) {
6228 *dst = *src;
6229 return UA_STATUSCODE_GOOD;
6230}
6231
6232static UA_StatusCode
6233copy4Byte(const u32 *src, u32 *dst, const UA_DataType *_) {
6234 *dst = *src;
6235 return UA_STATUSCODE_GOOD;
6236}
6237
6238static UA_StatusCode
6239copy8Byte(const u64 *src, u64 *dst, const UA_DataType *_) {
6240 *dst = *src;
6241 return UA_STATUSCODE_GOOD;
6242}
6243
6244static UA_StatusCode
6245copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) {
6246 *dst = *src;
6247 return UA_STATUSCODE_GOOD;
6248}
6249
6250static UA_StatusCode
6251copyStructure(const void *src, void *dst, const UA_DataType *type) {
6252 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6253 uintptr_t ptrs = (uintptr_t)src;
6254 uintptr_t ptrd = (uintptr_t)dst;
6255 for(size_t i = 0; i < type->membersSize; ++i) {
6256 const UA_DataTypeMember *m = &type->members[i];
6257 const UA_DataType *mt = m->memberType;
6258 ptrs += m->padding;
6259 ptrd += m->padding;
6260 if(!m->isOptional) {
6261 if(!m->isArray) {
6262 retval |= copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt);
6263 ptrs += mt->memSize;
6264 ptrd += mt->memSize;
6265 } else {
6266 size_t *dst_size = (size_t*)ptrd;
6267 const size_t size = *((const size_t*)ptrs);
6268 ptrs += sizeof(size_t);
6269 ptrd += sizeof(size_t);
6270 retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6271 if(retval == UA_STATUSCODE_GOOD)
6272 *dst_size = size;
6273 else
6274 *dst_size = 0;
6275 ptrs += sizeof(void*);
6276 ptrd += sizeof(void*);
6277 }
6278 } else {
6279 if(!m->isArray) {
6280 if(*(void* const*)ptrs != NULL)
6281 retval |= UA_Array_copy(src: *(void* const*)ptrs, size: 1, dst: (void**)ptrd, type: mt);
6282 } else {
6283 if(*(void* const*)(ptrs+sizeof(size_t)) != NULL) {
6284 size_t *dst_size = (size_t*)ptrd;
6285 const size_t size = *((const size_t*)ptrs);
6286 ptrs += sizeof(size_t);
6287 ptrd += sizeof(size_t);
6288 retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6289 if(retval == UA_STATUSCODE_GOOD)
6290 *dst_size = size;
6291 else
6292 *dst_size = 0;
6293 } else {
6294 ptrs += sizeof(size_t);
6295 ptrd += sizeof(size_t);
6296 }
6297 }
6298 ptrs += sizeof(void*);
6299 ptrd += sizeof(void*);
6300 }
6301 }
6302 return retval;
6303}
6304
6305static UA_StatusCode
6306copyUnion(const void *src, void *dst, const UA_DataType *type) {
6307 uintptr_t ptrs = (uintptr_t) src;
6308 uintptr_t ptrd = (uintptr_t) dst;
6309 UA_UInt32 selection = *(UA_UInt32 *)ptrs;
6310 UA_copy(src: (const UA_UInt32 *) ptrs, dst: (UA_UInt32 *) ptrd, type: &UA_TYPES[UA_TYPES_UINT32]);
6311 if(selection == 0)
6312 return UA_STATUSCODE_GOOD;
6313 const UA_DataTypeMember *m = &type->members[selection-1];
6314 const UA_DataType *mt = m->memberType;
6315 ptrs += m->padding;
6316 ptrd += m->padding;
6317
6318 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6319
6320 if (m->isArray) {
6321 size_t *dst_size = (size_t*)ptrd;
6322 const size_t size = *((const size_t*)ptrs);
6323 ptrs += sizeof(size_t);
6324 ptrd += sizeof(size_t);
6325 retval = UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt);
6326 if(retval == UA_STATUSCODE_GOOD)
6327 *dst_size = size;
6328 else
6329 *dst_size = 0;
6330 } else {
6331 retval = copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt);
6332 }
6333
6334 return retval;
6335}
6336
6337static UA_StatusCode
6338copyNotImplemented(const void *src, void *dst, const UA_DataType *type) {
6339 return UA_STATUSCODE_BADNOTIMPLEMENTED;
6340}
6341
6342const UA_copySignature copyJumpTable[UA_DATATYPEKINDS] = {
6343 (UA_copySignature)copyByte, /* Boolean */
6344 (UA_copySignature)copyByte, /* SByte */
6345 (UA_copySignature)copyByte, /* Byte */
6346 (UA_copySignature)copy2Byte, /* Int16 */
6347 (UA_copySignature)copy2Byte, /* UInt16 */
6348 (UA_copySignature)copy4Byte, /* Int32 */
6349 (UA_copySignature)copy4Byte, /* UInt32 */
6350 (UA_copySignature)copy8Byte, /* Int64 */
6351 (UA_copySignature)copy8Byte, /* UInt64 */
6352 (UA_copySignature)copy4Byte, /* Float */
6353 (UA_copySignature)copy8Byte, /* Double */
6354 (UA_copySignature)String_copy,
6355 (UA_copySignature)copy8Byte, /* DateTime */
6356 (UA_copySignature)copyGuid, /* Guid */
6357 (UA_copySignature)String_copy, /* ByteString */
6358 (UA_copySignature)String_copy, /* XmlElement */
6359 (UA_copySignature)NodeId_copy,
6360 (UA_copySignature)ExpandedNodeId_copy,
6361 (UA_copySignature)copy4Byte, /* StatusCode */
6362 (UA_copySignature)QualifiedName_copy,
6363 (UA_copySignature)LocalizedText_copy,
6364 (UA_copySignature)ExtensionObject_copy,
6365 (UA_copySignature)DataValue_copy,
6366 (UA_copySignature)Variant_copy,
6367 (UA_copySignature)DiagnosticInfo_copy,
6368 (UA_copySignature)copyNotImplemented, /* Decimal */
6369 (UA_copySignature)copy4Byte, /* Enumeration */
6370 (UA_copySignature)copyStructure,
6371 (UA_copySignature)copyStructure, /* Structure with Optional Fields */
6372 (UA_copySignature)copyUnion, /* Union */
6373 (UA_copySignature)copyNotImplemented /* BitfieldCluster*/
6374};
6375
6376UA_StatusCode
6377UA_copy(const void *src, void *dst, const UA_DataType *type) {
6378 memset(s: dst, c: 0, n: type->memSize); /* init */
6379 UA_StatusCode retval = copyJumpTable[type->typeKind](src, dst, type);
6380 if(retval != UA_STATUSCODE_GOOD)
6381 UA_clear(p: dst, type);
6382 return retval;
6383}
6384
6385static void
6386clearStructure(void *p, const UA_DataType *type) {
6387 uintptr_t ptr = (uintptr_t)p;
6388 for(size_t i = 0; i < type->membersSize; ++i) {
6389 const UA_DataTypeMember *m = &type->members[i];
6390 const UA_DataType *mt = m->memberType;
6391 ptr += m->padding;
6392 if(!m->isOptional) {
6393 if(!m->isArray) {
6394 clearJumpTable[mt->typeKind]((void*)ptr, mt);
6395 ptr += mt->memSize;
6396 } else {
6397 size_t length = *(size_t*)ptr;
6398 ptr += sizeof(size_t);
6399 UA_Array_delete(p: *(void**)ptr, size: length, type: mt);
6400 ptr += sizeof(void*);
6401 }
6402 } else { /* field is optional */
6403 if(!m->isArray) {
6404 /* optional scalar field is contained */
6405 if((*(void *const *)ptr != NULL))
6406 UA_Array_delete(p: *(void **)ptr, size: 1, type: mt);
6407 ptr += sizeof(void *);
6408 } else {
6409 /* optional array field is contained */
6410 if((*(void *const *)(ptr + sizeof(size_t)) != NULL)) {
6411 size_t length = *(size_t *)ptr;
6412 ptr += sizeof(size_t);
6413 UA_Array_delete(p: *(void **)ptr, size: length, type: mt);
6414 ptr += sizeof(void *);
6415 } else { /* optional array field not contained */
6416 ptr += sizeof(size_t);
6417 ptr += sizeof(void *);
6418 }
6419 }
6420 }
6421 }
6422}
6423
6424static void
6425clearUnion(void *p, const UA_DataType *type) {
6426 uintptr_t ptr = (uintptr_t) p;
6427 UA_UInt32 selection = *(UA_UInt32 *)ptr;
6428 if(selection == 0)
6429 return;
6430 const UA_DataTypeMember *m = &type->members[selection-1];
6431 const UA_DataType *mt = m->memberType;
6432 ptr += m->padding;
6433 if (m->isArray) {
6434 size_t length = *(size_t *)ptr;
6435 ptr += sizeof(size_t);
6436 UA_Array_delete(p: *(void **)ptr, size: length, type: mt);
6437 } else {
6438 UA_clear(p: (void *) ptr, type: mt);
6439 }
6440}
6441
6442static void nopClear(void *p, const UA_DataType *type) { }
6443
6444const
6445UA_clearSignature clearJumpTable[UA_DATATYPEKINDS] = {
6446 (UA_clearSignature)nopClear, /* Boolean */
6447 (UA_clearSignature)nopClear, /* SByte */
6448 (UA_clearSignature)nopClear, /* Byte */
6449 (UA_clearSignature)nopClear, /* Int16 */
6450 (UA_clearSignature)nopClear, /* UInt16 */
6451 (UA_clearSignature)nopClear, /* Int32 */
6452 (UA_clearSignature)nopClear, /* UInt32 */
6453 (UA_clearSignature)nopClear, /* Int64 */
6454 (UA_clearSignature)nopClear, /* UInt64 */
6455 (UA_clearSignature)nopClear, /* Float */
6456 (UA_clearSignature)nopClear, /* Double */
6457 (UA_clearSignature)String_clear, /* String */
6458 (UA_clearSignature)nopClear, /* DateTime */
6459 (UA_clearSignature)nopClear, /* Guid */
6460 (UA_clearSignature)String_clear, /* ByteString */
6461 (UA_clearSignature)String_clear, /* XmlElement */
6462 (UA_clearSignature)NodeId_clear,
6463 (UA_clearSignature)ExpandedNodeId_clear,
6464 (UA_clearSignature)nopClear, /* StatusCode */
6465 (UA_clearSignature)QualifiedName_clear,
6466 (UA_clearSignature)LocalizedText_clear,
6467 (UA_clearSignature)ExtensionObject_clear,
6468 (UA_clearSignature)DataValue_clear,
6469 (UA_clearSignature)Variant_clear,
6470 (UA_clearSignature)DiagnosticInfo_clear,
6471 (UA_clearSignature)nopClear, /* Decimal, not implemented */
6472 (UA_clearSignature)nopClear, /* Enumeration */
6473 (UA_clearSignature)clearStructure,
6474 (UA_clearSignature)clearStructure, /* Struct with Optional Fields*/
6475 (UA_clearSignature)clearUnion, /* Union*/
6476 (UA_clearSignature)nopClear /* BitfieldCluster, not implemented*/
6477};
6478
6479void
6480UA_clear(void *p, const UA_DataType *type) {
6481 clearJumpTable[type->typeKind](p, type);
6482 memset(s: p, c: 0, n: type->memSize); /* init */
6483}
6484
6485void
6486UA_delete(void *p, const UA_DataType *type) {
6487 clearJumpTable[type->typeKind](p, type);
6488 UA_free(ptr: p);
6489}
6490
6491/******************/
6492/* Value Ordering */
6493/******************/
6494
6495#define UA_NUMERICORDER(NAME, TYPE) \
6496 static UA_Order \
6497 NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
6498 if(*p1 != *p2) \
6499 return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
6500 return UA_ORDER_EQ; \
6501 }
6502
6503UA_NUMERICORDER(booleanOrder, UA_Boolean)
6504UA_NUMERICORDER(sByteOrder, UA_SByte)
6505UA_NUMERICORDER(byteOrder, UA_Byte)
6506UA_NUMERICORDER(int16Order, UA_Int16)
6507UA_NUMERICORDER(uInt16Order, UA_UInt16)
6508UA_NUMERICORDER(int32Order, UA_Int32)
6509UA_NUMERICORDER(uInt32Order, UA_UInt32)
6510UA_NUMERICORDER(int64Order, UA_Int64)
6511UA_NUMERICORDER(uInt64Order, UA_UInt64)
6512
6513#define UA_FLOATORDER(NAME, TYPE) \
6514 static UA_Order \
6515 NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \
6516 if(*p1 != *p2) { \
6517 /* p1 is NaN */ \
6518 if(*p1 != *p1) { \
6519 if(*p2 != *p2) \
6520 return UA_ORDER_EQ; \
6521 return UA_ORDER_LESS; \
6522 } \
6523 /* p2 is NaN */ \
6524 if(*p2 != *p2) \
6525 return UA_ORDER_MORE; \
6526 return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \
6527 } \
6528 return UA_ORDER_EQ; \
6529 }
6530
6531UA_FLOATORDER(floatOrder, UA_Float)
6532UA_FLOATORDER(doubleOrder, UA_Double)
6533
6534static UA_Order
6535guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type) {
6536 if(p1->data1 != p2->data1)
6537 return (p1->data1 < p2->data1) ? UA_ORDER_LESS : UA_ORDER_MORE;
6538 if(p1->data2 != p2->data2)
6539 return (p1->data2 < p2->data2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6540 if(p1->data3 != p2->data3)
6541 return (p1->data3 < p2->data3) ? UA_ORDER_LESS : UA_ORDER_MORE;
6542 int cmp = memcmp(s1: p1->data4, s2: p2->data4, n: 8);
6543 if(cmp != 0)
6544 return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
6545 return UA_ORDER_EQ;
6546}
6547
6548static UA_Order
6549stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type) {
6550 if(p1->length != p2->length)
6551 return (p1->length < p2->length) ? UA_ORDER_LESS : UA_ORDER_MORE;
6552 /* For zero-length arrays, every pointer not NULL is considered a
6553 * UA_EMPTY_ARRAY_SENTINEL. */
6554 if(p1->data == p2->data) return UA_ORDER_EQ;
6555 if(p1->data == NULL) return UA_ORDER_LESS;
6556 if(p2->data == NULL) return UA_ORDER_MORE;
6557 int cmp = memcmp(s1: (const char*)p1->data, s2: (const char*)p2->data, n: p1->length);
6558 if(cmp != 0)
6559 return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE;
6560 return UA_ORDER_EQ;
6561}
6562
6563static UA_Order
6564nodeIdOrder(const UA_NodeId *p1, const UA_NodeId *p2, const UA_DataType *type) {
6565 return UA_NodeId_order(n1: p1, n2: p2);
6566}
6567
6568static UA_Order
6569expandedNodeIdOrder(const UA_ExpandedNodeId *p1, const UA_ExpandedNodeId *p2,
6570 const UA_DataType *type) {
6571 return UA_ExpandedNodeId_order(n1: p1, n2: p2);
6572}
6573
6574static UA_Order
6575qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2,
6576 const UA_DataType *type) {
6577 if(p1->namespaceIndex != p2->namespaceIndex)
6578 return (p1->namespaceIndex < p2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE;
6579 return stringOrder(p1: &p1->name, p2: &p2->name, NULL);
6580}
6581
6582static UA_Order
6583localizedTextOrder(const UA_LocalizedText *p1, const UA_LocalizedText *p2,
6584 const UA_DataType *type) {
6585 UA_Order o = stringOrder(p1: &p1->locale, p2: &p2->locale, NULL);
6586 if(o != UA_ORDER_EQ)
6587 return o;
6588 return stringOrder(p1: &p1->text, p2: &p2->text, NULL);
6589}
6590
6591static UA_Order
6592extensionObjectOrder(const UA_ExtensionObject *p1, const UA_ExtensionObject *p2,
6593 const UA_DataType *type) {
6594 UA_ExtensionObjectEncoding enc1 = p1->encoding;
6595 UA_ExtensionObjectEncoding enc2 = p2->encoding;
6596 if(enc1 > UA_EXTENSIONOBJECT_DECODED)
6597 enc1 = UA_EXTENSIONOBJECT_DECODED;
6598 if(enc2 > UA_EXTENSIONOBJECT_DECODED)
6599 enc2 = UA_EXTENSIONOBJECT_DECODED;
6600 if(enc1 != enc2)
6601 return (enc1 < enc2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6602
6603 switch(enc1) {
6604 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
6605 return UA_ORDER_EQ;
6606
6607 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
6608 case UA_EXTENSIONOBJECT_ENCODED_XML: {
6609 UA_Order o = UA_NodeId_order(n1: &p1->content.encoded.typeId,
6610 n2: &p2->content.encoded.typeId);
6611 if(o == UA_ORDER_EQ)
6612 o = stringOrder(p1: (const UA_String*)&p1->content.encoded.body,
6613 p2: (const UA_String*)&p2->content.encoded.body, NULL);
6614 return o;
6615 }
6616
6617 case UA_EXTENSIONOBJECT_DECODED:
6618 default: {
6619 const UA_DataType *type1 = p1->content.decoded.type;
6620 const UA_DataType *type2 = p1->content.decoded.type;
6621 if(type1 != type2)
6622 return ((uintptr_t)type1 < (uintptr_t)type2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6623 if(!type1)
6624 return UA_ORDER_EQ;
6625 return orderJumpTable[type1->typeKind]
6626 (p1->content.decoded.data, p2->content.decoded.data, type1);
6627 }
6628 }
6629}
6630
6631static UA_Order
6632arrayOrder(const void *p1, size_t p1Length, const void *p2, size_t p2Length,
6633 const UA_DataType *type) {
6634 if(p1Length != p2Length)
6635 return (p1Length < p2Length) ? UA_ORDER_LESS : UA_ORDER_MORE;
6636 /* For zero-length arrays, every pointer not NULL is considered a
6637 * UA_EMPTY_ARRAY_SENTINEL. */
6638 if(p1 == p2) return UA_ORDER_EQ;
6639 if(p1 == NULL) return UA_ORDER_LESS;
6640 if(p2 == NULL) return UA_ORDER_MORE;
6641 uintptr_t u1 = (uintptr_t)p1;
6642 uintptr_t u2 = (uintptr_t)p2;
6643 for(size_t i = 0; i < p1Length; i++) {
6644 UA_Order o = orderJumpTable[type->typeKind]((const void*)u1, (const void*)u2, type);
6645 if(o != UA_ORDER_EQ)
6646 return o;
6647 u1 += type->memSize;
6648 u2 += type->memSize;
6649 }
6650 return UA_ORDER_EQ;
6651}
6652
6653static UA_Order
6654variantOrder(const UA_Variant *p1, const UA_Variant *p2,
6655 const UA_DataType *type) {
6656 if(p1->type != p2->type)
6657 return ((uintptr_t)p1->type < (uintptr_t)p2->type) ? UA_ORDER_LESS : UA_ORDER_MORE;
6658
6659 UA_Order o;
6660 if(p1->type != NULL) {
6661 /* Check if both variants are scalars or arrays */
6662 UA_Boolean s1 = UA_Variant_isScalar(v: p1);
6663 UA_Boolean s2 = UA_Variant_isScalar(v: p2);
6664 if(s1 != s2)
6665 return s1 ? UA_ORDER_LESS : UA_ORDER_MORE;
6666 if(s1) {
6667 o = orderJumpTable[p1->type->typeKind](p1->data, p2->data, p1->type);
6668 } else {
6669 /* Mismatching array length? */
6670 if(p1->arrayLength != p2->arrayLength)
6671 return (p1->arrayLength < p2->arrayLength) ? UA_ORDER_LESS : UA_ORDER_MORE;
6672 o = arrayOrder(p1: p1->data, p1Length: p1->arrayLength, p2: p2->data, p2Length: p2->arrayLength, type: p1->type);
6673 }
6674 if(o != UA_ORDER_EQ)
6675 return o;
6676 }
6677
6678 if(p1->arrayDimensionsSize != p2->arrayDimensionsSize)
6679 return (p1->arrayDimensionsSize < p2->arrayDimensionsSize) ?
6680 UA_ORDER_LESS : UA_ORDER_MORE;
6681 o = UA_ORDER_EQ;
6682 if(p1->arrayDimensionsSize > 0)
6683 o = arrayOrder(p1: p1->arrayDimensions, p1Length: p1->arrayDimensionsSize,
6684 p2: p2->arrayDimensions, p2Length: p2->arrayDimensionsSize,
6685 type: &UA_TYPES[UA_TYPES_UINT32]);
6686 return o;
6687}
6688
6689static UA_Order
6690dataValueOrder(const UA_DataValue *p1, const UA_DataValue *p2,
6691 const UA_DataType *type) {
6692 /* Value */
6693 if(p1->hasValue != p2->hasValue)
6694 return (!p1->hasValue) ? UA_ORDER_LESS : UA_ORDER_MORE;
6695 if(p1->hasValue) {
6696 UA_Order o = variantOrder(p1: &p1->value, p2: &p2->value, NULL);
6697 if(o != UA_ORDER_EQ)
6698 return o;
6699 }
6700
6701 /* Status */
6702 if(p1->hasStatus != p2->hasStatus)
6703 return (!p1->hasStatus) ? UA_ORDER_LESS : UA_ORDER_MORE;
6704 if(p1->hasStatus && p1->status != p2->status)
6705 return (p1->status < p2->status) ? UA_ORDER_LESS : UA_ORDER_MORE;
6706
6707 /* SourceTimestamp */
6708 if(p1->hasSourceTimestamp != p2->hasSourceTimestamp)
6709 return (!p1->hasSourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6710 if(p1->hasSourceTimestamp && p1->sourceTimestamp != p2->sourceTimestamp)
6711 return (p1->sourceTimestamp < p2->sourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6712
6713 /* ServerTimestamp */
6714 if(p1->hasServerTimestamp != p2->hasServerTimestamp)
6715 return (!p1->hasServerTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6716 if(p1->hasServerTimestamp && p1->serverTimestamp != p2->serverTimestamp)
6717 return (p1->serverTimestamp < p2->serverTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE;
6718
6719 /* SourcePicoseconds */
6720 if(p1->hasSourcePicoseconds != p2->hasSourcePicoseconds)
6721 return (!p1->hasSourcePicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
6722 if(p1->hasSourcePicoseconds && p1->sourcePicoseconds != p2->sourcePicoseconds)
6723 return (p1->sourcePicoseconds < p2->sourcePicoseconds) ?
6724 UA_ORDER_LESS : UA_ORDER_MORE;
6725
6726 /* ServerPicoseconds */
6727 if(p1->hasServerPicoseconds != p2->hasServerPicoseconds)
6728 return (!p1->hasServerPicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE;
6729 if(p1->hasServerPicoseconds && p1->serverPicoseconds != p2->serverPicoseconds)
6730 return (p1->serverPicoseconds < p2->serverPicoseconds) ?
6731 UA_ORDER_LESS : UA_ORDER_MORE;
6732
6733 return UA_ORDER_EQ;
6734}
6735
6736static UA_Order
6737diagnosticInfoOrder(const UA_DiagnosticInfo *p1, const UA_DiagnosticInfo *p2,
6738 const UA_DataType *type) {
6739 /* SymbolicId */
6740 if(p1->hasSymbolicId != p2->hasSymbolicId)
6741 return (!p1->hasSymbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
6742 if(p1->hasSymbolicId && p1->symbolicId != p2->symbolicId)
6743 return (p1->symbolicId < p2->symbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE;
6744
6745 /* NamespaceUri */
6746 if(p1->hasNamespaceUri != p2->hasNamespaceUri)
6747 return (!p1->hasNamespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
6748 if(p1->hasNamespaceUri && p1->namespaceUri != p2->namespaceUri)
6749 return (p1->namespaceUri < p2->namespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE;
6750
6751 /* LocalizedText */
6752 if(p1->hasLocalizedText != p2->hasLocalizedText)
6753 return (!p1->hasLocalizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
6754 if(p1->hasLocalizedText && p1->localizedText != p2->localizedText)
6755 return (p1->localizedText < p2->localizedText) ? UA_ORDER_LESS : UA_ORDER_MORE;
6756
6757 /* Locale */
6758 if(p1->hasLocale != p2->hasLocale)
6759 return (!p1->hasLocale) ? UA_ORDER_LESS : UA_ORDER_MORE;
6760 if(p1->hasLocale && p1->locale != p2->locale)
6761 return (p1->locale < p2->locale) ? UA_ORDER_LESS : UA_ORDER_MORE;
6762
6763 /* AdditionalInfo */
6764 if(p1->hasAdditionalInfo != p2->hasAdditionalInfo)
6765 return (!p1->hasAdditionalInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6766 if(p1->hasAdditionalInfo) {
6767 UA_Order o = stringOrder(p1: &p1->additionalInfo, p2: &p2->additionalInfo, NULL);
6768 if(o != UA_ORDER_EQ)
6769 return o;
6770 }
6771
6772 /* InnerStatusCode */
6773 if(p1->hasInnerStatusCode != p2->hasInnerStatusCode)
6774 return (!p1->hasInnerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
6775 if(p1->hasInnerStatusCode && p1->innerStatusCode != p2->innerStatusCode)
6776 return (p1->innerStatusCode < p2->innerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE;
6777
6778 /* InnerDiagnosticInfo */
6779 if(p1->hasInnerDiagnosticInfo != p2->hasInnerDiagnosticInfo)
6780 return (!p1->hasInnerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6781 if(p1->innerDiagnosticInfo == p2->innerDiagnosticInfo)
6782 return UA_ORDER_EQ;
6783 if(!p1->innerDiagnosticInfo || !p2->innerDiagnosticInfo)
6784 return (!p1->innerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE;
6785 return diagnosticInfoOrder(p1: p1->innerDiagnosticInfo, p2: p2->innerDiagnosticInfo, NULL);
6786}
6787
6788static UA_Order
6789structureOrder(const void *p1, const void *p2, const UA_DataType *type) {
6790 uintptr_t u1 = (uintptr_t)p1;
6791 uintptr_t u2 = (uintptr_t)p2;
6792 UA_Order o = UA_ORDER_EQ;
6793 for(size_t i = 0; i < type->membersSize; ++i) {
6794 const UA_DataTypeMember *m = &type->members[i];
6795 const UA_DataType *mt = m->memberType;
6796 u1 += m->padding;
6797 u2 += m->padding;
6798 if(!m->isOptional) {
6799 if(!m->isArray) {
6800 o = orderJumpTable[mt->typeKind]((const void *)u1, (const void *)u2, mt);
6801 u1 += mt->memSize;
6802 u2 += mt->memSize;
6803 } else {
6804 size_t size1 = *(size_t*)u1;
6805 size_t size2 = *(size_t*)u2;
6806 u1 += sizeof(size_t);
6807 u2 += sizeof(size_t);
6808 o = arrayOrder(p1: *(void* const*)u1, p1Length: size1, p2: *(void* const*)u2, p2Length: size2, type: mt);
6809 u1 += sizeof(void*);
6810 u2 += sizeof(void*);
6811 }
6812 } else {
6813 if(!m->isArray) {
6814 const void *pp1 = *(void* const*)u1;
6815 const void *pp2 = *(void* const*)u2;
6816 if(pp1 == pp2) {
6817 o = UA_ORDER_EQ;
6818 } else if(pp1 == NULL) {
6819 o = UA_ORDER_LESS;
6820 } else if(pp2 == NULL) {
6821 o = UA_ORDER_MORE;
6822 } else {
6823 o = orderJumpTable[mt->typeKind](pp1, pp2, mt);
6824 }
6825 } else {
6826 size_t sa1 = *(size_t*)u1;
6827 size_t sa2 = *(size_t*)u2;
6828 u1 += sizeof(size_t);
6829 u2 += sizeof(size_t);
6830 o = arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt);
6831 }
6832 u1 += sizeof(void*);
6833 u2 += sizeof(void*);
6834 }
6835
6836 if(o != UA_ORDER_EQ)
6837 break;
6838 }
6839 return o;
6840}
6841
6842static UA_Order
6843unionOrder(const void *p1, const void *p2, const UA_DataType *type) {
6844 UA_UInt32 sel1 = *(const UA_UInt32 *)p1;
6845 UA_UInt32 sel2 = *(const UA_UInt32 *)p2;
6846 if(sel1 != sel2)
6847 return (sel1 < sel2) ? UA_ORDER_LESS : UA_ORDER_MORE;
6848
6849 if(sel1 == 0) {
6850 return UA_ORDER_EQ;
6851 }
6852
6853 const UA_DataTypeMember *m = &type->members[sel1-1];
6854 const UA_DataType *mt = m->memberType;
6855
6856 uintptr_t u1 = ((uintptr_t)p1) + m->padding; /* includes switchfield length */
6857 uintptr_t u2 = ((uintptr_t)p2) + m->padding;
6858 if(m->isArray) {
6859 size_t sa1 = *(size_t*)u1;
6860 size_t sa2 = *(size_t*)u2;
6861 u1 += sizeof(size_t);
6862 u2 += sizeof(size_t);
6863 return arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt);
6864 }
6865 return orderJumpTable[mt->typeKind]((const void*)u1, (const void*)u2, mt);
6866}
6867
6868static UA_Order
6869notImplementedOrder(const void *p1, const void *p2, const UA_DataType *type) {
6870 return UA_ORDER_EQ;
6871}
6872
6873const
6874UA_orderSignature orderJumpTable[UA_DATATYPEKINDS] = {
6875 (UA_orderSignature)booleanOrder,
6876 (UA_orderSignature)sByteOrder,
6877 (UA_orderSignature)byteOrder,
6878 (UA_orderSignature)int16Order,
6879 (UA_orderSignature)uInt16Order,
6880 (UA_orderSignature)int32Order,
6881 (UA_orderSignature)uInt32Order,
6882 (UA_orderSignature)int64Order,
6883 (UA_orderSignature)uInt64Order,
6884 (UA_orderSignature)floatOrder,
6885 (UA_orderSignature)doubleOrder,
6886 (UA_orderSignature)stringOrder,
6887 (UA_orderSignature)int64Order, /* DateTime */
6888 (UA_orderSignature)guidOrder,
6889 (UA_orderSignature)stringOrder, /* ByteString */
6890 (UA_orderSignature)stringOrder, /* XmlElement */
6891 (UA_orderSignature)nodeIdOrder,
6892 (UA_orderSignature)expandedNodeIdOrder,
6893 (UA_orderSignature)uInt32Order, /* StatusCode */
6894 (UA_orderSignature)qualifiedNameOrder,
6895 (UA_orderSignature)localizedTextOrder,
6896 (UA_orderSignature)extensionObjectOrder,
6897 (UA_orderSignature)dataValueOrder,
6898 (UA_orderSignature)variantOrder,
6899 (UA_orderSignature)diagnosticInfoOrder,
6900 notImplementedOrder, /* Decimal, not implemented */
6901 (UA_orderSignature)uInt32Order, /* Enumeration */
6902 (UA_orderSignature)structureOrder,
6903 (UA_orderSignature)structureOrder, /* Struct with Optional Fields*/
6904 (UA_orderSignature)unionOrder, /* Union*/
6905 notImplementedOrder /* BitfieldCluster, not implemented */
6906};
6907
6908UA_Order UA_order(const void *p1, const void *p2, const UA_DataType *type) {
6909 return orderJumpTable[type->typeKind](p1, p2, type);
6910}
6911
6912/******************/
6913/* Array Handling */
6914/******************/
6915
6916void *
6917UA_Array_new(size_t size, const UA_DataType *type) {
6918 if(size > UA_INT32_MAX)
6919 return NULL;
6920 if(size == 0)
6921 return UA_EMPTY_ARRAY_SENTINEL;
6922 return UA_calloc(nmemb: size, size: type->memSize);
6923}
6924
6925UA_StatusCode
6926UA_Array_copy(const void *src, size_t size,
6927 void **dst, const UA_DataType *type) {
6928 if(size == 0) {
6929 if(src == NULL)
6930 *dst = NULL;
6931 else
6932 *dst= UA_EMPTY_ARRAY_SENTINEL;
6933 return UA_STATUSCODE_GOOD;
6934 }
6935
6936 /* Check the array consistency -- defensive programming in case the user
6937 * manually created an inconsistent array */
6938 if(UA_UNLIKELY(!type || !src))
6939 return UA_STATUSCODE_BADINTERNALERROR;
6940
6941 /* calloc, so we don't have to check retval in every iteration of copying */
6942 *dst = UA_calloc(nmemb: size, size: type->memSize);
6943 if(!*dst)
6944 return UA_STATUSCODE_BADOUTOFMEMORY;
6945
6946 if(type->pointerFree) {
6947 memcpy(dest: *dst, src: src, n: type->memSize * size);
6948 return UA_STATUSCODE_GOOD;
6949 }
6950
6951 uintptr_t ptrs = (uintptr_t)src;
6952 uintptr_t ptrd = (uintptr_t)*dst;
6953 UA_StatusCode retval = UA_STATUSCODE_GOOD;
6954 for(size_t i = 0; i < size; ++i) {
6955 retval |= UA_copy(src: (void*)ptrs, dst: (void*)ptrd, type);
6956 ptrs += type->memSize;
6957 ptrd += type->memSize;
6958 }
6959 if(retval != UA_STATUSCODE_GOOD) {
6960 UA_Array_delete(p: *dst, size, type);
6961 *dst = NULL;
6962 }
6963 return retval;
6964}
6965
6966UA_StatusCode
6967UA_Array_resize(void **p, size_t *size, size_t newSize,
6968 const UA_DataType *type) {
6969 if(*size == newSize)
6970 return UA_STATUSCODE_GOOD;
6971
6972 /* Empty array? */
6973 if(newSize == 0) {
6974 UA_Array_delete(p: *p, size: *size, type);
6975 *p = UA_EMPTY_ARRAY_SENTINEL;
6976 *size = 0;
6977 return UA_STATUSCODE_GOOD;
6978 }
6979
6980 /* Make a copy of the members that shall be removed. Realloc can fail during
6981 * trimming. So we cannot clear the members already here. */
6982 void *deleteMembers = NULL;
6983 if(newSize < *size && !type->pointerFree) {
6984 size_t deleteSize = *size - newSize;
6985 deleteMembers = UA_malloc(size: deleteSize * type->memSize);
6986 if(!deleteMembers)
6987 return UA_STATUSCODE_BADOUTOFMEMORY;
6988 memcpy(dest: deleteMembers, src: (void*)((uintptr_t)*p + (newSize * type->memSize)),
6989 n: deleteSize * type->memSize); /* shallow copy */
6990 }
6991
6992 void *oldP = *p;
6993 if(oldP == UA_EMPTY_ARRAY_SENTINEL)
6994 oldP = NULL;
6995
6996 /* Realloc */
6997 void *newP = UA_realloc(ptr: oldP, size: newSize * type->memSize);
6998 if(!newP) {
6999 if(deleteMembers)
7000 UA_free(ptr: deleteMembers);
7001 return UA_STATUSCODE_BADOUTOFMEMORY;
7002 }
7003
7004 /* Clear removed members or initialize the new ones. Note that deleteMembers
7005 * depends on type->pointerFree. */
7006 if(newSize > *size)
7007 memset(s: (void*)((uintptr_t)newP + (*size * type->memSize)), c: 0,
7008 n: (newSize - *size) * type->memSize);
7009 else if(deleteMembers)
7010 UA_Array_delete(p: deleteMembers, size: *size - newSize, type);
7011
7012 /* Set the new array */
7013 *p = newP;
7014 *size = newSize;
7015 return UA_STATUSCODE_GOOD;
7016}
7017
7018UA_StatusCode
7019UA_Array_append(void **p, size_t *size, void *newElem,
7020 const UA_DataType *type) {
7021 /* Resize the array */
7022 size_t oldSize = *size;
7023 UA_StatusCode res = UA_Array_resize(p, size, newSize: oldSize+1, type);
7024 if(res != UA_STATUSCODE_GOOD)
7025 return res;
7026
7027 /* Move the value */
7028 memcpy(dest: (void*)((uintptr_t)*p + (oldSize * type->memSize)),
7029 src: newElem, n: type->memSize);
7030 UA_init(p: newElem, type);
7031 return UA_STATUSCODE_GOOD;
7032}
7033
7034UA_StatusCode UA_EXPORT
7035UA_Array_appendCopy(void **p, size_t *size, const void *newElem,
7036 const UA_DataType *type) {
7037 char scratch[512];
7038 if(type->memSize > 512)
7039 return UA_STATUSCODE_BADINTERNALERROR;
7040
7041 /* Copy the value */
7042 UA_StatusCode res = UA_copy(src: newElem, dst: (void*)scratch, type);
7043 if(res != UA_STATUSCODE_GOOD)
7044 return res;
7045
7046 /* Append */
7047 res = UA_Array_append(p, size, newElem: (void*)scratch, type);
7048 if(res != UA_STATUSCODE_GOOD)
7049 UA_clear(p: (void*)scratch, type);
7050 return res;
7051}
7052
7053void
7054UA_Array_delete(void *p, size_t size, const UA_DataType *type) {
7055 if(!type->pointerFree) {
7056 uintptr_t ptr = (uintptr_t)p;
7057 for(size_t i = 0; i < size; ++i) {
7058 UA_clear(p: (void*)ptr, type);
7059 ptr += type->memSize;
7060 }
7061 }
7062 UA_free(ptr: (void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL));
7063}
7064
7065#ifdef UA_ENABLE_TYPEDESCRIPTION
7066UA_Boolean
7067UA_DataType_getStructMember(const UA_DataType *type, const char *memberName,
7068 size_t *outOffset, const UA_DataType **outMemberType,
7069 UA_Boolean *outIsArray) {
7070 if(type->typeKind != UA_DATATYPEKIND_STRUCTURE &&
7071 type->typeKind != UA_DATATYPEKIND_OPTSTRUCT)
7072 return false;
7073
7074 size_t offset = 0;
7075 for(size_t i = 0; i < type->membersSize; ++i) {
7076 const UA_DataTypeMember *m = &type->members[i];
7077 const UA_DataType *mt = m->memberType;
7078 offset += m->padding;
7079
7080 if(strcmp(s1: memberName, s2: m->memberName) == 0) {
7081 *outOffset = offset;
7082 *outMemberType = mt;
7083 *outIsArray = m->isArray;
7084 return true;
7085 }
7086
7087 if(!m->isOptional) {
7088 if(!m->isArray) {
7089 offset += mt->memSize;
7090 } else {
7091 offset += sizeof(size_t);
7092 offset += sizeof(void*);
7093 }
7094 } else { /* field is optional */
7095 if(!m->isArray) {
7096 offset += sizeof(void *);
7097 } else {
7098 offset += sizeof(size_t);
7099 offset += sizeof(void *);
7100 }
7101 }
7102 }
7103
7104 return false;
7105}
7106#endif
7107
7108UA_Boolean
7109UA_DataType_isNumeric(const UA_DataType *type) {
7110 switch(type->typeKind) {
7111 case UA_DATATYPEKIND_SBYTE:
7112 case UA_DATATYPEKIND_BYTE:
7113 case UA_DATATYPEKIND_INT16:
7114 case UA_DATATYPEKIND_UINT16:
7115 case UA_DATATYPEKIND_INT32:
7116 case UA_DATATYPEKIND_UINT32:
7117 case UA_DATATYPEKIND_INT64:
7118 case UA_DATATYPEKIND_UINT64:
7119 case UA_DATATYPEKIND_FLOAT:
7120 case UA_DATATYPEKIND_DOUBLE:
7121 /* not implemented: UA_DATATYPEKIND_DECIMAL */
7122 return true;
7123 default:
7124 return false;
7125 }
7126}
7127
7128UA_Int16
7129UA_DataType_getPrecedence(const UA_DataType *type){
7130 //Defined in Part 4 Table 123 "Data Precedence Rules"
7131 switch(type->typeKind) {
7132 case UA_DATATYPEKIND_DOUBLE:
7133 return 1;
7134 case UA_DATATYPEKIND_FLOAT:
7135 return 2;
7136 case UA_DATATYPEKIND_INT64:
7137 return 3;
7138 case UA_DATATYPEKIND_UINT64:
7139 return 4;
7140 case UA_DATATYPEKIND_INT32:
7141 return 5;
7142 case UA_DATATYPEKIND_UINT32:
7143 return 6;
7144 case UA_DATATYPEKIND_STATUSCODE:
7145 return 7;
7146 case UA_DATATYPEKIND_INT16:
7147 return 8;
7148 case UA_DATATYPEKIND_UINT16:
7149 return 9;
7150 case UA_DATATYPEKIND_SBYTE:
7151 return 10;
7152 case UA_DATATYPEKIND_BYTE:
7153 return 11;
7154 case UA_DATATYPEKIND_BOOLEAN:
7155 return 12;
7156 case UA_DATATYPEKIND_GUID:
7157 return 13;
7158 case UA_DATATYPEKIND_STRING:
7159 return 14;
7160 case UA_DATATYPEKIND_EXPANDEDNODEID:
7161 return 15;
7162 case UA_DATATYPEKIND_NODEID:
7163 return 16;
7164 case UA_DATATYPEKIND_LOCALIZEDTEXT:
7165 return 17;
7166 case UA_DATATYPEKIND_QUALIFIEDNAME:
7167 return 18;
7168 default:
7169 return -1;
7170 }
7171}
7172
7173/**********************/
7174/* Parse NumericRange */
7175/**********************/
7176
7177static size_t
7178readDimension(UA_Byte *buf, size_t buflen, UA_NumericRangeDimension *dim) {
7179 size_t progress = UA_readNumber(buf, buflen, number: &dim->min);
7180 if(progress == 0)
7181 return 0;
7182 if(buflen <= progress + 1 || buf[progress] != ':') {
7183 dim->max = dim->min;
7184 return progress;
7185 }
7186
7187 ++progress;
7188 size_t progress2 = UA_readNumber(buf: &buf[progress], buflen: buflen - progress, number: &dim->max);
7189 if(progress2 == 0)
7190 return 0;
7191
7192 /* invalid range */
7193 if(dim->min >= dim->max)
7194 return 0;
7195
7196 return progress + progress2;
7197}
7198
7199UA_StatusCode
7200UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) {
7201 size_t idx = 0;
7202 size_t dimensionsMax = 0;
7203 UA_NumericRangeDimension *dimensions = NULL;
7204 UA_StatusCode retval = UA_STATUSCODE_GOOD;
7205 size_t offset = 0;
7206 while(true) {
7207 /* alloc dimensions */
7208 if(idx >= dimensionsMax) {
7209 UA_NumericRangeDimension *newds;
7210 size_t newdssize = sizeof(UA_NumericRangeDimension) * (dimensionsMax + 2);
7211 newds = (UA_NumericRangeDimension*)UA_realloc(ptr: dimensions, size: newdssize);
7212 if(!newds) {
7213 retval = UA_STATUSCODE_BADOUTOFMEMORY;
7214 break;
7215 }
7216 dimensions = newds;
7217 dimensionsMax = dimensionsMax + 2;
7218 }
7219
7220 /* read the dimension */
7221 size_t progress = readDimension(buf: &str.data[offset], buflen: str.length - offset,
7222 dim: &dimensions[idx]);
7223 if(progress == 0) {
7224 retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
7225 break;
7226 }
7227 offset += progress;
7228 ++idx;
7229
7230 /* loop into the next dimension */
7231 if(offset >= str.length)
7232 break;
7233
7234 if(str.data[offset] != ',') {
7235 retval = UA_STATUSCODE_BADINDEXRANGEINVALID;
7236 break;
7237 }
7238 ++offset;
7239 }
7240
7241 if(retval == UA_STATUSCODE_GOOD && idx > 0) {
7242 range->dimensions = dimensions;
7243 range->dimensionsSize = idx;
7244 } else {
7245 UA_free(ptr: dimensions);
7246 }
7247
7248 return retval;
7249}
7250
7251/**** amalgamated original file "/src/ua_types_encoding_binary.c" ****/
7252
7253/* This Source Code Form is subject to the terms of the Mozilla Public
7254 * License, v. 2.0. If a copy of the MPL was not distributed with this
7255 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7256 *
7257 * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner)
7258 * Copyright 2020 (c) Grigory Friedman
7259 * Copyright 2014-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
7260 * Copyright 2014-2017 (c) Florian Palm
7261 * Copyright 2014-2016 (c) Sten Grüner
7262 * Copyright 2014 (c) Leon Urbas
7263 * Copyright 2015 (c) LEvertz
7264 * Copyright 2015 (c) Chris Iatrou
7265 * Copyright 2015-2016 (c) Oleksiy Vasylyev
7266 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
7267 * Copyright 2016 (c) Lorenz Haas
7268 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
7269 * Copyright 2017 (c) Henrik Norrman
7270 */
7271
7272
7273
7274/**
7275 * Type Encoding and Decoding
7276 * --------------------------
7277 * The following methods contain encoding and decoding functions for the builtin
7278 * data types and generic functions that operate on all types and arrays. This
7279 * requires the type description from a UA_DataType structure.
7280 *
7281 * Breaking a message up into chunks is integrated with the encoding. When the
7282 * end of a buffer is reached, a callback is executed that sends the current
7283 * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing
7284 * encoding. This reduces the RAM requirements and unnecessary copying. */
7285
7286/* Part 6 §5.1.5: Decoders shall support at least 100 nesting levels */
7287#define UA_ENCODING_MAX_RECURSION 100
7288
7289typedef struct {
7290 /* Pointers to the current and last buffer position */
7291 u8 *pos;
7292 const u8 *end;
7293
7294 /* How often did we en-/decoding recurse? */
7295 u16 depth;
7296
7297 const UA_DataTypeArray *customTypes;
7298 UA_exchangeEncodeBuffer exchangeBufferCallback;
7299 void *exchangeBufferCallbackHandle;
7300} Ctx;
7301
7302typedef status
7303(*encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type,
7304 Ctx *UA_RESTRICT ctx);
7305typedef status
7306(*decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type,
7307 Ctx *UA_RESTRICT ctx);
7308typedef size_t
7309(*calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *type);
7310
7311#define ENCODE_BINARY(TYPE) static status \
7312 TYPE##_encodeBinary(const UA_##TYPE *UA_RESTRICT src, \
7313 const UA_DataType *type, Ctx *UA_RESTRICT ctx)
7314#define DECODE_BINARY(TYPE) static status \
7315 TYPE##_decodeBinary(UA_##TYPE *UA_RESTRICT dst, \
7316 const UA_DataType *type, Ctx *UA_RESTRICT ctx)
7317#define CALCSIZE_BINARY(TYPE) static size_t \
7318 TYPE##_calcSizeBinary(const UA_##TYPE *UA_RESTRICT src, const UA_DataType *_)
7319#define ENCODE_DIRECT(SRC, TYPE) TYPE##_encodeBinary((const UA_##TYPE*)SRC, NULL, ctx)
7320#define DECODE_DIRECT(DST, TYPE) TYPE##_decodeBinary((UA_##TYPE*)DST, NULL, ctx)
7321
7322/* Jumptables for de-/encoding and computing the buffer length. The methods in
7323 * the decoding jumptable do not all clean up their allocated memory when an
7324 * error occurs. So a final _clear needs to be called before returning to the
7325 * user. */
7326extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS];
7327extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS];
7328extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS];
7329
7330/* Send the current chunk and replace the buffer */
7331static status exchangeBuffer(Ctx *ctx) {
7332 if(!ctx->exchangeBufferCallback)
7333 return UA_STATUSCODE_BADENCODINGERROR;
7334 return ctx->exchangeBufferCallback(ctx->exchangeBufferCallbackHandle,
7335 &ctx->pos, &ctx->end);
7336}
7337
7338/* If encoding fails, exchange the buffer and try again. */
7339static status
7340encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) {
7341 u8 *oldpos = ctx->pos; /* Last known good position */
7342#ifndef NDEBUG
7343 /* We have to ensure that the buffer was not exchanged AND
7344 * BADENCODINGLIMITSEXCEEDED was returned. If that were the case, oldpos
7345 * would be invalid. That means, a type encoding must never return
7346 * BADENCODINGLIMITSEXCEEDED once the buffer could have been exchanged. This
7347 * is achieved by the use of encodeWithExchangeBuffer. */
7348 const u8 *oldend = ctx->end;
7349 (void)oldend; /* For compilers who don't understand NDEBUG... */
7350#endif
7351 status ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
7352 if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
7353 UA_assert(ctx->end == oldend);
7354 ctx->pos = oldpos; /* Set to the last known good position and exchange */
7355 ret = exchangeBuffer(ctx);
7356 UA_CHECK_STATUS(ret, return ret);
7357 ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx);
7358 }
7359 return ret;
7360}
7361
7362/*****************/
7363/* Integer Types */
7364/*****************/
7365
7366#if !UA_BINARY_OVERLAYABLE_INTEGER
7367
7368#pragma message "Integer endianness could not be detected to be little endian. Use slow generic encoding."
7369
7370/* These en/decoding functions are only used when the architecture isn't little-endian. */
7371static void
7372UA_encode16(const u16 v, u8 buf[2]) {
7373 buf[0] = (u8)v;
7374 buf[1] = (u8)(v >> 8);
7375}
7376
7377static void
7378UA_decode16(const u8 buf[2], u16 *v) {
7379 *v = (u16)((u16)buf[0] + (((u16)buf[1]) << 8));
7380}
7381
7382static void
7383UA_encode32(const u32 v, u8 buf[4]) {
7384 buf[0] = (u8)v;
7385 buf[1] = (u8)(v >> 8);
7386 buf[2] = (u8)(v >> 16);
7387 buf[3] = (u8)(v >> 24);
7388}
7389
7390static void
7391UA_decode32(const u8 buf[4], u32 *v) {
7392 *v = (u32)((u32)buf[0] + (((u32)buf[1]) << 8) +
7393 (((u32)buf[2]) << 16) + (((u32)buf[3]) << 24));
7394}
7395
7396static void
7397UA_encode64(const u64 v, u8 buf[8]) {
7398 buf[0] = (u8)v;
7399 buf[1] = (u8)(v >> 8);
7400 buf[2] = (u8)(v >> 16);
7401 buf[3] = (u8)(v >> 24);
7402 buf[4] = (u8)(v >> 32);
7403 buf[5] = (u8)(v >> 40);
7404 buf[6] = (u8)(v >> 48);
7405 buf[7] = (u8)(v >> 56);
7406}
7407
7408static void
7409UA_decode64(const u8 buf[8], u64 *v) {
7410 *v = (u64)((u64)buf[0] + (((u64)buf[1]) << 8) +
7411 (((u64)buf[2]) << 16) + (((u64)buf[3]) << 24) +
7412 (((u64)buf[4]) << 32) + (((u64)buf[5]) << 40) +
7413 (((u64)buf[6]) << 48) + (((u64)buf[7]) << 56));
7414}
7415
7416#endif /* !UA_BINARY_OVERLAYABLE_INTEGER */
7417
7418/* Boolean */
7419/* Note that sizeof(bool) != 1 on some platforms. Overlayable integer encoding
7420 * is disabled in those cases. */
7421ENCODE_BINARY(Boolean) {
7422 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7423 *ctx->pos = *(const u8*)src;
7424 ++ctx->pos;
7425 return UA_STATUSCODE_GOOD;
7426}
7427
7428DECODE_BINARY(Boolean) {
7429 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
7430 *dst = (*ctx->pos > 0) ? true : false;
7431 ++ctx->pos;
7432 return UA_STATUSCODE_GOOD;
7433}
7434
7435/* Byte */
7436ENCODE_BINARY(Byte) {
7437 UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
7438 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7439 *ctx->pos = *(const u8*)src;
7440 ++ctx->pos;
7441 return UA_STATUSCODE_GOOD;
7442}
7443
7444DECODE_BINARY(Byte) {
7445 UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end,
7446 return UA_STATUSCODE_BADDECODINGERROR);
7447 *dst = *ctx->pos;
7448 ++ctx->pos;
7449 return UA_STATUSCODE_GOOD;
7450}
7451
7452/* UInt16 */
7453ENCODE_BINARY(UInt16) {
7454 UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
7455 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7456#if UA_BINARY_OVERLAYABLE_INTEGER
7457 memcpy(dest: ctx->pos, src: src, n: sizeof(u16));
7458#else
7459 UA_encode16(*src, ctx->pos);
7460#endif
7461 ctx->pos += 2;
7462 return UA_STATUSCODE_GOOD;
7463}
7464
7465DECODE_BINARY(UInt16) {
7466 UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end,
7467 return UA_STATUSCODE_BADDECODINGERROR);
7468#if UA_BINARY_OVERLAYABLE_INTEGER
7469 memcpy(dest: dst, src: ctx->pos, n: sizeof(u16));
7470#else
7471 UA_decode16(ctx->pos, dst);
7472#endif
7473 ctx->pos += 2;
7474 return UA_STATUSCODE_GOOD;
7475}
7476
7477/* UInt32 */
7478ENCODE_BINARY(UInt32) {
7479 UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
7480 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7481#if UA_BINARY_OVERLAYABLE_INTEGER
7482 memcpy(dest: ctx->pos, src: src, n: sizeof(u32));
7483#else
7484 UA_encode32(*src, ctx->pos);
7485#endif
7486 ctx->pos += 4;
7487 return UA_STATUSCODE_GOOD;
7488}
7489
7490DECODE_BINARY(UInt32) {
7491 UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end,
7492 return UA_STATUSCODE_BADDECODINGERROR);
7493#if UA_BINARY_OVERLAYABLE_INTEGER
7494 memcpy(dest: dst, src: ctx->pos, n: sizeof(u32));
7495#else
7496 UA_decode32(ctx->pos, dst);
7497#endif
7498 ctx->pos += 4;
7499 return UA_STATUSCODE_GOOD;
7500}
7501
7502/* UInt64 */
7503ENCODE_BINARY(UInt64) {
7504 UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
7505 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7506#if UA_BINARY_OVERLAYABLE_INTEGER
7507 memcpy(dest: ctx->pos, src: src, n: sizeof(u64));
7508#else
7509 UA_encode64(*src, ctx->pos);
7510#endif
7511 ctx->pos += 8;
7512 return UA_STATUSCODE_GOOD;
7513}
7514
7515DECODE_BINARY(UInt64) {
7516 UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end,
7517 return UA_STATUSCODE_BADDECODINGERROR);
7518#if UA_BINARY_OVERLAYABLE_INTEGER
7519 memcpy(dest: dst, src: ctx->pos, n: sizeof(u64));
7520#else
7521 UA_decode64(ctx->pos, dst);
7522#endif
7523 ctx->pos += 8;
7524 return UA_STATUSCODE_GOOD;
7525}
7526
7527/************************/
7528/* Floating Point Types */
7529/************************/
7530
7531/* Can we reuse the integer encoding mechanism by casting floating point
7532 * values? */
7533#if (UA_FLOAT_IEEE754 == 1) && (UA_LITTLE_ENDIAN == UA_FLOAT_LITTLE_ENDIAN)
7534# define Float_encodeBinary UInt32_encodeBinary
7535# define Float_decodeBinary UInt32_decodeBinary
7536# define Double_encodeBinary UInt64_encodeBinary
7537# define Double_decodeBinary UInt64_decodeBinary
7538#else
7539
7540#include <math.h>
7541
7542#pragma message "No native IEEE 754 format detected. Use slow generic encoding."
7543
7544/* Handling of IEEE754 floating point values was taken from Beej's Guide to
7545 * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the
7546 * edge cases +/-0, +/-inf and nan. */
7547static uint64_t
7548pack754(long double f, unsigned bits, unsigned expbits) {
7549 unsigned significandbits = bits - expbits - 1;
7550 long double fnorm;
7551 long long sign;
7552 if(f < 0) { sign = 1; fnorm = -f; }
7553 else { sign = 0; fnorm = f; }
7554 int shift = 0;
7555 while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; }
7556 while(fnorm < 1.0) { fnorm *= 2.0; --shift; }
7557 fnorm = fnorm - 1.0;
7558 long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f));
7559 long long exponent = shift + ((1<<(expbits-1)) - 1);
7560 return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand);
7561}
7562
7563static long double
7564unpack754(uint64_t i, unsigned bits, unsigned expbits) {
7565 unsigned significandbits = bits - expbits - 1;
7566 long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1));
7567 result /= (long double)(1LL<<significandbits);
7568 result += 1.0f;
7569 unsigned bias = (unsigned)(1<<(expbits-1)) - 1;
7570 long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias;
7571 while(shift > 0) { result *= 2.0; --shift; }
7572 while(shift < 0) { result /= 2.0; ++shift; }
7573 result *= ((i>>(bits-1))&1)? -1.0: 1.0;
7574 return result;
7575}
7576
7577/* Float */
7578#define FLOAT_NAN 0xffc00000
7579#define FLOAT_INF 0x7f800000
7580#define FLOAT_NEG_INF 0xff800000
7581#define FLOAT_NEG_ZERO 0x80000000
7582
7583ENCODE_BINARY(Float) {
7584 UA_Float f = *src;
7585 u32 encoded;
7586 /* cppcheck-suppress duplicateExpression */
7587 if(f != f) encoded = FLOAT_NAN;
7588 else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0;
7589 else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF;
7590 else encoded = (u32)pack754(f, 32, 8);
7591 return ENCODE_DIRECT(&encoded, UInt32);
7592}
7593
7594DECODE_BINARY(Float) {
7595 u32 decoded;
7596 status ret = DECODE_DIRECT(&decoded, UInt32);
7597 if(ret != UA_STATUSCODE_GOOD)
7598 return ret;
7599 if(decoded == 0) *dst = 0.0f;
7600 else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f;
7601 else if(decoded == FLOAT_INF) *dst = INFINITY;
7602 else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY;
7603 else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) ||
7604 (decoded >= 0xff800001)) *dst = NAN;
7605 else *dst = (UA_Float)unpack754(decoded, 32, 8);
7606 return UA_STATUSCODE_GOOD;
7607}
7608
7609/* Double */
7610#define DOUBLE_NAN 0xfff8000000000000L
7611#define DOUBLE_INF 0x7ff0000000000000L
7612#define DOUBLE_NEG_INF 0xfff0000000000000L
7613#define DOUBLE_NEG_ZERO 0x8000000000000000L
7614
7615ENCODE_BINARY(Double) {
7616 UA_Double d = *src;
7617 u64 encoded;
7618 /* cppcheck-suppress duplicateExpression */
7619 if(d != d) encoded = DOUBLE_NAN;
7620 else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0;
7621 else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF;
7622 else encoded = pack754(d, 64, 11);
7623 return ENCODE_DIRECT(&encoded, UInt64);
7624}
7625
7626DECODE_BINARY(Double) {
7627 u64 decoded;
7628 status ret = DECODE_DIRECT(&decoded, UInt64);
7629 UA_CHECK_STATUS(ret, return ret);
7630 if(decoded == 0) *dst = 0.0;
7631 else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0;
7632 else if(decoded == DOUBLE_INF) *dst = INFINITY;
7633 else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY;
7634 else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) ||
7635 (decoded >= 0xfff0000000000001L)) *dst = NAN;
7636 else *dst = (UA_Double)unpack754(decoded, 64, 11);
7637 return UA_STATUSCODE_GOOD;
7638}
7639
7640#endif
7641
7642/******************/
7643/* Array Handling */
7644/******************/
7645
7646static status
7647Array_encodeBinaryOverlayable(uintptr_t ptr, size_t memSize, Ctx *ctx) {
7648 /* Loop as long as more elements remain than fit into the chunk */
7649 while(ctx->end < ctx->pos + memSize) {
7650 size_t possible = ((uintptr_t)ctx->end - (uintptr_t)ctx->pos);
7651 memcpy(dest: ctx->pos, src: (void*)ptr, n: possible);
7652 ctx->pos += possible;
7653 ptr += possible;
7654 status ret = exchangeBuffer(ctx);
7655 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7656 UA_CHECK_STATUS(ret, return ret);
7657 memSize -= possible;
7658 }
7659
7660 /* Encode the remaining elements */
7661 memcpy(dest: ctx->pos, src: (void*)ptr, n: memSize);
7662 ctx->pos += memSize;
7663 return UA_STATUSCODE_GOOD;
7664}
7665
7666static status
7667Array_encodeBinaryComplex(uintptr_t ptr, size_t length,
7668 const UA_DataType *type, Ctx *ctx) {
7669 /* Encode every element */
7670 for(size_t i = 0; i < length; ++i) {
7671 status ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type, ctx);
7672 ptr += type->memSize;
7673 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7674 UA_CHECK_STATUS(ret, return ret); /* Unrecoverable fail */
7675 }
7676 return UA_STATUSCODE_GOOD;
7677}
7678
7679static status
7680Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx *ctx) {
7681 /* Check and convert the array length to int32 */
7682 i32 signed_length = -1;
7683 if(length > UA_INT32_MAX)
7684 return UA_STATUSCODE_BADINTERNALERROR;
7685 if(length > 0)
7686 signed_length = (i32)length;
7687 else if(src == UA_EMPTY_ARRAY_SENTINEL)
7688 signed_length = 0;
7689
7690 /* Encode the array length */
7691 status ret = encodeWithExchangeBuffer(ptr: &signed_length, type: &UA_TYPES[UA_TYPES_INT32], ctx);
7692 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7693 UA_CHECK_STATUS(ret, return ret);
7694
7695 /* Encode the content */
7696 if(length > 0) {
7697 if(type->overlayable)
7698 ret = Array_encodeBinaryOverlayable(ptr: (uintptr_t)src, memSize: length * type->memSize, ctx);
7699 else
7700 ret = Array_encodeBinaryComplex(ptr: (uintptr_t)src, length, type, ctx);
7701 }
7702 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7703 return ret;
7704}
7705
7706static status
7707Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length,
7708 const UA_DataType *type, Ctx *ctx) {
7709 /* Decode the length */
7710 i32 signed_length;
7711 status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */
7712 UA_CHECK_STATUS(ret, return ret);
7713
7714 /* Return early for empty arrays */
7715 if(signed_length <= 0) {
7716 *out_length = 0;
7717 if(signed_length < 0)
7718 *dst = NULL;
7719 else
7720 *dst = UA_EMPTY_ARRAY_SENTINEL;
7721 return UA_STATUSCODE_GOOD;
7722 }
7723
7724 /* Filter out arrays that can obviously not be decoded, because the message
7725 * is too small for the array length. This prevents the allocation of very
7726 * long arrays for bogus messages.
7727 *
7728 * The worst known case (so far) is UA_DataValue. It has
7729 * sizeof(UA_DataValue) == 80 and an empty DataValue is encoded with just
7730 * one byte. We use 128 as the smallest power of 2 larger than 80. */
7731 size_t length = (size_t)signed_length;
7732 UA_CHECK(ctx->pos + ((type->memSize * length) / 128) <= ctx->end,
7733 return UA_STATUSCODE_BADDECODINGERROR);
7734
7735 /* Allocate memory */
7736 *dst = UA_calloc(nmemb: length, size: type->memSize);
7737 UA_CHECK_MEM(*dst, return UA_STATUSCODE_BADOUTOFMEMORY);
7738
7739 if(type->overlayable) {
7740 /* memcpy overlayable array */
7741 UA_CHECK(ctx->pos + (type->memSize * length) <= ctx->end,
7742 UA_free(*dst); *dst = NULL; return UA_STATUSCODE_BADDECODINGERROR);
7743 memcpy(dest: *dst, src: ctx->pos, n: type->memSize * length);
7744 ctx->pos += type->memSize * length;
7745 } else {
7746 /* Decode array members */
7747 uintptr_t ptr = (uintptr_t)*dst;
7748 for(size_t i = 0; i < length; ++i) {
7749 ret = decodeBinaryJumpTable[type->typeKind]((void*)ptr, type, ctx);
7750 UA_CHECK_STATUS(ret, /* +1 because last element is also already initialized */
7751 UA_Array_delete(*dst, i+1, type); *dst = NULL; return ret);
7752 ptr += type->memSize;
7753 }
7754 }
7755 *out_length = length;
7756 return UA_STATUSCODE_GOOD;
7757}
7758
7759/*****************/
7760/* Builtin Types */
7761/*****************/
7762
7763ENCODE_BINARY(String) {
7764 return Array_encodeBinary(src: src->data, length: src->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
7765}
7766
7767DECODE_BINARY(String) {
7768 return Array_decodeBinary(dst: (void**)&dst->data, out_length: &dst->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
7769}
7770
7771/* Guid */
7772ENCODE_BINARY(Guid) {
7773 status ret = UA_STATUSCODE_GOOD;
7774 ret |= ENCODE_DIRECT(&src->data1, UInt32);
7775 ret |= ENCODE_DIRECT(&src->data2, UInt16);
7776 ret |= ENCODE_DIRECT(&src->data3, UInt16);
7777 UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
7778 return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7779 memcpy(dest: ctx->pos, src: src->data4, n: 8*sizeof(u8));
7780 ctx->pos += 8;
7781 return ret;
7782}
7783
7784DECODE_BINARY(Guid) {
7785 status ret = UA_STATUSCODE_GOOD;
7786 ret |= DECODE_DIRECT(&dst->data1, UInt32);
7787 ret |= DECODE_DIRECT(&dst->data2, UInt16);
7788 ret |= DECODE_DIRECT(&dst->data3, UInt16);
7789 UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end,
7790 return UA_STATUSCODE_BADDECODINGERROR);
7791 memcpy(dest: dst->data4, src: ctx->pos, n: 8*sizeof(u8));
7792 ctx->pos += 8;
7793 return ret;
7794}
7795
7796/* NodeId */
7797#define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0u
7798#define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1u
7799#define UA_NODEIDTYPE_NUMERIC_COMPLETE 2u
7800
7801#define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40u
7802#define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80u
7803
7804/* For ExpandedNodeId, we prefill the encoding mask. */
7805static status
7806NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx) {
7807 status ret = UA_STATUSCODE_GOOD;
7808 switch(src->identifierType) {
7809 case UA_NODEIDTYPE_NUMERIC:
7810 if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
7811 encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE;
7812 ret |= ENCODE_DIRECT(&encoding, Byte);
7813 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7814 ret |= ENCODE_DIRECT(&src->identifier.numeric, UInt32);
7815 } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
7816 encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE;
7817 ret |= ENCODE_DIRECT(&encoding, Byte);
7818 u8 nsindex = (u8)src->namespaceIndex;
7819 ret |= ENCODE_DIRECT(&nsindex, Byte);
7820 u16 identifier16 = (u16)src->identifier.numeric;
7821 ret |= ENCODE_DIRECT(&identifier16, UInt16);
7822 } else {
7823 encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE;
7824 ret |= ENCODE_DIRECT(&encoding, Byte);
7825 u8 identifier8 = (u8)src->identifier.numeric;
7826 ret |= ENCODE_DIRECT(&identifier8, Byte);
7827 }
7828 break;
7829 case UA_NODEIDTYPE_STRING:
7830 encoding |= (u8)UA_NODEIDTYPE_STRING;
7831 ret |= ENCODE_DIRECT(&encoding, Byte);
7832 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7833 UA_CHECK_STATUS(ret, return ret);
7834 /* Can exchange the buffer */
7835 ret = ENCODE_DIRECT(&src->identifier.string, String);
7836 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7837 break;
7838 case UA_NODEIDTYPE_GUID:
7839 encoding |= (u8)UA_NODEIDTYPE_GUID;
7840 ret |= ENCODE_DIRECT(&encoding, Byte);
7841 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7842 ret |= ENCODE_DIRECT(&src->identifier.guid, Guid);
7843 break;
7844 case UA_NODEIDTYPE_BYTESTRING:
7845 encoding |= (u8)UA_NODEIDTYPE_BYTESTRING;
7846 ret |= ENCODE_DIRECT(&encoding, Byte);
7847 ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7848 UA_CHECK_STATUS(ret, return ret);
7849 /* Can exchange the buffer */
7850 ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */
7851 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7852 break;
7853 default:
7854 return UA_STATUSCODE_BADINTERNALERROR;
7855 }
7856 return ret;
7857}
7858
7859ENCODE_BINARY(NodeId) {
7860 return NodeId_encodeBinaryWithEncodingMask(src, encoding: 0, ctx);
7861}
7862
7863DECODE_BINARY(NodeId) {
7864 u8 dstByte = 0, encodingByte = 0;
7865 u16 dstUInt16 = 0;
7866
7867 /* Decode the encoding bitfield */
7868 status ret = DECODE_DIRECT(&encodingByte, Byte);
7869 UA_CHECK_STATUS(ret, return ret);
7870
7871 /* Filter out the bits used only for ExpandedNodeIds */
7872 encodingByte &= (u8)~(u8)(UA_EXPANDEDNODEID_SERVERINDEX_FLAG |
7873 UA_EXPANDEDNODEID_NAMESPACEURI_FLAG);
7874
7875 /* Decode the namespace and identifier */
7876 switch(encodingByte) {
7877 case UA_NODEIDTYPE_NUMERIC_TWOBYTE:
7878 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7879 ret = DECODE_DIRECT(&dstByte, Byte);
7880 dst->identifier.numeric = dstByte;
7881 dst->namespaceIndex = 0;
7882 break;
7883 case UA_NODEIDTYPE_NUMERIC_FOURBYTE:
7884 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7885 ret |= DECODE_DIRECT(&dstByte, Byte);
7886 dst->namespaceIndex = dstByte;
7887 ret |= DECODE_DIRECT(&dstUInt16, UInt16);
7888 dst->identifier.numeric = dstUInt16;
7889 break;
7890 case UA_NODEIDTYPE_NUMERIC_COMPLETE:
7891 dst->identifierType = UA_NODEIDTYPE_NUMERIC;
7892 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7893 ret |= DECODE_DIRECT(&dst->identifier.numeric, UInt32);
7894 break;
7895 case UA_NODEIDTYPE_STRING:
7896 dst->identifierType = UA_NODEIDTYPE_STRING;
7897 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7898 ret |= DECODE_DIRECT(&dst->identifier.string, String);
7899 break;
7900 case UA_NODEIDTYPE_GUID:
7901 dst->identifierType = UA_NODEIDTYPE_GUID;
7902 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7903 ret |= DECODE_DIRECT(&dst->identifier.guid, Guid);
7904 break;
7905 case UA_NODEIDTYPE_BYTESTRING:
7906 dst->identifierType = UA_NODEIDTYPE_BYTESTRING;
7907 ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7908 ret |= DECODE_DIRECT(&dst->identifier.byteString, String); /* ByteString */
7909 break;
7910 default:
7911 ret |= UA_STATUSCODE_BADINTERNALERROR;
7912 break;
7913 }
7914 return ret;
7915}
7916
7917/* ExpandedNodeId */
7918ENCODE_BINARY(ExpandedNodeId) {
7919 /* Set up the encoding mask */
7920 u8 encoding = 0;
7921 if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL)
7922 encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG;
7923 if(src->serverIndex > 0)
7924 encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG;
7925
7926 /* Encode the NodeId. Can exchange the buffer. */
7927 status ret = NodeId_encodeBinaryWithEncodingMask(src: &src->nodeId, encoding, ctx);
7928 UA_CHECK_STATUS(ret, return ret);
7929
7930 /* Encode the namespace. Internally uses encodeWithExchangeBuffer
7931 * everywhere. So it will never return
7932 * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
7933 if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) {
7934 ret = ENCODE_DIRECT(&src->namespaceUri, String);
7935 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7936 UA_CHECK_STATUS(ret, return ret);
7937 }
7938
7939 /* Encode the serverIndex */
7940 if(src->serverIndex > 0)
7941 ret = encodeWithExchangeBuffer(ptr: &src->serverIndex, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
7942 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
7943 return ret;
7944}
7945
7946DECODE_BINARY(ExpandedNodeId) {
7947 /* Decode the encoding mask */
7948 UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR);
7949 u8 encoding = *ctx->pos;
7950
7951 /* Decode the NodeId */
7952 status ret = DECODE_DIRECT(&dst->nodeId, NodeId);
7953
7954 /* Decode the NamespaceUri */
7955 if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) {
7956 dst->nodeId.namespaceIndex = 0;
7957 ret |= DECODE_DIRECT(&dst->namespaceUri, String);
7958 }
7959
7960 /* Decode the ServerIndex */
7961 if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG)
7962 ret |= DECODE_DIRECT(&dst->serverIndex, UInt32);
7963 return ret;
7964}
7965
7966/* QualifiedName */
7967ENCODE_BINARY(QualifiedName) {
7968 status ret = ENCODE_DIRECT(&src->namespaceIndex, UInt16);
7969 /* Must check here so we can exchange the buffer in the string encoding */
7970 UA_CHECK_STATUS(ret, return ret);
7971 ret |= ENCODE_DIRECT(&src->name, String);
7972 return ret;
7973}
7974
7975DECODE_BINARY(QualifiedName) {
7976 status ret = DECODE_DIRECT(&dst->namespaceIndex, UInt16);
7977 ret |= DECODE_DIRECT(&dst->name, String);
7978 return ret;
7979}
7980
7981/* LocalizedText */
7982#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01u
7983#define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02u
7984
7985ENCODE_BINARY(LocalizedText) {
7986 /* Set up the encoding mask */
7987 u8 encoding = 0;
7988 if(src->locale.data)
7989 encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE;
7990 if(src->text.data)
7991 encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT;
7992
7993 /* Encode the encoding byte */
7994 status ret = ENCODE_DIRECT(&encoding, Byte);
7995 /* Must check here so we can exchange the buffer in the string encoding */
7996 UA_CHECK_STATUS(ret, return ret);
7997
7998 /* Encode the strings */
7999 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
8000 ret |= ENCODE_DIRECT(&src->locale, String);
8001 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
8002 ret |= ENCODE_DIRECT(&src->text, String);
8003 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8004 return ret;
8005}
8006
8007DECODE_BINARY(LocalizedText) {
8008 /* Decode the encoding mask */
8009 u8 encoding = 0;
8010 status ret = DECODE_DIRECT(&encoding, Byte);
8011
8012 /* Decode the content */
8013 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE)
8014 ret |= DECODE_DIRECT(&dst->locale, String);
8015 if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT)
8016 ret |= DECODE_DIRECT(&dst->text, String);
8017 return ret;
8018}
8019
8020/* The binary encoding has a different nodeid from the data type. So it is not
8021 * possible to reuse UA_findDataType */
8022static const UA_DataType *
8023UA_findDataTypeByBinaryInternal(const UA_NodeId *typeId, Ctx *ctx) {
8024 /* Always look in the built-in types first. Assume that only numeric
8025 * identifiers are used for the builtin types. (They may contain data types
8026 * from all namespaces though.) */
8027 if(typeId->identifierType == UA_NODEIDTYPE_NUMERIC) {
8028 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
8029 if(UA_TYPES[i].binaryEncodingId.identifier.numeric == typeId->identifier.numeric &&
8030 UA_TYPES[i].binaryEncodingId.namespaceIndex == typeId->namespaceIndex)
8031 return &UA_TYPES[i];
8032 }
8033 }
8034
8035 const UA_DataTypeArray *customTypes = ctx->customTypes;
8036 while(customTypes) {
8037 for(size_t i = 0; i < customTypes->typesSize; ++i) {
8038 if(UA_NodeId_equal(n1: typeId, n2: &customTypes->types[i].binaryEncodingId))
8039 return &customTypes->types[i];
8040 }
8041 customTypes = customTypes->next;
8042 }
8043
8044 return NULL;
8045}
8046
8047const UA_DataType *
8048UA_findDataTypeByBinary(const UA_NodeId *typeId) {
8049 Ctx ctx;
8050 ctx.customTypes = NULL;
8051 return UA_findDataTypeByBinaryInternal(typeId, ctx: &ctx);
8052}
8053
8054/* ExtensionObject */
8055ENCODE_BINARY(ExtensionObject) {
8056 u8 encoding = (u8)src->encoding;
8057
8058 /* No content or already encoded content. */
8059 if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
8060 /* Can exchange the buffer */
8061 status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId);
8062 UA_CHECK_STATUS(ret, return ret);
8063 ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
8064 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8065 UA_CHECK_STATUS(ret, return ret);
8066 switch(src->encoding) {
8067 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
8068 break;
8069 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
8070 case UA_EXTENSIONOBJECT_ENCODED_XML:
8071 /* ByteString in disguise. Array encoding can exchange the buffer */
8072 ret = ENCODE_DIRECT(&src->content.encoded.body, String);
8073 break;
8074 default:
8075 ret = UA_STATUSCODE_BADINTERNALERROR;
8076 }
8077 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8078 return ret;
8079 }
8080
8081 /* Cannot encode with no data or no type description */
8082 if(!src->content.decoded.type || !src->content.decoded.data)
8083 return UA_STATUSCODE_BADENCODINGERROR;
8084
8085 /* Write the NodeId for the binary encoded type. This could perform a buffer
8086 * exchange, but can also return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */
8087 status ret = ENCODE_DIRECT(&src->content.decoded.type->binaryEncodingId, NodeId);
8088 UA_CHECK_STATUS(ret, return ret);
8089
8090 /* Encode the encoding byte */
8091 encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
8092 ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx);
8093 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8094 UA_CHECK_STATUS(ret, return ret);
8095
8096 /* Encode the content length */
8097 const UA_DataType *contentType = src->content.decoded.type;
8098 size_t len = UA_calcSizeBinary(p: src->content.decoded.data, type: contentType);
8099 UA_CHECK(len <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
8100 i32 signed_len = (i32)len;
8101 ret = encodeWithExchangeBuffer(ptr: &signed_len, type: &UA_TYPES[UA_TYPES_INT32], ctx);
8102 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8103 UA_CHECK_STATUS(ret, return ret);
8104
8105 /* Encode the content */
8106 ret = encodeWithExchangeBuffer(ptr: src->content.decoded.data, type: contentType, ctx);
8107 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8108 return ret;
8109}
8110
8111static status
8112ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId,
8113 Ctx *ctx) {
8114 /* Lookup the datatype */
8115 const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx);
8116
8117 /* Unknown type, just take the binary content */
8118 if(!type) {
8119 dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING;
8120 UA_NodeId_copy(src: typeId, dst: &dst->content.encoded.typeId);
8121 return DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
8122 }
8123
8124 /* Allocate memory */
8125 dst->content.decoded.data = UA_new(type);
8126 UA_CHECK_MEM(dst->content.decoded.data, return UA_STATUSCODE_BADOUTOFMEMORY);
8127
8128 /* Jump over the length field (TODO: check if the decoded length matches) */
8129 ctx->pos += 4;
8130
8131 /* Decode */
8132 dst->encoding = UA_EXTENSIONOBJECT_DECODED;
8133 dst->content.decoded.type = type;
8134 return decodeBinaryJumpTable[type->typeKind](dst->content.decoded.data, type, ctx);
8135}
8136
8137DECODE_BINARY(ExtensionObject) {
8138 u8 encoding = 0;
8139 UA_NodeId binTypeId;
8140 UA_NodeId_init(p: &binTypeId);
8141
8142 status ret = UA_STATUSCODE_GOOD;
8143 ret |= DECODE_DIRECT(&binTypeId, NodeId);
8144 ret |= DECODE_DIRECT(&encoding, Byte);
8145 UA_CHECK_STATUS(ret, UA_NodeId_clear(&binTypeId); return ret);
8146
8147 switch(encoding) {
8148 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
8149 ret = ExtensionObject_decodeBinaryContent(dst, typeId: &binTypeId, ctx);
8150 UA_NodeId_clear(p: &binTypeId);
8151 break;
8152 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
8153 dst->encoding = (UA_ExtensionObjectEncoding)encoding;
8154 dst->content.encoded.typeId = binTypeId; /* move to dst */
8155 dst->content.encoded.body = UA_BYTESTRING_NULL;
8156 break;
8157 case UA_EXTENSIONOBJECT_ENCODED_XML:
8158 dst->encoding = (UA_ExtensionObjectEncoding)encoding;
8159 dst->content.encoded.typeId = binTypeId; /* move to dst */
8160 ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */
8161 UA_CHECK_STATUS(ret, UA_NodeId_clear(&dst->content.encoded.typeId));
8162 break;
8163 default:
8164 UA_NodeId_clear(p: &binTypeId);
8165 ret = UA_STATUSCODE_BADDECODINGERROR;
8166 break;
8167 }
8168
8169 return ret;
8170}
8171
8172/* Variant */
8173
8174static status
8175Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src,
8176 const UA_Boolean isArray, Ctx *ctx) {
8177 size_t length = 1; /* Default to 1 for a scalar. */
8178
8179 /* Encode the array length if required */
8180 status ret = UA_STATUSCODE_GOOD;
8181 if(isArray) {
8182 UA_CHECK(src->arrayLength <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR);
8183 length = src->arrayLength;
8184 i32 encodedLength = (i32)src->arrayLength;
8185 ret = ENCODE_DIRECT(&encodedLength, UInt32); /* Int32 */
8186 UA_CHECK_STATUS(ret, return ret);
8187 }
8188
8189 /* Set up the ExtensionObject */
8190 UA_ExtensionObject eo;
8191 UA_ExtensionObject_init(p: &eo);
8192 eo.encoding = UA_EXTENSIONOBJECT_DECODED;
8193 eo.content.decoded.type = src->type;
8194 const u16 memSize = src->type->memSize;
8195 uintptr_t ptr = (uintptr_t)src->data;
8196
8197 /* Iterate over the array */
8198 for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) {
8199 eo.content.decoded.data = (void*)ptr;
8200 ret = encodeWithExchangeBuffer(ptr: &eo, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx);
8201 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8202 ptr += memSize;
8203 }
8204 return ret;
8205}
8206
8207enum UA_VARIANT_ENCODINGMASKTYPE {
8208 UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3Fu, /* bits 0:5 */
8209 UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (u8)(0x01u << 6u), /* bit 6 */
8210 UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (u8)(0x01u << 7u) /* bit 7 */
8211};
8212
8213ENCODE_BINARY(Variant) {
8214 /* Quit early for the empty variant */
8215 u8 encoding = 0;
8216 if(!src->type)
8217 return ENCODE_DIRECT(&encoding, Byte);
8218
8219 /* Set the content type in the encoding mask */
8220 const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
8221 const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
8222 if(isBuiltin)
8223 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->typeKind + 1u)));
8224 else if(isEnum)
8225 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_INT32 + 1u)));
8226 else
8227 encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_EXTENSIONOBJECT + 1u)));
8228
8229 /* Set the array type in the encoding mask */
8230 const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
8231 const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
8232 if(isArray) {
8233 encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY;
8234 if(hasDimensions)
8235 encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS;
8236 }
8237
8238 /* Encode the encoding byte */
8239 status ret = ENCODE_DIRECT(&encoding, Byte);
8240 UA_CHECK_STATUS(ret, return ret);
8241
8242 /* Encode the content. This can exchange the buffer. */
8243 if(!isBuiltin && !isEnum) {
8244 /* This could return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. But we
8245 * have not exchanged the buffer so far. */
8246 ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx);
8247 } else if(!isArray) {
8248 ret = encodeWithExchangeBuffer(ptr: src->data, type: src->type, ctx);
8249 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8250 } else {
8251 ret = Array_encodeBinary(src: src->data, length: src->arrayLength, type: src->type, ctx);
8252 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8253 }
8254 UA_CHECK_STATUS(ret, return ret);
8255
8256 /* Encode the array dimensions */
8257 if(hasDimensions && ret == UA_STATUSCODE_GOOD)
8258 ret = Array_encodeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize,
8259 type: &UA_TYPES[UA_TYPES_INT32], ctx);
8260 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8261 return ret;
8262}
8263
8264static status
8265Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) {
8266 /* Save the position in the ByteString. If unwrapping is not possible, start
8267 * from here to decode a normal ExtensionObject. */
8268 u8 *old_pos = ctx->pos;
8269
8270 /* Decode the DataType */
8271 UA_NodeId typeId;
8272 UA_NodeId_init(p: &typeId);
8273 status ret = DECODE_DIRECT(&typeId, NodeId);
8274 UA_CHECK_STATUS(ret, return ret);
8275
8276 /* Decode the EncodingByte */
8277 u8 encoding;
8278 ret = DECODE_DIRECT(&encoding, Byte);
8279 UA_CHECK_STATUS(ret, UA_NodeId_clear(&typeId); return ret);
8280
8281 /* Search for the datatype. Default to ExtensionObject. */
8282 if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING &&
8283 (dst->type = UA_findDataTypeByBinaryInternal(typeId: &typeId, ctx)) != NULL) {
8284 /* Jump over the length field (TODO: check if length matches) */
8285 ctx->pos += 4;
8286 } else {
8287 /* Reset and decode as ExtensionObject */
8288 dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT];
8289 ctx->pos = old_pos;
8290 }
8291 UA_NodeId_clear(p: &typeId);
8292
8293 /* Allocate memory */
8294 dst->data = UA_new(type: dst->type);
8295 UA_CHECK_MEM(dst->data, return UA_STATUSCODE_BADOUTOFMEMORY);
8296
8297 /* Decode the content */
8298 return decodeBinaryJumpTable[dst->type->typeKind](dst->data, dst->type, ctx);
8299}
8300
8301/* The resulting variant always has the storagetype UA_VARIANT_DATA. */
8302DECODE_BINARY(Variant) {
8303 /* Decode the encoding byte */
8304 u8 encodingByte;
8305 status ret = DECODE_DIRECT(&encodingByte, Byte);
8306 UA_CHECK_STATUS(ret, return ret);
8307
8308 /* Return early for an empty variant (was already _inited) */
8309 if(encodingByte == 0)
8310 return UA_STATUSCODE_GOOD;
8311
8312 /* Does the variant contain an array? */
8313 const UA_Boolean isArray = (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0;
8314
8315 /* Get the datatype of the content. The type must be a builtin data type.
8316 * All not-builtin types are wrapped in an ExtensionObject. The "type kind"
8317 * for types up to DiagnsticInfo equals to the index in the encoding
8318 * byte. */
8319 size_t typeKind = (size_t)((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1);
8320 UA_CHECK(typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO, return UA_STATUSCODE_BADDECODINGERROR);
8321
8322 /* A variant cannot contain a variant. But it can contain an array of
8323 * variants */
8324 UA_CHECK(typeKind != UA_DATATYPEKIND_VARIANT || isArray,
8325 return UA_STATUSCODE_BADDECODINGERROR);
8326
8327 /* Check the recursion limit */
8328 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8329 ctx->depth++;
8330
8331 /* Decode the content */
8332 dst->type = &UA_TYPES[typeKind];
8333 if(isArray) {
8334 ret = Array_decodeBinary(dst: &dst->data, out_length: &dst->arrayLength, type: dst->type, ctx);
8335 } else if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) {
8336 dst->data = UA_new(type: dst->type);
8337 UA_CHECK_MEM(dst->data, ctx->depth--; return UA_STATUSCODE_BADOUTOFMEMORY);
8338 ret = decodeBinaryJumpTable[typeKind](dst->data, dst->type, ctx);
8339 } else {
8340 ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx);
8341 }
8342
8343 /* Decode array dimensions */
8344 if(isArray && (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0)
8345 ret |= Array_decodeBinary(dst: (void**)&dst->arrayDimensions, out_length: &dst->arrayDimensionsSize,
8346 type: &UA_TYPES[UA_TYPES_INT32], ctx);
8347
8348 ctx->depth--;
8349 return ret;
8350}
8351
8352/* DataValue */
8353ENCODE_BINARY(DataValue) {
8354 /* Set up the encoding mask */
8355 u8 encodingMask = src->hasValue;
8356 encodingMask |= (u8)(src->hasStatus << 1u);
8357 encodingMask |= (u8)(src->hasSourceTimestamp << 2u);
8358 encodingMask |= (u8)(src->hasServerTimestamp << 3u);
8359 encodingMask |= (u8)(src->hasSourcePicoseconds << 4u);
8360 encodingMask |= (u8)(src->hasServerPicoseconds << 5u);
8361
8362 /* Encode the encoding byte */
8363 status ret = ENCODE_DIRECT(&encodingMask, Byte);
8364 UA_CHECK_STATUS(ret, return ret);
8365
8366 /* Encode the variant. */
8367 if(src->hasValue) {
8368 ret = ENCODE_DIRECT(&src->value, Variant);
8369 if(ret != UA_STATUSCODE_GOOD)
8370 return ret;
8371 }
8372
8373 if(src->hasStatus)
8374 ret |= encodeWithExchangeBuffer(ptr: &src->status, type: &UA_TYPES[UA_TYPES_STATUSCODE], ctx);
8375 if(src->hasSourceTimestamp)
8376 ret |= encodeWithExchangeBuffer(ptr: &src->sourceTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx);
8377 if(src->hasSourcePicoseconds)
8378 ret |= encodeWithExchangeBuffer(ptr: &src->sourcePicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx);
8379 if(src->hasServerTimestamp)
8380 ret |= encodeWithExchangeBuffer(ptr: &src->serverTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx);
8381 if(src->hasServerPicoseconds)
8382 ret |= encodeWithExchangeBuffer(ptr: &src->serverPicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx);
8383 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8384 return ret;
8385}
8386
8387#define MAX_PICO_SECONDS 9999
8388
8389DECODE_BINARY(DataValue) {
8390 /* Decode the encoding mask */
8391 u8 encodingMask;
8392 status ret = DECODE_DIRECT(&encodingMask, Byte);
8393 UA_CHECK_STATUS(ret, return ret);
8394
8395 /* Check the recursion limit */
8396 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8397 ctx->depth++;
8398
8399 /* Decode the content */
8400 if(encodingMask & 0x01u) {
8401 dst->hasValue = true;
8402 ret |= DECODE_DIRECT(&dst->value, Variant);
8403 }
8404 if(encodingMask & 0x02u) {
8405 dst->hasStatus = true;
8406 ret |= DECODE_DIRECT(&dst->status, UInt32); /* StatusCode */
8407 }
8408 if(encodingMask & 0x04u) {
8409 dst->hasSourceTimestamp = true;
8410 ret |= DECODE_DIRECT(&dst->sourceTimestamp, UInt64); /* DateTime */
8411 }
8412 if(encodingMask & 0x10u) {
8413 dst->hasSourcePicoseconds = true;
8414 ret |= DECODE_DIRECT(&dst->sourcePicoseconds, UInt16);
8415 if(dst->sourcePicoseconds > MAX_PICO_SECONDS)
8416 dst->sourcePicoseconds = MAX_PICO_SECONDS;
8417 }
8418 if(encodingMask & 0x08u) {
8419 dst->hasServerTimestamp = true;
8420 ret |= DECODE_DIRECT(&dst->serverTimestamp, UInt64); /* DateTime */
8421 }
8422 if(encodingMask & 0x20u) {
8423 dst->hasServerPicoseconds = true;
8424 ret |= DECODE_DIRECT(&dst->serverPicoseconds, UInt16);
8425 if(dst->serverPicoseconds > MAX_PICO_SECONDS)
8426 dst->serverPicoseconds = MAX_PICO_SECONDS;
8427 }
8428
8429 ctx->depth--;
8430 return ret;
8431}
8432
8433/* DiagnosticInfo */
8434ENCODE_BINARY(DiagnosticInfo) {
8435 /* Set up the encoding mask */
8436 u8 encodingMask = src->hasSymbolicId;
8437 encodingMask |= (u8)(src->hasNamespaceUri << 1u);
8438 encodingMask |= (u8)(src->hasLocalizedText << 2u);
8439 encodingMask |= (u8)(src->hasLocale << 3u);
8440 encodingMask |= (u8)(src->hasAdditionalInfo << 4u);
8441 encodingMask |= (u8)(src->hasInnerStatusCode << 5u);
8442 encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 6u);
8443
8444 /* Encode the numeric content */
8445 status ret = ENCODE_DIRECT(&encodingMask, Byte);
8446 if(src->hasSymbolicId)
8447 ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */
8448 if(src->hasNamespaceUri)
8449 ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */
8450 if(src->hasLocalizedText)
8451 ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */
8452 if(src->hasLocale)
8453 ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */
8454 if(ret != UA_STATUSCODE_GOOD)
8455 return ret;
8456
8457 /* Encode the additional info. Can exchange the buffer. */
8458 if(src->hasAdditionalInfo) {
8459 ret = ENCODE_DIRECT(&src->additionalInfo, String);
8460 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8461 UA_CHECK_STATUS(ret, return ret);
8462 }
8463
8464 /* Encode the inner status code */
8465 if(src->hasInnerStatusCode) {
8466 ret = encodeWithExchangeBuffer(ptr: &src->innerStatusCode, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
8467 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8468 UA_CHECK_STATUS(ret, return ret);
8469 }
8470
8471 /* Encode the inner diagnostic info */
8472 if(src->hasInnerDiagnosticInfo) {
8473 ret = encodeWithExchangeBuffer(ptr: src->innerDiagnosticInfo,
8474 type: &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx);
8475 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8476 }
8477
8478 return ret;
8479}
8480
8481DECODE_BINARY(DiagnosticInfo) {
8482 /* Decode the encoding mask */
8483 u8 encodingMask;
8484 status ret = DECODE_DIRECT(&encodingMask, Byte);
8485 UA_CHECK_STATUS(ret, return ret);
8486
8487 /* Decode the content */
8488 if(encodingMask & 0x01u) {
8489 dst->hasSymbolicId = true;
8490 ret |= DECODE_DIRECT(&dst->symbolicId, UInt32); /* Int32 */
8491 }
8492 if(encodingMask & 0x02u) {
8493 dst->hasNamespaceUri = true;
8494 ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */
8495 }
8496 if(encodingMask & 0x04u) {
8497 dst->hasLocalizedText = true;
8498 ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */
8499 }
8500 if(encodingMask & 0x08u) {
8501 dst->hasLocale = true;
8502 ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */
8503 }
8504 if(encodingMask & 0x10u) {
8505 dst->hasAdditionalInfo = true;
8506 ret |= DECODE_DIRECT(&dst->additionalInfo, String);
8507 }
8508 if(encodingMask & 0x20u) {
8509 dst->hasInnerStatusCode = true;
8510 ret |= DECODE_DIRECT(&dst->innerStatusCode, UInt32); /* StatusCode */
8511 }
8512 if(encodingMask & 0x40u) {
8513 /* innerDiagnosticInfo is allocated on the heap */
8514 dst->innerDiagnosticInfo = (UA_DiagnosticInfo*)
8515 UA_calloc(nmemb: 1, size: sizeof(UA_DiagnosticInfo));
8516 UA_CHECK_MEM(dst->innerDiagnosticInfo, return UA_STATUSCODE_BADOUTOFMEMORY);
8517 dst->hasInnerDiagnosticInfo = true;
8518
8519 /* Check the recursion limit */
8520 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8521 return UA_STATUSCODE_BADENCODINGERROR);
8522
8523 ctx->depth++;
8524 ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo);
8525 ctx->depth--;
8526 }
8527 return ret;
8528}
8529
8530/********************/
8531/* Structured Types */
8532/********************/
8533
8534static status
8535encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) {
8536 /* Check the recursion limit */
8537 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8538 return UA_STATUSCODE_BADENCODINGERROR);
8539 ctx->depth++;
8540
8541 /* Loop over members */
8542 uintptr_t ptr = (uintptr_t)src;
8543 status ret = UA_STATUSCODE_GOOD;
8544 for(size_t i = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8545 const UA_DataTypeMember *m = &type->members[i];
8546 const UA_DataType *mt = m->memberType;
8547 ptr += m->padding;
8548
8549 /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */
8550 if(m->isArray) {
8551 const size_t length = *((const size_t*)ptr);
8552 ptr += sizeof(size_t);
8553 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx);
8554 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8555 ptr += sizeof(void*);
8556 continue;
8557 }
8558
8559 /* Scalar */
8560 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8561 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8562 ptr += mt->memSize;
8563 }
8564
8565 ctx->depth--;
8566 return ret;
8567}
8568
8569static status
8570encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *ctx) {
8571 /* Check the recursion limit */
8572 if(ctx->depth > UA_ENCODING_MAX_RECURSION)
8573 return UA_STATUSCODE_BADENCODINGERROR;
8574 ctx->depth++;
8575
8576 /* Creating the encoding mask, marking the available optional fields */
8577 uintptr_t ptr = (uintptr_t)src;
8578 size_t optFieldCounter = 0;
8579 UA_UInt32 encodingMask = 0;
8580 for(size_t j = 0; j < type->membersSize; ++j) {
8581 const UA_DataTypeMember *m = &type->members[j];
8582 const UA_DataType *mt = m->memberType;
8583 ptr += m->padding;
8584 if(m->isOptional) {
8585 if(m->isArray)
8586 ptr += sizeof(size_t);
8587 if(*(void* const*)ptr != NULL)
8588 encodingMask |= (UA_UInt32) 1 << optFieldCounter;
8589 ptr += sizeof(void *);
8590 optFieldCounter++;
8591 } else if (m->isArray) {
8592 ptr += sizeof(size_t);
8593 ptr += sizeof(void *);
8594 } else {
8595 ptr += mt->memSize;
8596 }
8597 }
8598
8599 /* Encode the mask */
8600 status ret = ENCODE_DIRECT(&encodingMask, UInt32);
8601 UA_CHECK_STATUS(ret, ctx->depth--; return ret);
8602
8603 /* Loop over members */
8604 ptr = (uintptr_t)src;
8605 for(size_t i = 0, o = 0; i < type->membersSize && UA_LIKELY(ret == UA_STATUSCODE_GOOD); ++i) {
8606 const UA_DataTypeMember *m = &type->members[i];
8607 const UA_DataType *mt = m->memberType;
8608 ptr += m->padding;
8609
8610 if(m->isOptional) {
8611 if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) {
8612 /* Optional and not contained */
8613 if(m->isArray)
8614 ptr += sizeof(size_t);
8615 } else if(m->isArray) {
8616 /* Optional Array */
8617 const size_t length = *((const size_t *) ptr);
8618 ptr += sizeof(size_t);
8619 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx);
8620 } else {
8621 /* Optional Scalar */
8622 ret = encodeWithExchangeBuffer(ptr: *(void* const*) ptr, type: mt, ctx);
8623 }
8624 ptr += sizeof(void *);
8625 continue;
8626 }
8627
8628 /* Mandatory Array */
8629 if(m->isArray) {
8630 const size_t length = *((const size_t *) ptr);
8631 ptr += sizeof(size_t);
8632 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx);
8633 ptr += sizeof(void *);
8634 continue;
8635 }
8636
8637 /* Mandatory Scalar */
8638 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8639 ptr += mt->memSize;
8640 }
8641 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8642
8643 ctx->depth--;
8644 return ret;
8645}
8646
8647static status
8648encodeBinaryUnion(const void *src, const UA_DataType *type, Ctx *ctx) {
8649 /* Check the recursion limit */
8650 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8651 return UA_STATUSCODE_BADENCODINGERROR);
8652 ctx->depth++;
8653
8654 /* Encode the selection */
8655 const UA_UInt32 selection = *(const UA_UInt32*)src;
8656 status ret = ENCODE_DIRECT(&selection, UInt32);
8657 if(UA_UNLIKELY(ret != UA_STATUSCODE_GOOD) || selection == 0) {
8658 ctx->depth--;
8659 return ret;
8660 }
8661
8662 /* Select the member */
8663 const UA_DataTypeMember *m = &type->members[selection-1];
8664 const UA_DataType *mt = m->memberType;
8665
8666 /* Encode the member */
8667 uintptr_t ptr = ((uintptr_t)src) + m->padding; /* includes the switchfield length */
8668 if(!m->isArray) {
8669 ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx);
8670 } else {
8671 const size_t length = *((const size_t*)ptr);
8672 ptr += sizeof(size_t);
8673 ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx);
8674 }
8675
8676 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8677
8678 ctx->depth--;
8679 return ret;
8680}
8681
8682static status
8683encodeBinaryNotImplemented(const void *src, const UA_DataType *type, Ctx *ctx) {
8684 (void)src, (void)type, (void)ctx;
8685 return UA_STATUSCODE_BADNOTIMPLEMENTED;
8686}
8687
8688const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = {
8689 (encodeBinarySignature)Boolean_encodeBinary,
8690 (encodeBinarySignature)Byte_encodeBinary, /* SByte */
8691 (encodeBinarySignature)Byte_encodeBinary,
8692 (encodeBinarySignature)UInt16_encodeBinary, /* Int16 */
8693 (encodeBinarySignature)UInt16_encodeBinary,
8694 (encodeBinarySignature)UInt32_encodeBinary, /* Int32 */
8695 (encodeBinarySignature)UInt32_encodeBinary,
8696 (encodeBinarySignature)UInt64_encodeBinary, /* Int64 */
8697 (encodeBinarySignature)UInt64_encodeBinary,
8698 (encodeBinarySignature)Float_encodeBinary,
8699 (encodeBinarySignature)Double_encodeBinary,
8700 (encodeBinarySignature)String_encodeBinary,
8701 (encodeBinarySignature)UInt64_encodeBinary, /* DateTime */
8702 (encodeBinarySignature)Guid_encodeBinary,
8703 (encodeBinarySignature)String_encodeBinary, /* ByteString */
8704 (encodeBinarySignature)String_encodeBinary, /* XmlElement */
8705 (encodeBinarySignature)NodeId_encodeBinary,
8706 (encodeBinarySignature)ExpandedNodeId_encodeBinary,
8707 (encodeBinarySignature)UInt32_encodeBinary, /* StatusCode */
8708 (encodeBinarySignature)QualifiedName_encodeBinary,
8709 (encodeBinarySignature)LocalizedText_encodeBinary,
8710 (encodeBinarySignature)ExtensionObject_encodeBinary,
8711 (encodeBinarySignature)DataValue_encodeBinary,
8712 (encodeBinarySignature)Variant_encodeBinary,
8713 (encodeBinarySignature)DiagnosticInfo_encodeBinary,
8714 (encodeBinarySignature)encodeBinaryNotImplemented, /* Decimal */
8715 (encodeBinarySignature)UInt32_encodeBinary, /* Enumeration */
8716 (encodeBinarySignature)encodeBinaryStruct,
8717 (encodeBinarySignature)encodeBinaryStructWithOptFields, /* Structure with Optional Fields */
8718 (encodeBinarySignature)encodeBinaryUnion, /* Union */
8719 (encodeBinarySignature)encodeBinaryStruct /* BitfieldCluster */
8720};
8721
8722status
8723UA_encodeBinaryInternal(const void *src, const UA_DataType *type,
8724 u8 **bufPos, const u8 **bufEnd,
8725 UA_exchangeEncodeBuffer exchangeCallback,
8726 void *exchangeHandle) {
8727 /* Set up the context */
8728 Ctx ctx;
8729 ctx.pos = *bufPos;
8730 ctx.end = *bufEnd;
8731 ctx.depth = 0;
8732 ctx.exchangeBufferCallback = exchangeCallback;
8733 ctx.exchangeBufferCallbackHandle = exchangeHandle;
8734
8735 UA_CHECK_MEM(ctx.pos, return UA_STATUSCODE_BADINVALIDARGUMENT);
8736
8737 /* Encode */
8738 status ret = encodeWithExchangeBuffer(ptr: src, type, ctx: &ctx);
8739 UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED);
8740
8741 /* Set the new buffer position for the output. Beware that the buffer might
8742 * have been exchanged internally. */
8743 *bufPos = ctx.pos;
8744 *bufEnd = ctx.end;
8745 return ret;
8746}
8747
8748UA_StatusCode
8749UA_encodeBinary(const void *p, const UA_DataType *type,
8750 UA_ByteString *outBuf) {
8751 /* Allocate buffer */
8752 UA_Boolean allocated = false;
8753 status res = UA_STATUSCODE_GOOD;
8754 if(outBuf->length == 0) {
8755 size_t len = UA_calcSizeBinary(p, type);
8756 res = UA_ByteString_allocBuffer(bs: outBuf, length: len);
8757 if(res != UA_STATUSCODE_GOOD)
8758 return res;
8759 allocated = true;
8760 }
8761
8762 /* Encode */
8763 u8 *pos = outBuf->data;
8764 const u8 *posEnd = &outBuf->data[outBuf->length];
8765 res = UA_encodeBinaryInternal(src: p, type, bufPos: &pos, bufEnd: &posEnd, NULL, NULL);
8766
8767 /* Clean up */
8768 if(res == UA_STATUSCODE_GOOD) {
8769 outBuf->length = (size_t)((uintptr_t)pos - (uintptr_t)outBuf->data);
8770 } else if(allocated) {
8771 UA_ByteString_clear(p: outBuf);
8772 }
8773 return res;
8774}
8775
8776static status
8777decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) {
8778 (void)dst, (void)type, (void)ctx;
8779 return UA_STATUSCODE_BADNOTIMPLEMENTED;
8780}
8781
8782static status
8783decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) {
8784 /* Check the recursion limit */
8785 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8786 return UA_STATUSCODE_BADENCODINGERROR);
8787 ctx->depth++;
8788
8789 uintptr_t ptr = (uintptr_t)dst;
8790 status ret = UA_STATUSCODE_GOOD;
8791 u8 membersSize = type->membersSize;
8792
8793 /* Loop over members */
8794 for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8795 const UA_DataTypeMember *m = &type->members[i];
8796 const UA_DataType *mt = m->memberType;
8797 ptr += m->padding;
8798
8799 /* Array */
8800 if(m->isArray) {
8801 size_t *length = (size_t*)ptr;
8802 ptr += sizeof(size_t);
8803 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx);
8804 ptr += sizeof(void*);
8805 continue;
8806 }
8807
8808 /* Scalar */
8809 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8810 ptr += mt->memSize;
8811 }
8812
8813 ctx->depth--;
8814 return ret;
8815}
8816
8817static status
8818decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx) {
8819 /* Check the recursion limit */
8820 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR);
8821 ctx->depth++;
8822
8823 uintptr_t ptr = (uintptr_t)dst;
8824 UA_UInt32 encodingMask = 0;
8825 status ret = UInt32_decodeBinary(dst: &encodingMask, type: &UA_TYPES[UA_TYPES_UINT32], ctx);
8826 UA_CHECK_STATUS(ret, ctx->depth--; return ret);
8827
8828 /* Loop over members */
8829 for(size_t i = 0, o = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) {
8830 const UA_DataTypeMember *m = &type->members[i];
8831 const UA_DataType *mt = m->memberType;
8832 ptr += m->padding;
8833 if(m->isOptional) {
8834 if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) {
8835 /* Optional field is not contained */
8836 if(m->isArray)
8837 ptr += sizeof(size_t);
8838 } else if(m->isArray) {
8839 /* Optional Array */
8840 size_t *length = (size_t*)ptr;
8841 ptr += sizeof(size_t);
8842 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx);
8843 } else {
8844 /* Optional Scalar */
8845 *(void *UA_RESTRICT *UA_RESTRICT) ptr = UA_calloc(nmemb: 1, size: mt->memSize);
8846 UA_CHECK_MEM(*(void *UA_RESTRICT *UA_RESTRICT) ptr, return UA_STATUSCODE_BADOUTOFMEMORY);
8847 ret = decodeBinaryJumpTable[mt->typeKind](*(void *UA_RESTRICT *UA_RESTRICT) ptr, mt, ctx);
8848 }
8849 ptr += sizeof(void *);
8850 continue;
8851 }
8852
8853 /* Array */
8854 if(m->isArray) {
8855 size_t *length = (size_t *)ptr;
8856 ptr += sizeof(size_t);
8857 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx);
8858 ptr += sizeof(void *);
8859 continue;
8860 }
8861
8862 /* Scalar */
8863 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8864 ptr += mt->memSize;
8865 }
8866 ctx->depth--;
8867 return ret;
8868}
8869
8870static status
8871decodeBinaryUnion(void *UA_RESTRICT dst, const UA_DataType *type, Ctx *ctx) {
8872 /* Check the recursion limit */
8873 UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION,
8874 return UA_STATUSCODE_BADENCODINGERROR);
8875
8876 /* Decode the selection directly into the switchfield */
8877 status ret = DECODE_DIRECT(dst, UInt32);
8878 UA_CHECK_STATUS(ret, return ret);
8879
8880 /* No content? */
8881 UA_UInt32 selection = *(UA_UInt32*)dst;
8882 if(selection == 0)
8883 return UA_STATUSCODE_GOOD;
8884
8885 /* Sanity check the selection */
8886 UA_CHECK(selection-1 < type->membersSize,
8887 return UA_STATUSCODE_BADDECODINGERROR);
8888
8889 /* Select the member */
8890 const UA_DataTypeMember *m = &type->members[selection-1];
8891 const UA_DataType *mt = m->memberType;
8892
8893 /* Decode */
8894 ctx->depth++;
8895 uintptr_t ptr = ((uintptr_t)dst) + m->padding; /* includes the switchfield */
8896 if(!m->isArray) {
8897 ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx);
8898 } else {
8899 size_t *length = (size_t *)ptr;
8900 ptr += sizeof(size_t);
8901 ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx);
8902 }
8903 ctx->depth--;
8904 return ret;
8905}
8906
8907const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = {
8908 (decodeBinarySignature)Boolean_decodeBinary,
8909 (decodeBinarySignature)Byte_decodeBinary, /* SByte */
8910 (decodeBinarySignature)Byte_decodeBinary,
8911 (decodeBinarySignature)UInt16_decodeBinary, /* Int16 */
8912 (decodeBinarySignature)UInt16_decodeBinary,
8913 (decodeBinarySignature)UInt32_decodeBinary, /* Int32 */
8914 (decodeBinarySignature)UInt32_decodeBinary,
8915 (decodeBinarySignature)UInt64_decodeBinary, /* Int64 */
8916 (decodeBinarySignature)UInt64_decodeBinary,
8917 (decodeBinarySignature)Float_decodeBinary,
8918 (decodeBinarySignature)Double_decodeBinary,
8919 (decodeBinarySignature)String_decodeBinary,
8920 (decodeBinarySignature)UInt64_decodeBinary, /* DateTime */
8921 (decodeBinarySignature)Guid_decodeBinary,
8922 (decodeBinarySignature)String_decodeBinary, /* ByteString */
8923 (decodeBinarySignature)String_decodeBinary, /* XmlElement */
8924 (decodeBinarySignature)NodeId_decodeBinary,
8925 (decodeBinarySignature)ExpandedNodeId_decodeBinary,
8926 (decodeBinarySignature)UInt32_decodeBinary, /* StatusCode */
8927 (decodeBinarySignature)QualifiedName_decodeBinary,
8928 (decodeBinarySignature)LocalizedText_decodeBinary,
8929 (decodeBinarySignature)ExtensionObject_decodeBinary,
8930 (decodeBinarySignature)DataValue_decodeBinary,
8931 (decodeBinarySignature)Variant_decodeBinary,
8932 (decodeBinarySignature)DiagnosticInfo_decodeBinary,
8933 (decodeBinarySignature)decodeBinaryNotImplemented, /* Decimal */
8934 (decodeBinarySignature)UInt32_decodeBinary, /* Enumeration */
8935 (decodeBinarySignature)decodeBinaryStructure,
8936 (decodeBinarySignature)decodeBinaryStructureWithOptFields, /* Structure with optional fields */
8937 (decodeBinarySignature)decodeBinaryUnion, /* Union */
8938 (decodeBinarySignature)decodeBinaryNotImplemented /* BitfieldCluster */
8939};
8940
8941status
8942UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset,
8943 void *dst, const UA_DataType *type,
8944 const UA_DataTypeArray *customTypes) {
8945 /* Set up the context */
8946 Ctx ctx;
8947 ctx.pos = &src->data[*offset];
8948 ctx.end = &src->data[src->length];
8949 ctx.depth = 0;
8950 ctx.customTypes = customTypes;
8951
8952 /* Decode */
8953 memset(s: dst, c: 0, n: type->memSize); /* Initialize the value */
8954 status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx);
8955
8956 if(UA_LIKELY(ret == UA_STATUSCODE_GOOD)) {
8957 /* Set the new offset */
8958 *offset = (size_t)(ctx.pos - src->data) / sizeof(u8);
8959 } else {
8960 /* Clean up */
8961 UA_clear(p: dst, type);
8962 memset(s: dst, c: 0, n: type->memSize);
8963 }
8964 return ret;
8965}
8966
8967UA_StatusCode
8968UA_decodeBinary(const UA_ByteString *inBuf,
8969 void *p, const UA_DataType *type,
8970 const UA_DecodeBinaryOptions *options) {
8971 size_t offset = 0;
8972 const UA_DataTypeArray *customTypes = options ? options->customTypes : NULL;
8973 return UA_decodeBinaryInternal(src: inBuf, offset: &offset, dst: p, type, customTypes);
8974}
8975
8976/**
8977 * Compute the Message Size
8978 * ------------------------
8979 * The following methods are used to compute the length of a datum in binary
8980 * encoding. */
8981
8982static size_t
8983Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) {
8984 size_t s = 4; /* length */
8985 if(type->overlayable) {
8986 s += type->memSize * length;
8987 return s;
8988 }
8989 uintptr_t ptr = (uintptr_t)src;
8990 for(size_t i = 0; i < length; ++i) {
8991 s += calcSizeBinaryJumpTable[type->typeKind]((const void*)ptr, type);
8992 ptr += type->memSize;
8993 }
8994 return s;
8995}
8996
8997static size_t calcSizeBinary1(const void *_, const UA_DataType *__) { (void)_, (void)__; return 1; }
8998static size_t calcSizeBinary2(const void *_, const UA_DataType *__) { (void)_, (void)__; return 2; }
8999static size_t calcSizeBinary4(const void *_, const UA_DataType *__) { (void)_, (void)__; return 4; }
9000static size_t calcSizeBinary8(const void *_, const UA_DataType *__) { (void)_, (void)__; return 8; }
9001
9002CALCSIZE_BINARY(String) { return 4 + src->length; }
9003
9004CALCSIZE_BINARY(Guid) { return 16; }
9005
9006CALCSIZE_BINARY(NodeId) {
9007 size_t s = 1; /* Encoding byte */
9008 switch(src->identifierType) {
9009 case UA_NODEIDTYPE_NUMERIC:
9010 if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) {
9011 s += 6;
9012 } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) {
9013 s += 3;
9014 } else {
9015 s += 1;
9016 }
9017 break;
9018 case UA_NODEIDTYPE_BYTESTRING:
9019 case UA_NODEIDTYPE_STRING:
9020 s += 2;
9021 s += String_calcSizeBinary(src: &src->identifier.string, NULL);
9022 break;
9023 case UA_NODEIDTYPE_GUID:
9024 s += 18;
9025 break;
9026 default:
9027 return 0;
9028 }
9029 return s;
9030}
9031
9032CALCSIZE_BINARY(ExpandedNodeId) {
9033 size_t s = NodeId_calcSizeBinary(src: &src->nodeId, NULL);
9034 if(src->namespaceUri.length > 0)
9035 s += String_calcSizeBinary(src: &src->namespaceUri, NULL);
9036 if(src->serverIndex > 0)
9037 s += 4;
9038 return s;
9039}
9040
9041CALCSIZE_BINARY(QualifiedName) {
9042 return 2 + String_calcSizeBinary(src: &src->name, NULL);
9043}
9044
9045CALCSIZE_BINARY(LocalizedText) {
9046 size_t s = 1; /* Encoding byte */
9047 if(src->locale.data)
9048 s += String_calcSizeBinary(src: &src->locale, NULL);
9049 if(src->text.data)
9050 s += String_calcSizeBinary(src: &src->text, NULL);
9051 return s;
9052}
9053
9054CALCSIZE_BINARY(ExtensionObject) {
9055 size_t s = 1; /* Encoding byte */
9056
9057 /* Encoded content */
9058 if(src->encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) {
9059 s += NodeId_calcSizeBinary(src: &src->content.encoded.typeId, NULL);
9060 switch(src->encoding) {
9061 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
9062 break;
9063 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
9064 case UA_EXTENSIONOBJECT_ENCODED_XML:
9065 s += String_calcSizeBinary(src: &src->content.encoded.body, NULL);
9066 break;
9067 default:
9068 return 0;
9069 }
9070 return s;
9071 }
9072
9073 /* Decoded content */
9074 if(!src->content.decoded.type || !src->content.decoded.data)
9075 return 0;
9076 if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC)
9077 return 0;
9078
9079 s += NodeId_calcSizeBinary(src: &src->content.decoded.type->binaryEncodingId, NULL); /* Type encoding length */
9080 s += 4; /* Encoding length field */
9081 const UA_DataType *type = src->content.decoded.type;
9082 s += calcSizeBinaryJumpTable[type->typeKind](src->content.decoded.data, type); /* Encoding length */
9083 return s;
9084}
9085
9086CALCSIZE_BINARY(Variant) {
9087 size_t s = 1; /* Encoding byte */
9088 if(!src->type)
9089 return s;
9090
9091 const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL;
9092 if(isArray)
9093 s += Array_calcSizeBinary(src: src->data, length: src->arrayLength, type: src->type);
9094 else
9095 s += calcSizeBinaryJumpTable[src->type->typeKind](src->data, src->type);
9096
9097 const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO);
9098 const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM);
9099 if(!isBuiltin && !isEnum) {
9100 /* The type is wrapped inside an extensionobject */
9101 /* (NodeId + encoding byte + extension object length) * array length */
9102 size_t length = isArray ? src->arrayLength : 1;
9103 s += (NodeId_calcSizeBinary(src: &src->type->binaryEncodingId, NULL) + 1 + 4) * length;
9104 }
9105
9106 const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0;
9107 if(hasDimensions)
9108 s += Array_calcSizeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize,
9109 type: &UA_TYPES[UA_TYPES_INT32]);
9110 return s;
9111}
9112
9113CALCSIZE_BINARY(DataValue) {
9114 size_t s = 1; /* Encoding byte */
9115 if(src->hasValue)
9116 s += Variant_calcSizeBinary(src: &src->value, NULL);
9117 if(src->hasStatus)
9118 s += 4;
9119 if(src->hasSourceTimestamp)
9120 s += 8;
9121 if(src->hasSourcePicoseconds)
9122 s += 2;
9123 if(src->hasServerTimestamp)
9124 s += 8;
9125 if(src->hasServerPicoseconds)
9126 s += 2;
9127 return s;
9128}
9129
9130CALCSIZE_BINARY(DiagnosticInfo) {
9131 size_t s = 1; /* Encoding byte */
9132 if(src->hasSymbolicId)
9133 s += 4;
9134 if(src->hasNamespaceUri)
9135 s += 4;
9136 if(src->hasLocalizedText)
9137 s += 4;
9138 if(src->hasLocale)
9139 s += 4;
9140 if(src->hasAdditionalInfo)
9141 s += String_calcSizeBinary(src: &src->additionalInfo, NULL);
9142 if(src->hasInnerStatusCode)
9143 s += 4;
9144 if(src->hasInnerDiagnosticInfo)
9145 s += DiagnosticInfo_calcSizeBinary(src: src->innerDiagnosticInfo, NULL);
9146 return s;
9147}
9148
9149static size_t
9150calcSizeBinaryStructure(const void *p, const UA_DataType *type) {
9151 size_t s = 0;
9152 uintptr_t ptr = (uintptr_t)p;
9153 u8 membersSize = type->membersSize;
9154
9155 /* Loop over members */
9156 for(size_t i = 0; i < membersSize; ++i) {
9157 const UA_DataTypeMember *member = &type->members[i];
9158 const UA_DataType *membertype = member->memberType;
9159 ptr += member->padding;
9160
9161 /* Array */
9162 if(member->isArray) {
9163 const size_t length = *((const size_t*)ptr);
9164 ptr += sizeof(size_t);
9165 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype);
9166 ptr += sizeof(void*);
9167 continue;
9168 }
9169
9170 /* Scalar */
9171 s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
9172 ptr += membertype->memSize;
9173 }
9174
9175 return s;
9176}
9177
9178static size_t
9179calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) {
9180 /* Start with the size of the encoding mask */
9181 size_t s = sizeof(UA_UInt32);
9182
9183 /* Loop over members */
9184 uintptr_t ptr = (uintptr_t)p;
9185 for(size_t i = 0; i < type->membersSize; ++i) {
9186 const UA_DataTypeMember *member = &type->members[i];
9187 const UA_DataType *membertype = member->memberType;
9188 ptr += member->padding;
9189 if(member->isOptional) {
9190 if((member->isArray && ((*(void* const*)(ptr+sizeof(size_t))) == NULL)) ||
9191 (!member->isArray && (*(void* const*)ptr == NULL))) {
9192 /* Optional member not contained */
9193 if(member->isArray)
9194 ptr += sizeof(size_t);
9195 ptr += sizeof(void *);
9196 continue;
9197 }
9198 /* Fallthrough to take the size into account */
9199 }
9200 /* Array */
9201 if(member->isArray) {
9202 const size_t length = *((const size_t*)ptr);
9203 ptr += sizeof(size_t);
9204 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype);
9205 ptr += sizeof(void*);
9206 continue;
9207 }
9208 /* Scalar */
9209 if (member->isOptional) {
9210 s += calcSizeBinaryJumpTable[membertype->typeKind](*(void* const*)ptr, membertype);
9211 ptr += sizeof(void *);
9212 } else {
9213 s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype);
9214 ptr += membertype->memSize;
9215 }
9216 }
9217 return s;
9218}
9219
9220static size_t
9221calcSizeBinaryUnion(const void *p, const UA_DataType *type) {
9222 size_t s = 4; /* UA_TYPES[UA_TYPES_UINT32].memSize; */
9223 const UA_UInt32 selection = *(const UA_UInt32 *)p;
9224 if(selection == 0)
9225 return s;
9226
9227 const UA_DataTypeMember *m = &type->members[selection-1];
9228 const UA_DataType *mt = m->memberType;
9229
9230 uintptr_t ptr = ((uintptr_t)p) + m->padding; /* includes switchfield length */
9231 if(!m->isArray) {
9232 s += UA_calcSizeBinary(p: (const void*)ptr, type: mt);
9233 } else {
9234 const size_t length = *((const size_t*)ptr);
9235 ptr += sizeof(size_t);
9236 s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt);
9237 }
9238 return s;
9239}
9240
9241static size_t
9242calcSizeBinaryNotImplemented(const void *p, const UA_DataType *type) {
9243 (void)p, (void)type;
9244 return 0;
9245}
9246
9247const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS] = {
9248 (calcSizeBinarySignature)calcSizeBinary1, /* Boolean */
9249 (calcSizeBinarySignature)calcSizeBinary1, /* SByte */
9250 (calcSizeBinarySignature)calcSizeBinary1, /* Byte */
9251 (calcSizeBinarySignature)calcSizeBinary2, /* Int16 */
9252 (calcSizeBinarySignature)calcSizeBinary2, /* UInt16 */
9253 (calcSizeBinarySignature)calcSizeBinary4, /* Int32 */
9254 (calcSizeBinarySignature)calcSizeBinary4, /* UInt32 */
9255 (calcSizeBinarySignature)calcSizeBinary8, /* Int64 */
9256 (calcSizeBinarySignature)calcSizeBinary8, /* UInt64 */
9257 (calcSizeBinarySignature)calcSizeBinary4, /* Float */
9258 (calcSizeBinarySignature)calcSizeBinary8, /* Double */
9259 (calcSizeBinarySignature)String_calcSizeBinary,
9260 (calcSizeBinarySignature)calcSizeBinary8, /* DateTime */
9261 (calcSizeBinarySignature)Guid_calcSizeBinary,
9262 (calcSizeBinarySignature)String_calcSizeBinary, /* ByteString */
9263 (calcSizeBinarySignature)String_calcSizeBinary, /* XmlElement */
9264 (calcSizeBinarySignature)NodeId_calcSizeBinary,
9265 (calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary,
9266 (calcSizeBinarySignature)calcSizeBinary4, /* StatusCode */
9267 (calcSizeBinarySignature)QualifiedName_calcSizeBinary,
9268 (calcSizeBinarySignature)LocalizedText_calcSizeBinary,
9269 (calcSizeBinarySignature)ExtensionObject_calcSizeBinary,
9270 (calcSizeBinarySignature)DataValue_calcSizeBinary,
9271 (calcSizeBinarySignature)Variant_calcSizeBinary,
9272 (calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary,
9273 (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Decimal */
9274 (calcSizeBinarySignature)calcSizeBinary4, /* Enumeration */
9275 (calcSizeBinarySignature)calcSizeBinaryStructure,
9276 (calcSizeBinarySignature)calcSizeBinaryStructureWithOptFields, /* Structure with Optional Fields */
9277 (calcSizeBinarySignature)calcSizeBinaryUnion, /* Union */
9278 (calcSizeBinarySignature)calcSizeBinaryNotImplemented /* BitfieldCluster */
9279};
9280
9281size_t
9282UA_calcSizeBinary(const void *p, const UA_DataType *type) {
9283 return calcSizeBinaryJumpTable[type->typeKind](p, type);
9284}
9285
9286/**** amalgamated original file "/src/ua_types_print.c" ****/
9287
9288/* This Source Code Form is subject to the terms of the Mozilla Public
9289 * License, v. 2.0. If a copy of the MPL was not distributed with this
9290 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9291 *
9292 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
9293 */
9294
9295
9296
9297/* Printing of NodeIds is always enabled. We need it for logging. */
9298
9299UA_StatusCode
9300UA_NodeId_print(const UA_NodeId *id, UA_String *output) {
9301 UA_String_clear(p: output);
9302 if(!id)
9303 return UA_STATUSCODE_GOOD;
9304
9305 char *nsStr = NULL;
9306 long snprintfLen = 0;
9307 size_t nsLen = 0;
9308 if(id->namespaceIndex != 0) {
9309 nsStr = (char*)UA_malloc(size: 9+1); // strlen("ns=XXXXX;") = 9 + Nullbyte
9310 if(!nsStr)
9311 return UA_STATUSCODE_BADOUTOFMEMORY;
9312 snprintfLen = UA_snprintf(s: nsStr, maxlen: 10, format: "ns=%d;", id->namespaceIndex);
9313 if(snprintfLen < 0 || snprintfLen >= 10) {
9314 UA_free(ptr: nsStr);
9315 return UA_STATUSCODE_BADINTERNALERROR;
9316 }
9317 nsLen = (size_t)(snprintfLen);
9318 }
9319
9320 UA_ByteString byteStr = UA_BYTESTRING_NULL;
9321 switch (id->identifierType) {
9322 case UA_NODEIDTYPE_NUMERIC:
9323 /* ns (2 byte, 65535) = 5 chars, numeric (4 byte, 4294967295) = 10
9324 * chars, delim = 1 , nullbyte = 1-> 17 chars */
9325 output->length = nsLen + 2 + 10 + 1;
9326 output->data = (UA_Byte*)UA_malloc(size: output->length);
9327 if(output->data == NULL) {
9328 output->length = 0;
9329 UA_free(ptr: nsStr);
9330 return UA_STATUSCODE_BADOUTOFMEMORY;
9331 }
9332 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%si=%lu",
9333 nsLen > 0 ? nsStr : "",
9334 (unsigned long )id->identifier.numeric);
9335 break;
9336 case UA_NODEIDTYPE_STRING:
9337 /* ns (16bit) = 5 chars, strlen + nullbyte */
9338 output->length = nsLen + 2 + id->identifier.string.length + 1;
9339 output->data = (UA_Byte*)UA_malloc(size: output->length);
9340 if(output->data == NULL) {
9341 output->length = 0;
9342 UA_free(ptr: nsStr);
9343 return UA_STATUSCODE_BADOUTOFMEMORY;
9344 }
9345 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%ss=%.*s",
9346 nsLen > 0 ? nsStr : "", (int)id->identifier.string.length,
9347 id->identifier.string.data);
9348 break;
9349 case UA_NODEIDTYPE_GUID:
9350 /* ns (16bit) = 5 chars + strlen(A123456C-0ABC-1A2B-815F-687212AAEE1B)=36 + nullbyte */
9351 output->length = nsLen + 2 + 36 + 1;
9352 output->data = (UA_Byte*)UA_malloc(size: output->length);
9353 if(output->data == NULL) {
9354 output->length = 0;
9355 UA_free(ptr: nsStr);
9356 return UA_STATUSCODE_BADOUTOFMEMORY;
9357 }
9358 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length,
9359 format: "%sg=" UA_PRINTF_GUID_FORMAT, nsLen > 0 ? nsStr : "",
9360 UA_PRINTF_GUID_DATA(id->identifier.guid));
9361 break;
9362 case UA_NODEIDTYPE_BYTESTRING:
9363 UA_ByteString_toBase64(bs: &id->identifier.byteString, output: &byteStr);
9364 /* ns (16bit) = 5 chars + LEN + nullbyte */
9365 output->length = nsLen + 2 + byteStr.length + 1;
9366 output->data = (UA_Byte*)UA_malloc(size: output->length);
9367 if(output->data == NULL) {
9368 output->length = 0;
9369 UA_String_clear(p: &byteStr);
9370 UA_free(ptr: nsStr);
9371 return UA_STATUSCODE_BADOUTOFMEMORY;
9372 }
9373 snprintfLen = UA_snprintf(s: (char*)output->data, maxlen: output->length, format: "%sb=%.*s",
9374 nsLen > 0 ? nsStr : "",
9375 (int)byteStr.length, byteStr.data);
9376 UA_String_clear(p: &byteStr);
9377 break;
9378 }
9379 UA_free(ptr: nsStr);
9380
9381 if(snprintfLen < 0 || snprintfLen >= (long) output->length) {
9382 UA_free(ptr: output->data);
9383 output->data = NULL;
9384 output->length = 0;
9385 return UA_STATUSCODE_BADINTERNALERROR;
9386 }
9387 output->length = (size_t)snprintfLen;
9388
9389 return UA_STATUSCODE_GOOD;
9390}
9391
9392UA_StatusCode
9393UA_ExpandedNodeId_print(const UA_ExpandedNodeId *id, UA_String *output) {
9394 /* Don't print the namespace-index if a NamespaceUri is set */
9395 UA_NodeId nid = id->nodeId;
9396 if(id->namespaceUri.data != NULL)
9397 nid.namespaceIndex = 0;
9398
9399 /* Encode the NodeId */
9400 UA_String outNid = UA_STRING_NULL;
9401 UA_StatusCode res = UA_NodeId_print(id: &nid, output: &outNid);
9402 if(res != UA_STATUSCODE_GOOD)
9403 return res;
9404
9405 /* Encode the ServerIndex */
9406 char svr[100];
9407 if(id->serverIndex == 0)
9408 svr[0] = 0;
9409 else
9410 UA_snprintf(s: svr, maxlen: 100, format: "svr=%"PRIu32";", id->serverIndex);
9411 size_t svrlen = strlen(s: svr);
9412
9413 /* Encode the NamespaceUri */
9414 char nsu[100];
9415 if(id->namespaceUri.data == NULL)
9416 nsu[0] = 0;
9417 else
9418 UA_snprintf(s: nsu, maxlen: 100, format: "nsu=%.*s;", (int)id->namespaceUri.length, id->namespaceUri.data);
9419 size_t nsulen = strlen(s: nsu);
9420
9421 /* Combine everything */
9422 res = UA_ByteString_allocBuffer(bs: (UA_String*)output, length: outNid.length + svrlen + nsulen);
9423 if(res == UA_STATUSCODE_GOOD) {
9424 memcpy(dest: output->data, src: svr, n: svrlen);
9425 memcpy(dest: &output->data[svrlen], src: nsu, n: nsulen);
9426 memcpy(dest: &output->data[svrlen+nsulen], src: outNid.data, n: outNid.length);
9427 }
9428
9429 UA_String_clear(p: &outNid);
9430 return res;
9431}
9432
9433#ifdef UA_ENABLE_TYPEDESCRIPTION
9434
9435/***********************/
9436/* Jumptable Signature */
9437/***********************/
9438
9439typedef struct UA_PrintElement {
9440 TAILQ_ENTRY(UA_PrintElement) next;
9441 size_t length;
9442 UA_Byte data[];
9443} UA_PrintOutput;
9444
9445typedef struct {
9446 size_t depth;
9447 TAILQ_HEAD(, UA_PrintElement) outputs;
9448} UA_PrintContext;
9449
9450typedef UA_StatusCode
9451(*UA_printSignature)(UA_PrintContext *ctx, const void *p,
9452 const UA_DataType *type);
9453
9454extern const UA_printSignature printJumpTable[UA_DATATYPEKINDS];
9455
9456/********************/
9457/* Helper Functions */
9458/********************/
9459
9460static UA_PrintOutput *
9461UA_PrintContext_addOutput(UA_PrintContext *ctx, size_t length) {
9462 /* Protect against overlong output in pretty-printing */
9463 if(length > 2<<16)
9464 return NULL;
9465 UA_PrintOutput *output = (UA_PrintOutput*)UA_malloc(size: sizeof(UA_PrintOutput) + length + 1);
9466 if(!output)
9467 return NULL;
9468 output->length = length;
9469 TAILQ_INSERT_TAIL(&ctx->outputs, output, next);
9470 return output;
9471}
9472
9473static UA_StatusCode
9474UA_PrintContext_addNewlineTabs(UA_PrintContext *ctx, size_t tabs) {
9475 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: tabs+1);
9476 if(!out)
9477 return UA_STATUSCODE_BADOUTOFMEMORY;
9478 out->data[0] = '\n';
9479 for(size_t i = 1; i <= tabs; i++)
9480 out->data[i] = '\t';
9481 return UA_STATUSCODE_GOOD;
9482}
9483
9484static UA_StatusCode
9485UA_PrintContext_addName(UA_PrintContext *ctx, const char *name) {
9486 size_t nameLen = strlen(s: name);
9487 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: nameLen+2);
9488 if(!out)
9489 return UA_STATUSCODE_BADOUTOFMEMORY;
9490 memcpy(dest: &out->data, src: name, n: nameLen);
9491 out->data[nameLen] = ':';
9492 out->data[nameLen+1] = ' ';
9493 return UA_STATUSCODE_GOOD;
9494}
9495
9496static UA_StatusCode
9497UA_PrintContext_addString(UA_PrintContext *ctx, const char *str) {
9498 size_t len = strlen(s: str);
9499 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: len);
9500 if(!out)
9501 return UA_STATUSCODE_BADOUTOFMEMORY;
9502 memcpy(dest: &out->data, src: str, n: len);
9503 return UA_STATUSCODE_GOOD;
9504}
9505
9506/*********************/
9507/* Printing Routines */
9508/*********************/
9509
9510static UA_StatusCode
9511printArray(UA_PrintContext *ctx, const void *p, const size_t length,
9512 const UA_DataType *type);
9513
9514static UA_StatusCode
9515printBoolean(UA_PrintContext *ctx, const UA_Boolean *p, const UA_DataType *_) {
9516 if(*p)
9517 return UA_PrintContext_addString(ctx, str: "true");
9518 return UA_PrintContext_addString(ctx, str: "false");
9519}
9520
9521static UA_StatusCode
9522printSByte(UA_PrintContext *ctx, const UA_SByte *p, const UA_DataType *_) {
9523 char out[32];
9524 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi8, *p);
9525 return UA_PrintContext_addString(ctx, str: out);
9526}
9527
9528static UA_StatusCode
9529printByte(UA_PrintContext *ctx, const UA_Byte *p, const UA_DataType *_) {
9530 char out[32];
9531 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu8, *p);
9532 return UA_PrintContext_addString(ctx, str: out);
9533}
9534
9535static UA_StatusCode
9536printInt16(UA_PrintContext *ctx, const UA_Int16 *p, const UA_DataType *_) {
9537 char out[32];
9538 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi16, *p);
9539 return UA_PrintContext_addString(ctx, str: out);
9540}
9541
9542static UA_StatusCode
9543printUInt16(UA_PrintContext *ctx, const UA_UInt16 *p, const UA_DataType *_) {
9544 char out[32];
9545 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu16, *p);
9546 return UA_PrintContext_addString(ctx, str: out);
9547}
9548
9549static UA_StatusCode
9550printInt32(UA_PrintContext *ctx, const UA_Int32 *p, const UA_DataType *_) {
9551 char out[32];
9552 UA_snprintf(s: out, maxlen: 32, format: "%"PRIi32, *p);
9553 return UA_PrintContext_addString(ctx, str: out);
9554}
9555
9556static UA_StatusCode
9557printUInt32(UA_PrintContext *ctx, const UA_UInt32 *p, const UA_DataType *_) {
9558 char out[32];
9559 UA_snprintf(s: out, maxlen: 32, format: "%"PRIu32, *p);
9560 return UA_PrintContext_addString(ctx, str: out);
9561}
9562
9563static UA_StatusCode
9564printInt64(UA_PrintContext *ctx, const UA_Int64 *p, const UA_DataType *_) {
9565 char out[64];
9566 UA_snprintf(s: out, maxlen: 64, format: "%"PRIi64, *p);
9567 return UA_PrintContext_addString(ctx, str: out);
9568}
9569
9570static UA_StatusCode
9571printUInt64(UA_PrintContext *ctx, const UA_UInt64 *p, const UA_DataType *_) {
9572 char out[64];
9573 UA_snprintf(s: out, maxlen: 64, format: "%"PRIu64, *p);
9574 return UA_PrintContext_addString(ctx, str: out);
9575}
9576
9577static UA_StatusCode
9578printFloat(UA_PrintContext *ctx, const UA_Float *p, const UA_DataType *_) {
9579 char out[64];
9580 UA_snprintf(s: out, maxlen: 32, format: "%f", *p);
9581 return UA_PrintContext_addString(ctx, str: out);
9582}
9583
9584static UA_StatusCode
9585printDouble(UA_PrintContext *ctx, const UA_Double *p, const UA_DataType *_) {
9586 char out[64];
9587 UA_snprintf(s: out, maxlen: 64, format: "%lf", *p);
9588 return UA_PrintContext_addString(ctx, str: out);
9589}
9590
9591static UA_StatusCode
9592printStatusCode(UA_PrintContext *ctx, const UA_StatusCode *p, const UA_DataType *_) {
9593 return UA_PrintContext_addString(ctx, str: UA_StatusCode_name(code: *p));
9594}
9595
9596static UA_StatusCode
9597printNodeId(UA_PrintContext *ctx, const UA_NodeId *p, const UA_DataType *_) {
9598 UA_String out;
9599 UA_String_init(p: &out);
9600 UA_StatusCode res = UA_NodeId_print(id: p, output: &out);
9601 if(res != UA_STATUSCODE_GOOD)
9602 return res;
9603 UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, length: out.length);
9604 if(po)
9605 memcpy(dest: po->data, src: out.data, n: out.length);
9606 else
9607 res = UA_STATUSCODE_BADOUTOFMEMORY;
9608 UA_String_clear(p: &out);
9609 return res;
9610}
9611
9612static UA_StatusCode
9613printExpandedNodeId(UA_PrintContext *ctx, const UA_ExpandedNodeId *p, const UA_DataType *_) {
9614 UA_String out;
9615 UA_String_init(p: &out);
9616 UA_StatusCode res = UA_ExpandedNodeId_print(id: p, output: &out);
9617 if(res != UA_STATUSCODE_GOOD)
9618 return res;
9619 UA_PrintOutput *po = UA_PrintContext_addOutput(ctx, length: out.length);
9620 if(!po)
9621 return UA_STATUSCODE_BADOUTOFMEMORY;
9622 memcpy(dest: po->data, src: out.data, n: out.length);
9623 UA_String_clear(p: &out);
9624 return UA_STATUSCODE_GOOD;
9625}
9626
9627static UA_StatusCode
9628printDateTime(UA_PrintContext *ctx, const UA_DateTime *p, const UA_DataType *_) {
9629 UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
9630 UA_DateTimeStruct dts = UA_DateTime_toStruct(t: *p);
9631 char dateString[100];
9632 UA_snprintf(s: (char*)dateString, maxlen: 100,
9633 format: "%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)",
9634 dts.year, dts.month, dts.day, dts.hour, dts.min,
9635 dts.sec, dts.milliSec,
9636 (int)(tOffset / UA_DATETIME_SEC / 36));
9637 return UA_PrintContext_addString(ctx, str: dateString);
9638}
9639
9640static UA_StatusCode
9641printGuid(UA_PrintContext *ctx, const UA_Guid *p, const UA_DataType *_) {
9642 char tmp[100];
9643 UA_snprintf(s: tmp, maxlen: 100, UA_PRINTF_GUID_FORMAT, UA_PRINTF_GUID_DATA(*p));
9644 return UA_PrintContext_addString(ctx, str: tmp);
9645}
9646
9647static UA_StatusCode
9648printString(UA_PrintContext *ctx, const UA_String *p, const UA_DataType *_) {
9649 if(!p->data)
9650 return UA_PrintContext_addString(ctx, str: "NullString");
9651 UA_PrintOutput *out = UA_PrintContext_addOutput(ctx, length: p->length+2);
9652 if(!out)
9653 return UA_STATUSCODE_BADOUTOFMEMORY;
9654 UA_snprintf(s: (char*)out->data, maxlen: p->length+3, format: "\"%.*s\"", (int)p->length, p->data);
9655 return UA_STATUSCODE_GOOD;
9656}
9657
9658static UA_StatusCode
9659printByteString(UA_PrintContext *ctx, const UA_ByteString *p, const UA_DataType *_) {
9660 if(!p->data)
9661 return UA_PrintContext_addString(ctx, str: "NullByteString");
9662 UA_String str = UA_BYTESTRING_NULL;
9663 UA_StatusCode res = UA_ByteString_toBase64(bs: p, output: &str);
9664 if(res != UA_STATUSCODE_GOOD)
9665 return res;
9666 res = printString(ctx, p: &str, NULL);
9667 UA_String_clear(p: &str);
9668 return res;
9669}
9670
9671static UA_StatusCode
9672printQualifiedName(UA_PrintContext *ctx, const UA_QualifiedName *p, const UA_DataType *_) {
9673 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9674 retval |= UA_PrintContext_addString(ctx, str: "{");
9675 ctx->depth++;
9676 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9677 retval |= UA_PrintContext_addName(ctx, name: "NamespaceIndex");
9678 retval |= printUInt16(ctx, p: &p->namespaceIndex, NULL);
9679 retval |= UA_PrintContext_addString(ctx, str: ",");
9680 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9681 retval |= UA_PrintContext_addName(ctx, name: "Name");
9682 retval |= printString(ctx, p: &p->name, NULL);
9683 ctx->depth--;
9684 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9685 retval |= UA_PrintContext_addString(ctx, str: "}");
9686 return retval;
9687}
9688
9689static UA_StatusCode
9690printLocalizedText(UA_PrintContext *ctx, const UA_LocalizedText *p, const UA_DataType *_) {
9691 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9692 retval |= UA_PrintContext_addString(ctx, str: "{");
9693 ctx->depth++;
9694 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9695 retval |= UA_PrintContext_addName(ctx, name: "Locale");
9696 retval |= printString(ctx, p: &p->locale, NULL);
9697 retval |= UA_PrintContext_addString(ctx, str: ",");
9698 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9699 retval |= UA_PrintContext_addName(ctx, name: "Text");
9700 retval |= printString(ctx, p: &p->text, NULL);
9701 ctx->depth--;
9702 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9703 retval |= UA_PrintContext_addString(ctx, str: "}");
9704 return retval;
9705}
9706
9707static UA_StatusCode
9708printVariant(UA_PrintContext *ctx, const UA_Variant *p, const UA_DataType *_) {
9709 if(!p->type)
9710 return UA_PrintContext_addString(ctx, str: "NullVariant");
9711
9712 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9713 retval |= UA_PrintContext_addString(ctx, str: "{");
9714 ctx->depth++;
9715
9716 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9717 retval |= UA_PrintContext_addName(ctx, name: "DataType");
9718 retval |= UA_PrintContext_addString(ctx, str: p->type->typeName);
9719 retval |= UA_PrintContext_addString(ctx, str: ",");
9720
9721 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9722 retval |= UA_PrintContext_addName(ctx, name: "Value");
9723 if(UA_Variant_isScalar(v: p))
9724 retval |= printJumpTable[p->type->typeKind](ctx, p->data, p->type);
9725 else
9726 retval |= printArray(ctx, p: p->data, length: p->arrayLength, type: p->type);
9727
9728 if(p->arrayDimensionsSize > 0) {
9729 retval |= UA_PrintContext_addString(ctx, str: ",");
9730 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9731 retval |= UA_PrintContext_addName(ctx, name: "ArrayDimensions");
9732 retval |= printArray(ctx, p: p->arrayDimensions, length: p->arrayDimensionsSize,
9733 type: &UA_TYPES[UA_TYPES_UINT32]);
9734 }
9735
9736 ctx->depth--;
9737 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9738 retval |= UA_PrintContext_addString(ctx, str: "}");
9739 return retval;
9740}
9741
9742static UA_StatusCode
9743printExtensionObject(UA_PrintContext *ctx, const UA_ExtensionObject*p,
9744 const UA_DataType *_) {
9745 UA_StatusCode res = UA_STATUSCODE_GOOD;
9746 switch(p->encoding) {
9747 case UA_EXTENSIONOBJECT_ENCODED_NOBODY:
9748 return UA_PrintContext_addString(ctx, str: "ExtensionObject(No Body)");
9749 case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING:
9750 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject(Binary Encoded) {");
9751 ctx->depth++;
9752 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9753 res |= UA_PrintContext_addName(ctx, name: "DataType");
9754 res |= printNodeId(ctx, p: &p->content.encoded.typeId, NULL);
9755 res |= UA_PrintContext_addString(ctx, str: ",");
9756 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9757 res |= UA_PrintContext_addName(ctx, name: "Body");
9758 res |= printByteString(ctx, p: &p->content.encoded.body, NULL);
9759 ctx->depth--;
9760 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9761 res |= UA_PrintContext_addName(ctx, name: "}");
9762 break;
9763 case UA_EXTENSIONOBJECT_ENCODED_XML:
9764 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject(XML Encoded) {");
9765 ctx->depth++;
9766 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9767 res |= UA_PrintContext_addName(ctx, name: "DataType");
9768 res |= printNodeId(ctx, p: &p->content.encoded.typeId, NULL);
9769 res |= UA_PrintContext_addString(ctx, str: ",");
9770 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9771 res |= UA_PrintContext_addName(ctx, name: "Body");
9772 res |= printString(ctx, p: (const UA_String*)&p->content.encoded.body, NULL);
9773 ctx->depth--;
9774 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9775 res |= UA_PrintContext_addName(ctx, name: "}");
9776 break;
9777 case UA_EXTENSIONOBJECT_DECODED:
9778 case UA_EXTENSIONOBJECT_DECODED_NODELETE:
9779 res |= UA_PrintContext_addString(ctx, str: "ExtensionObject {");
9780 ctx->depth++;
9781 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9782 res |= UA_PrintContext_addName(ctx, name: "DataType");
9783 res |= UA_PrintContext_addString(ctx, str: p->content.decoded.type->typeName);
9784 res |= UA_PrintContext_addString(ctx, str: ",");
9785 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9786 res |= UA_PrintContext_addName(ctx, name: "Body");
9787 res |= printJumpTable[p->content.decoded.type->typeKind](ctx,
9788 p->content.decoded.data,
9789 p->content.decoded.type);
9790 ctx->depth--;
9791 res |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9792 res |= UA_PrintContext_addName(ctx, name: "}");
9793 break;
9794 default:
9795 res = UA_STATUSCODE_BADINTERNALERROR;
9796 break;
9797 }
9798 return res;
9799}
9800
9801static UA_StatusCode
9802printDataValue(UA_PrintContext *ctx, const UA_DataValue *p, const UA_DataType *_) {
9803 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9804 retval |= UA_PrintContext_addString(ctx, str: "{");
9805 ctx->depth++;
9806 UA_Boolean comma = false;
9807
9808 if(p->hasValue) {
9809 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9810 retval |= UA_PrintContext_addName(ctx, name: "Value");
9811 retval |= printVariant(ctx, p: &p->value, NULL);
9812 comma = true;
9813 }
9814
9815 if(p->hasStatus) {
9816 if(comma)
9817 retval |= UA_PrintContext_addString(ctx, str: ",");
9818 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9819 retval |= UA_PrintContext_addName(ctx, name: "Status");
9820 retval |= printStatusCode(ctx, p: &p->status, NULL);
9821 comma = true;
9822 }
9823
9824 if(p->hasSourceTimestamp) {
9825 if(comma)
9826 retval |= UA_PrintContext_addString(ctx, str: ",");
9827 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9828 retval |= UA_PrintContext_addName(ctx, name: "SourceTimestamp");
9829 retval |= printDateTime(ctx, p: &p->sourceTimestamp, NULL);
9830 comma = true;
9831 }
9832
9833 if(p->hasSourcePicoseconds) {
9834 if(comma)
9835 retval |= UA_PrintContext_addString(ctx, str: ",");
9836 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9837 retval |= UA_PrintContext_addName(ctx, name: "SourcePicoseconds");
9838 retval |= printUInt16(ctx, p: &p->sourcePicoseconds, NULL);
9839 comma = true;
9840 }
9841
9842 if(p->hasServerTimestamp) {
9843 if(comma)
9844 retval |= UA_PrintContext_addString(ctx, str: ",");
9845 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9846 retval |= UA_PrintContext_addName(ctx, name: "ServerTimestamp");
9847 retval |= printDateTime(ctx, p: &p->serverTimestamp, NULL);
9848 comma = true;
9849 }
9850
9851 if(p->hasServerPicoseconds) {
9852 if(comma)
9853 retval |= UA_PrintContext_addString(ctx, str: ",");
9854 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9855 retval |= UA_PrintContext_addName(ctx, name: "ServerPicoseconds");
9856 retval |= printUInt16(ctx, p: &p->serverPicoseconds, NULL);
9857 comma = true;
9858 }
9859
9860 ctx->depth--;
9861 if(comma) {
9862 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9863 retval |= UA_PrintContext_addString(ctx, str: "}");
9864 } else {
9865 retval |= UA_PrintContext_addString(ctx, str: " }");
9866 }
9867 return retval;
9868}
9869
9870static UA_StatusCode
9871printDiagnosticInfo(UA_PrintContext *ctx, const UA_DiagnosticInfo *p, const UA_DataType *_) {
9872 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9873 retval |= UA_PrintContext_addString(ctx, str: "{");
9874 ctx->depth++;
9875 UA_Boolean comma = false;
9876
9877 if(p->hasSymbolicId) {
9878 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9879 retval |= UA_PrintContext_addName(ctx, name: "SymbolicId");
9880 retval |= printInt32(ctx, p: &p->symbolicId, NULL);
9881 comma = true;
9882 }
9883
9884 if(p->hasNamespaceUri) {
9885 if(comma)
9886 retval |= UA_PrintContext_addString(ctx, str: ",");
9887 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9888 retval |= UA_PrintContext_addName(ctx, name: "NamespaceUri");
9889 retval |= printInt32(ctx, p: &p->namespaceUri, NULL);
9890 comma = true;
9891 }
9892
9893 if(p->hasLocalizedText) {
9894 if(comma)
9895 retval |= UA_PrintContext_addString(ctx, str: ",");
9896 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9897 retval |= UA_PrintContext_addName(ctx, name: "LocalizedText");
9898 retval |= printInt32(ctx, p: &p->localizedText, NULL);
9899 comma = true;
9900 }
9901
9902 if(p->hasLocale) {
9903 if(comma)
9904 retval |= UA_PrintContext_addString(ctx, str: ",");
9905 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9906 retval |= UA_PrintContext_addName(ctx, name: "Locale");
9907 retval |= printInt32(ctx, p: &p->locale, NULL);
9908 comma = true;
9909 }
9910
9911 if(p->hasAdditionalInfo) {
9912 if(comma)
9913 retval |= UA_PrintContext_addString(ctx, str: ",");
9914 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9915 retval |= UA_PrintContext_addName(ctx, name: "AdditionalInfo");
9916 retval |= printString(ctx, p: &p->additionalInfo, NULL);
9917 comma = true;
9918 }
9919
9920 if(p->hasInnerStatusCode) {
9921 if(comma)
9922 retval |= UA_PrintContext_addString(ctx, str: ",");
9923 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9924 retval |= UA_PrintContext_addName(ctx, name: "InnerStatusCode");
9925 retval |= printStatusCode(ctx, p: &p->innerStatusCode, NULL);
9926 comma = true;
9927 }
9928
9929 if(p->hasInnerDiagnosticInfo) {
9930 if(comma)
9931 retval |= UA_PrintContext_addString(ctx, str: ",");
9932 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9933 retval |= UA_PrintContext_addName(ctx, name: "InnerDiagnosticInfo");
9934 retval |= printDiagnosticInfo(ctx, p: p->innerDiagnosticInfo, NULL);
9935 comma = true;
9936 }
9937
9938 ctx->depth--;
9939 if(comma) {
9940 retval |= UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9941 retval |= UA_PrintContext_addString(ctx, str: "}");
9942 } else {
9943 retval |= UA_PrintContext_addString(ctx, str: " }");
9944 }
9945 return retval;
9946}
9947
9948static UA_StatusCode
9949printArray(UA_PrintContext *ctx, const void *p, const size_t length,
9950 const UA_DataType *type) {
9951 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9952 if(!p) {
9953 retval |= UA_PrintContext_addString(ctx, str: "Array(-1, ");
9954 retval |= UA_PrintContext_addString(ctx, str: type->typeName);
9955 retval |= UA_PrintContext_addString(ctx, str: ")");
9956 return retval;
9957 }
9958
9959 UA_UInt32 length32 = (UA_UInt32)length;
9960 retval |= UA_PrintContext_addString(ctx, str: "Array(");
9961 retval |= printUInt32(ctx, p: &length32, NULL);
9962 retval |= UA_PrintContext_addString(ctx, str: ", ");
9963 retval |= UA_PrintContext_addString(ctx, str: type->typeName);
9964 retval |= UA_PrintContext_addString(ctx, str: ") {");
9965 ctx->depth++;
9966 uintptr_t target = (uintptr_t)p;
9967 for(UA_UInt32 i = 0; i < length; i++) {
9968 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9969 printUInt32(ctx, p: &i, NULL);
9970 retval |= UA_PrintContext_addString(ctx, str: ": ");
9971 printJumpTable[type->typeKind](ctx, (const void*)target, type);
9972 if(i < length - 1)
9973 retval |= UA_PrintContext_addString(ctx, str: ",");
9974 target += type->memSize;
9975 }
9976 ctx->depth--;
9977 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9978 retval |= UA_PrintContext_addString(ctx, str: "}");
9979 return retval;
9980}
9981
9982static UA_StatusCode
9983printStructure(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
9984 UA_StatusCode retval = UA_STATUSCODE_GOOD;
9985 uintptr_t ptrs = (uintptr_t)p;
9986 retval |= UA_PrintContext_addString(ctx, str: "{");
9987 ctx->depth++;
9988 for(size_t i = 0; i < type->membersSize; ++i) {
9989 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
9990 const UA_DataTypeMember *m = &type->members[i];
9991 const UA_DataType *mt = m->memberType;
9992 ptrs += m->padding;
9993 retval |= UA_PrintContext_addName(ctx, name: m->memberName);
9994 if(!m->isArray) {
9995 retval |= printJumpTable[mt->typeKind](ctx, (const void *)ptrs, mt);
9996 ptrs += mt->memSize;
9997 } else {
9998 const size_t size = *((const size_t*)ptrs);
9999 ptrs += sizeof(size_t);
10000 retval |= printArray(ctx, p: *(void* const*)ptrs, length: size, type: mt);
10001 ptrs += sizeof(void*);
10002 }
10003 if(i < (size_t)(type->membersSize - 1))
10004 retval |= UA_PrintContext_addString(ctx, str: ",");
10005 }
10006 ctx->depth--;
10007 UA_PrintContext_addNewlineTabs(ctx, tabs: ctx->depth);
10008 retval |= UA_PrintContext_addString(ctx, str: "}");
10009 return retval;
10010}
10011
10012static UA_StatusCode
10013printNotImplemented(UA_PrintContext *ctx, const void *p, const UA_DataType *type) {
10014 UA_StatusCode res = UA_STATUSCODE_GOOD;
10015 res |= UA_PrintContext_addString(ctx, str: type->typeName);
10016 res |= UA_PrintContext_addString(ctx, str: " (Printing Not Implemented)");
10017 return res;
10018}
10019
10020const UA_printSignature printJumpTable[UA_DATATYPEKINDS] = {
10021 (UA_printSignature)printBoolean,
10022 (UA_printSignature)printSByte,
10023 (UA_printSignature)printByte,
10024 (UA_printSignature)printInt16,
10025 (UA_printSignature)printUInt16,
10026 (UA_printSignature)printInt32,
10027 (UA_printSignature)printUInt32,
10028 (UA_printSignature)printInt64,
10029 (UA_printSignature)printUInt64,
10030 (UA_printSignature)printFloat,
10031 (UA_printSignature)printDouble,
10032 (UA_printSignature)printString,
10033 (UA_printSignature)printDateTime,
10034 (UA_printSignature)printGuid,
10035 (UA_printSignature)printByteString,
10036 (UA_printSignature)printString, /* XmlElement */
10037 (UA_printSignature)printNodeId,
10038 (UA_printSignature)printExpandedNodeId,
10039 (UA_printSignature)printStatusCode,
10040 (UA_printSignature)printQualifiedName,
10041 (UA_printSignature)printLocalizedText,
10042 (UA_printSignature)printExtensionObject,
10043 (UA_printSignature)printDataValue,
10044 (UA_printSignature)printVariant,
10045 (UA_printSignature)printDiagnosticInfo,
10046 (UA_printSignature)printNotImplemented, /* Decimal */
10047 (UA_printSignature)printUInt32, /* Enumeration */
10048 (UA_printSignature)printStructure,
10049 (UA_printSignature)printNotImplemented, /* Structure with Optional Fields */
10050 (UA_printSignature)printNotImplemented, /* Union */
10051 (UA_printSignature)printNotImplemented /* BitfieldCluster*/
10052};
10053
10054UA_StatusCode
10055UA_print(const void *p, const UA_DataType *type, UA_String *output) {
10056 UA_PrintContext ctx;
10057 ctx.depth = 0;
10058 TAILQ_INIT(&ctx.outputs);
10059
10060 /* Encode */
10061 UA_StatusCode retval = printJumpTable[type->typeKind](&ctx, p, type);
10062
10063 /* Allocate memory for the output */
10064 if(retval == UA_STATUSCODE_GOOD) {
10065 size_t total = 0;
10066 UA_PrintOutput *out;
10067 TAILQ_FOREACH(out, &ctx.outputs, next)
10068 total += out->length;
10069 retval = UA_ByteString_allocBuffer(bs: (UA_String*)output, length: total);
10070 }
10071
10072 /* Write the output */
10073 if(retval == UA_STATUSCODE_GOOD) {
10074 size_t pos = 0;
10075 UA_PrintOutput *out;
10076 TAILQ_FOREACH(out, &ctx.outputs, next) {
10077 memcpy(dest: &output->data[pos], src: out->data, n: out->length);
10078 pos += out->length;
10079 }
10080 }
10081
10082 /* Free the context */
10083 UA_PrintOutput *o, *o2;
10084 TAILQ_FOREACH_SAFE(o, &ctx.outputs, next, o2) {
10085 TAILQ_REMOVE(&ctx.outputs, o, next);
10086 UA_free(ptr: o);
10087 }
10088 return retval;
10089}
10090
10091#endif /* UA_ENABLE_TYPEDESCRIPTION */
10092
10093/**** amalgamated original file "/build/src_generated/open62541/types_generated.c" ****/
10094
10095/**********************************
10096 * Autogenerated -- do not modify *
10097 **********************************/
10098
10099
10100/* Boolean */
10101#define Boolean_members NULL
10102
10103/* SByte */
10104#define SByte_members NULL
10105
10106/* Byte */
10107#define Byte_members NULL
10108
10109/* Int16 */
10110#define Int16_members NULL
10111
10112/* UInt16 */
10113#define UInt16_members NULL
10114
10115/* Int32 */
10116#define Int32_members NULL
10117
10118/* UInt32 */
10119#define UInt32_members NULL
10120
10121/* Int64 */
10122#define Int64_members NULL
10123
10124/* UInt64 */
10125#define UInt64_members NULL
10126
10127/* Float */
10128#define Float_members NULL
10129
10130/* Double */
10131#define Double_members NULL
10132
10133/* String */
10134#define String_members NULL
10135
10136/* DateTime */
10137#define DateTime_members NULL
10138
10139/* Guid */
10140#define Guid_members NULL
10141
10142/* ByteString */
10143#define ByteString_members NULL
10144
10145/* XmlElement */
10146#define XmlElement_members NULL
10147
10148/* NodeId */
10149#define NodeId_members NULL
10150
10151/* ExpandedNodeId */
10152#define ExpandedNodeId_members NULL
10153
10154/* StatusCode */
10155#define StatusCode_members NULL
10156
10157/* QualifiedName */
10158#define QualifiedName_members NULL
10159
10160/* LocalizedText */
10161#define LocalizedText_members NULL
10162
10163/* ExtensionObject */
10164#define ExtensionObject_members NULL
10165
10166/* DataValue */
10167#define DataValue_members NULL
10168
10169/* Variant */
10170#define Variant_members NULL
10171
10172/* DiagnosticInfo */
10173#define DiagnosticInfo_members NULL
10174
10175/* KeyValuePair */
10176static UA_DataTypeMember KeyValuePair_members[2] = {
10177{
10178 UA_TYPENAME("Key") /* .memberName */
10179 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
10180 0, /* .padding */
10181 false, /* .isArray */
10182 false /* .isOptional */
10183},
10184{
10185 UA_TYPENAME("Value") /* .memberName */
10186 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
10187 offsetof(UA_KeyValuePair, value) - offsetof(UA_KeyValuePair, key) - sizeof(UA_QualifiedName), /* .padding */
10188 false, /* .isArray */
10189 false /* .isOptional */
10190},};
10191
10192/* NodeClass */
10193#define NodeClass_members NULL
10194
10195/* StructureType */
10196#define StructureType_members NULL
10197
10198/* StructureField */
10199static UA_DataTypeMember StructureField_members[7] = {
10200{
10201 UA_TYPENAME("Name") /* .memberName */
10202 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10203 0, /* .padding */
10204 false, /* .isArray */
10205 false /* .isOptional */
10206},
10207{
10208 UA_TYPENAME("Description") /* .memberName */
10209 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10210 offsetof(UA_StructureField, description) - offsetof(UA_StructureField, name) - sizeof(UA_String), /* .padding */
10211 false, /* .isArray */
10212 false /* .isOptional */
10213},
10214{
10215 UA_TYPENAME("DataType") /* .memberName */
10216 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10217 offsetof(UA_StructureField, dataType) - offsetof(UA_StructureField, description) - sizeof(UA_LocalizedText), /* .padding */
10218 false, /* .isArray */
10219 false /* .isOptional */
10220},
10221{
10222 UA_TYPENAME("ValueRank") /* .memberName */
10223 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
10224 offsetof(UA_StructureField, valueRank) - offsetof(UA_StructureField, dataType) - sizeof(UA_NodeId), /* .padding */
10225 false, /* .isArray */
10226 false /* .isOptional */
10227},
10228{
10229 UA_TYPENAME("ArrayDimensions") /* .memberName */
10230 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10231 offsetof(UA_StructureField, arrayDimensionsSize) - offsetof(UA_StructureField, valueRank) - sizeof(UA_Int32), /* .padding */
10232 true, /* .isArray */
10233 false /* .isOptional */
10234},
10235{
10236 UA_TYPENAME("MaxStringLength") /* .memberName */
10237 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10238 offsetof(UA_StructureField, maxStringLength) - offsetof(UA_StructureField, arrayDimensions) - sizeof(void *), /* .padding */
10239 false, /* .isArray */
10240 false /* .isOptional */
10241},
10242{
10243 UA_TYPENAME("IsOptional") /* .memberName */
10244 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
10245 offsetof(UA_StructureField, isOptional) - offsetof(UA_StructureField, maxStringLength) - sizeof(UA_UInt32), /* .padding */
10246 false, /* .isArray */
10247 false /* .isOptional */
10248},};
10249
10250/* StructureDefinition */
10251static UA_DataTypeMember StructureDefinition_members[4] = {
10252{
10253 UA_TYPENAME("DefaultEncodingId") /* .memberName */
10254 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10255 0, /* .padding */
10256 false, /* .isArray */
10257 false /* .isOptional */
10258},
10259{
10260 UA_TYPENAME("BaseDataType") /* .memberName */
10261 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10262 offsetof(UA_StructureDefinition, baseDataType) - offsetof(UA_StructureDefinition, defaultEncodingId) - sizeof(UA_NodeId), /* .padding */
10263 false, /* .isArray */
10264 false /* .isOptional */
10265},
10266{
10267 UA_TYPENAME("StructureType") /* .memberName */
10268 &UA_TYPES[UA_TYPES_STRUCTURETYPE], /* .memberType */
10269 offsetof(UA_StructureDefinition, structureType) - offsetof(UA_StructureDefinition, baseDataType) - sizeof(UA_NodeId), /* .padding */
10270 false, /* .isArray */
10271 false /* .isOptional */
10272},
10273{
10274 UA_TYPENAME("Fields") /* .memberName */
10275 &UA_TYPES[UA_TYPES_STRUCTUREFIELD], /* .memberType */
10276 offsetof(UA_StructureDefinition, fieldsSize) - offsetof(UA_StructureDefinition, structureType) - sizeof(UA_StructureType), /* .padding */
10277 true, /* .isArray */
10278 false /* .isOptional */
10279},};
10280
10281/* Argument */
10282static UA_DataTypeMember Argument_members[5] = {
10283{
10284 UA_TYPENAME("Name") /* .memberName */
10285 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10286 0, /* .padding */
10287 false, /* .isArray */
10288 false /* .isOptional */
10289},
10290{
10291 UA_TYPENAME("DataType") /* .memberName */
10292 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10293 offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String), /* .padding */
10294 false, /* .isArray */
10295 false /* .isOptional */
10296},
10297{
10298 UA_TYPENAME("ValueRank") /* .memberName */
10299 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
10300 offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId), /* .padding */
10301 false, /* .isArray */
10302 false /* .isOptional */
10303},
10304{
10305 UA_TYPENAME("ArrayDimensions") /* .memberName */
10306 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10307 offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32), /* .padding */
10308 true, /* .isArray */
10309 false /* .isOptional */
10310},
10311{
10312 UA_TYPENAME("Description") /* .memberName */
10313 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10314 offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void *), /* .padding */
10315 false, /* .isArray */
10316 false /* .isOptional */
10317},};
10318
10319/* EnumValueType */
10320static UA_DataTypeMember EnumValueType_members[3] = {
10321{
10322 UA_TYPENAME("Value") /* .memberName */
10323 &UA_TYPES[UA_TYPES_INT64], /* .memberType */
10324 0, /* .padding */
10325 false, /* .isArray */
10326 false /* .isOptional */
10327},
10328{
10329 UA_TYPENAME("DisplayName") /* .memberName */
10330 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10331 offsetof(UA_EnumValueType, displayName) - offsetof(UA_EnumValueType, value) - sizeof(UA_Int64), /* .padding */
10332 false, /* .isArray */
10333 false /* .isOptional */
10334},
10335{
10336 UA_TYPENAME("Description") /* .memberName */
10337 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10338 offsetof(UA_EnumValueType, description) - offsetof(UA_EnumValueType, displayName) - sizeof(UA_LocalizedText), /* .padding */
10339 false, /* .isArray */
10340 false /* .isOptional */
10341},};
10342
10343/* EnumField */
10344static UA_DataTypeMember EnumField_members[4] = {
10345{
10346 UA_TYPENAME("Value") /* .memberName */
10347 &UA_TYPES[UA_TYPES_INT64], /* .memberType */
10348 0, /* .padding */
10349 false, /* .isArray */
10350 false /* .isOptional */
10351},
10352{
10353 UA_TYPENAME("DisplayName") /* .memberName */
10354 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10355 offsetof(UA_EnumField, displayName) - offsetof(UA_EnumField, value) - sizeof(UA_Int64), /* .padding */
10356 false, /* .isArray */
10357 false /* .isOptional */
10358},
10359{
10360 UA_TYPENAME("Description") /* .memberName */
10361 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10362 offsetof(UA_EnumField, description) - offsetof(UA_EnumField, displayName) - sizeof(UA_LocalizedText), /* .padding */
10363 false, /* .isArray */
10364 false /* .isOptional */
10365},
10366{
10367 UA_TYPENAME("Name") /* .memberName */
10368 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10369 offsetof(UA_EnumField, name) - offsetof(UA_EnumField, description) - sizeof(UA_LocalizedText), /* .padding */
10370 false, /* .isArray */
10371 false /* .isOptional */
10372},};
10373
10374/* Duration */
10375#define Duration_members NULL
10376
10377/* UtcTime */
10378#define UtcTime_members NULL
10379
10380/* LocaleId */
10381#define LocaleId_members NULL
10382
10383/* TimeZoneDataType */
10384static UA_DataTypeMember TimeZoneDataType_members[2] = {
10385{
10386 UA_TYPENAME("Offset") /* .memberName */
10387 &UA_TYPES[UA_TYPES_INT16], /* .memberType */
10388 0, /* .padding */
10389 false, /* .isArray */
10390 false /* .isOptional */
10391},
10392{
10393 UA_TYPENAME("DaylightSavingInOffset") /* .memberName */
10394 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
10395 offsetof(UA_TimeZoneDataType, daylightSavingInOffset) - offsetof(UA_TimeZoneDataType, offset) - sizeof(UA_Int16), /* .padding */
10396 false, /* .isArray */
10397 false /* .isOptional */
10398},};
10399
10400/* ApplicationType */
10401#define ApplicationType_members NULL
10402
10403/* ApplicationDescription */
10404static UA_DataTypeMember ApplicationDescription_members[7] = {
10405{
10406 UA_TYPENAME("ApplicationUri") /* .memberName */
10407 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10408 0, /* .padding */
10409 false, /* .isArray */
10410 false /* .isOptional */
10411},
10412{
10413 UA_TYPENAME("ProductUri") /* .memberName */
10414 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10415 offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String), /* .padding */
10416 false, /* .isArray */
10417 false /* .isOptional */
10418},
10419{
10420 UA_TYPENAME("ApplicationName") /* .memberName */
10421 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
10422 offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String), /* .padding */
10423 false, /* .isArray */
10424 false /* .isOptional */
10425},
10426{
10427 UA_TYPENAME("ApplicationType") /* .memberName */
10428 &UA_TYPES[UA_TYPES_APPLICATIONTYPE], /* .memberType */
10429 offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText), /* .padding */
10430 false, /* .isArray */
10431 false /* .isOptional */
10432},
10433{
10434 UA_TYPENAME("GatewayServerUri") /* .memberName */
10435 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10436 offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType), /* .padding */
10437 false, /* .isArray */
10438 false /* .isOptional */
10439},
10440{
10441 UA_TYPENAME("DiscoveryProfileUri") /* .memberName */
10442 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10443 offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String), /* .padding */
10444 false, /* .isArray */
10445 false /* .isOptional */
10446},
10447{
10448 UA_TYPENAME("DiscoveryUrls") /* .memberName */
10449 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10450 offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String), /* .padding */
10451 true, /* .isArray */
10452 false /* .isOptional */
10453},};
10454
10455/* RequestHeader */
10456static UA_DataTypeMember RequestHeader_members[7] = {
10457{
10458 UA_TYPENAME("AuthenticationToken") /* .memberName */
10459 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
10460 0, /* .padding */
10461 false, /* .isArray */
10462 false /* .isOptional */
10463},
10464{
10465 UA_TYPENAME("Timestamp") /* .memberName */
10466 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10467 offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId), /* .padding */
10468 false, /* .isArray */
10469 false /* .isOptional */
10470},
10471{
10472 UA_TYPENAME("RequestHandle") /* .memberName */
10473 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10474 offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
10475 false, /* .isArray */
10476 false /* .isOptional */
10477},
10478{
10479 UA_TYPENAME("ReturnDiagnostics") /* .memberName */
10480 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10481 offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
10482 false, /* .isArray */
10483 false /* .isOptional */
10484},
10485{
10486 UA_TYPENAME("AuditEntryId") /* .memberName */
10487 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10488 offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32), /* .padding */
10489 false, /* .isArray */
10490 false /* .isOptional */
10491},
10492{
10493 UA_TYPENAME("TimeoutHint") /* .memberName */
10494 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10495 offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String), /* .padding */
10496 false, /* .isArray */
10497 false /* .isOptional */
10498},
10499{
10500 UA_TYPENAME("AdditionalHeader") /* .memberName */
10501 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
10502 offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32), /* .padding */
10503 false, /* .isArray */
10504 false /* .isOptional */
10505},};
10506
10507/* ResponseHeader */
10508static UA_DataTypeMember ResponseHeader_members[6] = {
10509{
10510 UA_TYPENAME("Timestamp") /* .memberName */
10511 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10512 0, /* .padding */
10513 false, /* .isArray */
10514 false /* .isOptional */
10515},
10516{
10517 UA_TYPENAME("RequestHandle") /* .memberName */
10518 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10519 offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime), /* .padding */
10520 false, /* .isArray */
10521 false /* .isOptional */
10522},
10523{
10524 UA_TYPENAME("ServiceResult") /* .memberName */
10525 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
10526 offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */
10527 false, /* .isArray */
10528 false /* .isOptional */
10529},
10530{
10531 UA_TYPENAME("ServiceDiagnostics") /* .memberName */
10532 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
10533 offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode), /* .padding */
10534 false, /* .isArray */
10535 false /* .isOptional */
10536},
10537{
10538 UA_TYPENAME("StringTable") /* .memberName */
10539 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10540 offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo), /* .padding */
10541 true, /* .isArray */
10542 false /* .isOptional */
10543},
10544{
10545 UA_TYPENAME("AdditionalHeader") /* .memberName */
10546 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
10547 offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void *), /* .padding */
10548 false, /* .isArray */
10549 false /* .isOptional */
10550},};
10551
10552/* ServiceFault */
10553static UA_DataTypeMember ServiceFault_members[1] = {
10554{
10555 UA_TYPENAME("ResponseHeader") /* .memberName */
10556 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10557 0, /* .padding */
10558 false, /* .isArray */
10559 false /* .isOptional */
10560},};
10561
10562/* FindServersRequest */
10563static UA_DataTypeMember FindServersRequest_members[4] = {
10564{
10565 UA_TYPENAME("RequestHeader") /* .memberName */
10566 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10567 0, /* .padding */
10568 false, /* .isArray */
10569 false /* .isOptional */
10570},
10571{
10572 UA_TYPENAME("EndpointUrl") /* .memberName */
10573 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10574 offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10575 false, /* .isArray */
10576 false /* .isOptional */
10577},
10578{
10579 UA_TYPENAME("LocaleIds") /* .memberName */
10580 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10581 offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10582 true, /* .isArray */
10583 false /* .isOptional */
10584},
10585{
10586 UA_TYPENAME("ServerUris") /* .memberName */
10587 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10588 offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void *), /* .padding */
10589 true, /* .isArray */
10590 false /* .isOptional */
10591},};
10592
10593/* FindServersResponse */
10594static UA_DataTypeMember FindServersResponse_members[2] = {
10595{
10596 UA_TYPENAME("ResponseHeader") /* .memberName */
10597 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10598 0, /* .padding */
10599 false, /* .isArray */
10600 false /* .isOptional */
10601},
10602{
10603 UA_TYPENAME("Servers") /* .memberName */
10604 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10605 offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10606 true, /* .isArray */
10607 false /* .isOptional */
10608},};
10609
10610/* MessageSecurityMode */
10611#define MessageSecurityMode_members NULL
10612
10613/* UserTokenType */
10614#define UserTokenType_members NULL
10615
10616/* UserTokenPolicy */
10617static UA_DataTypeMember UserTokenPolicy_members[5] = {
10618{
10619 UA_TYPENAME("PolicyId") /* .memberName */
10620 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10621 0, /* .padding */
10622 false, /* .isArray */
10623 false /* .isOptional */
10624},
10625{
10626 UA_TYPENAME("TokenType") /* .memberName */
10627 &UA_TYPES[UA_TYPES_USERTOKENTYPE], /* .memberType */
10628 offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String), /* .padding */
10629 false, /* .isArray */
10630 false /* .isOptional */
10631},
10632{
10633 UA_TYPENAME("IssuedTokenType") /* .memberName */
10634 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10635 offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType), /* .padding */
10636 false, /* .isArray */
10637 false /* .isOptional */
10638},
10639{
10640 UA_TYPENAME("IssuerEndpointUrl") /* .memberName */
10641 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10642 offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String), /* .padding */
10643 false, /* .isArray */
10644 false /* .isOptional */
10645},
10646{
10647 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
10648 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10649 offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String), /* .padding */
10650 false, /* .isArray */
10651 false /* .isOptional */
10652},};
10653
10654/* EndpointDescription */
10655static UA_DataTypeMember EndpointDescription_members[8] = {
10656{
10657 UA_TYPENAME("EndpointUrl") /* .memberName */
10658 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10659 0, /* .padding */
10660 false, /* .isArray */
10661 false /* .isOptional */
10662},
10663{
10664 UA_TYPENAME("Server") /* .memberName */
10665 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10666 offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String), /* .padding */
10667 false, /* .isArray */
10668 false /* .isOptional */
10669},
10670{
10671 UA_TYPENAME("ServerCertificate") /* .memberName */
10672 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10673 offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription), /* .padding */
10674 false, /* .isArray */
10675 false /* .isOptional */
10676},
10677{
10678 UA_TYPENAME("SecurityMode") /* .memberName */
10679 &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
10680 offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString), /* .padding */
10681 false, /* .isArray */
10682 false /* .isOptional */
10683},
10684{
10685 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
10686 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10687 offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
10688 false, /* .isArray */
10689 false /* .isOptional */
10690},
10691{
10692 UA_TYPENAME("UserIdentityTokens") /* .memberName */
10693 &UA_TYPES[UA_TYPES_USERTOKENPOLICY], /* .memberType */
10694 offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String), /* .padding */
10695 true, /* .isArray */
10696 false /* .isOptional */
10697},
10698{
10699 UA_TYPENAME("TransportProfileUri") /* .memberName */
10700 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10701 offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void *), /* .padding */
10702 false, /* .isArray */
10703 false /* .isOptional */
10704},
10705{
10706 UA_TYPENAME("SecurityLevel") /* .memberName */
10707 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
10708 offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String), /* .padding */
10709 false, /* .isArray */
10710 false /* .isOptional */
10711},};
10712
10713/* GetEndpointsRequest */
10714static UA_DataTypeMember GetEndpointsRequest_members[4] = {
10715{
10716 UA_TYPENAME("RequestHeader") /* .memberName */
10717 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10718 0, /* .padding */
10719 false, /* .isArray */
10720 false /* .isOptional */
10721},
10722{
10723 UA_TYPENAME("EndpointUrl") /* .memberName */
10724 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10725 offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10726 false, /* .isArray */
10727 false /* .isOptional */
10728},
10729{
10730 UA_TYPENAME("LocaleIds") /* .memberName */
10731 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10732 offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10733 true, /* .isArray */
10734 false /* .isOptional */
10735},
10736{
10737 UA_TYPENAME("ProfileUris") /* .memberName */
10738 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10739 offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void *), /* .padding */
10740 true, /* .isArray */
10741 false /* .isOptional */
10742},};
10743
10744/* GetEndpointsResponse */
10745static UA_DataTypeMember GetEndpointsResponse_members[2] = {
10746{
10747 UA_TYPENAME("ResponseHeader") /* .memberName */
10748 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10749 0, /* .padding */
10750 false, /* .isArray */
10751 false /* .isOptional */
10752},
10753{
10754 UA_TYPENAME("Endpoints") /* .memberName */
10755 &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
10756 offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10757 true, /* .isArray */
10758 false /* .isOptional */
10759},};
10760
10761/* SecurityTokenRequestType */
10762#define SecurityTokenRequestType_members NULL
10763
10764/* ChannelSecurityToken */
10765static UA_DataTypeMember ChannelSecurityToken_members[4] = {
10766{
10767 UA_TYPENAME("ChannelId") /* .memberName */
10768 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10769 0, /* .padding */
10770 false, /* .isArray */
10771 false /* .isOptional */
10772},
10773{
10774 UA_TYPENAME("TokenId") /* .memberName */
10775 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10776 offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32), /* .padding */
10777 false, /* .isArray */
10778 false /* .isOptional */
10779},
10780{
10781 UA_TYPENAME("CreatedAt") /* .memberName */
10782 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
10783 offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32), /* .padding */
10784 false, /* .isArray */
10785 false /* .isOptional */
10786},
10787{
10788 UA_TYPENAME("RevisedLifetime") /* .memberName */
10789 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10790 offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime), /* .padding */
10791 false, /* .isArray */
10792 false /* .isOptional */
10793},};
10794
10795/* OpenSecureChannelRequest */
10796static UA_DataTypeMember OpenSecureChannelRequest_members[6] = {
10797{
10798 UA_TYPENAME("RequestHeader") /* .memberName */
10799 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10800 0, /* .padding */
10801 false, /* .isArray */
10802 false /* .isOptional */
10803},
10804{
10805 UA_TYPENAME("ClientProtocolVersion") /* .memberName */
10806 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10807 offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10808 false, /* .isArray */
10809 false /* .isOptional */
10810},
10811{
10812 UA_TYPENAME("RequestType") /* .memberName */
10813 &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], /* .memberType */
10814 offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32), /* .padding */
10815 false, /* .isArray */
10816 false /* .isOptional */
10817},
10818{
10819 UA_TYPENAME("SecurityMode") /* .memberName */
10820 &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */
10821 offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType), /* .padding */
10822 false, /* .isArray */
10823 false /* .isOptional */
10824},
10825{
10826 UA_TYPENAME("ClientNonce") /* .memberName */
10827 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10828 offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */
10829 false, /* .isArray */
10830 false /* .isOptional */
10831},
10832{
10833 UA_TYPENAME("RequestedLifetime") /* .memberName */
10834 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10835 offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
10836 false, /* .isArray */
10837 false /* .isOptional */
10838},};
10839
10840/* OpenSecureChannelResponse */
10841static UA_DataTypeMember OpenSecureChannelResponse_members[4] = {
10842{
10843 UA_TYPENAME("ResponseHeader") /* .memberName */
10844 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10845 0, /* .padding */
10846 false, /* .isArray */
10847 false /* .isOptional */
10848},
10849{
10850 UA_TYPENAME("ServerProtocolVersion") /* .memberName */
10851 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10852 offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
10853 false, /* .isArray */
10854 false /* .isOptional */
10855},
10856{
10857 UA_TYPENAME("SecurityToken") /* .memberName */
10858 &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], /* .memberType */
10859 offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32), /* .padding */
10860 false, /* .isArray */
10861 false /* .isOptional */
10862},
10863{
10864 UA_TYPENAME("ServerNonce") /* .memberName */
10865 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10866 offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken), /* .padding */
10867 false, /* .isArray */
10868 false /* .isOptional */
10869},};
10870
10871/* CloseSecureChannelRequest */
10872static UA_DataTypeMember CloseSecureChannelRequest_members[1] = {
10873{
10874 UA_TYPENAME("RequestHeader") /* .memberName */
10875 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10876 0, /* .padding */
10877 false, /* .isArray */
10878 false /* .isOptional */
10879},};
10880
10881/* CloseSecureChannelResponse */
10882static UA_DataTypeMember CloseSecureChannelResponse_members[1] = {
10883{
10884 UA_TYPENAME("ResponseHeader") /* .memberName */
10885 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10886 0, /* .padding */
10887 false, /* .isArray */
10888 false /* .isOptional */
10889},};
10890
10891/* SignedSoftwareCertificate */
10892static UA_DataTypeMember SignedSoftwareCertificate_members[2] = {
10893{
10894 UA_TYPENAME("CertificateData") /* .memberName */
10895 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10896 0, /* .padding */
10897 false, /* .isArray */
10898 false /* .isOptional */
10899},
10900{
10901 UA_TYPENAME("Signature") /* .memberName */
10902 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10903 offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString), /* .padding */
10904 false, /* .isArray */
10905 false /* .isOptional */
10906},};
10907
10908/* SignatureData */
10909static UA_DataTypeMember SignatureData_members[2] = {
10910{
10911 UA_TYPENAME("Algorithm") /* .memberName */
10912 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10913 0, /* .padding */
10914 false, /* .isArray */
10915 false /* .isOptional */
10916},
10917{
10918 UA_TYPENAME("Signature") /* .memberName */
10919 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10920 offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String), /* .padding */
10921 false, /* .isArray */
10922 false /* .isOptional */
10923},};
10924
10925/* CreateSessionRequest */
10926static UA_DataTypeMember CreateSessionRequest_members[9] = {
10927{
10928 UA_TYPENAME("RequestHeader") /* .memberName */
10929 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
10930 0, /* .padding */
10931 false, /* .isArray */
10932 false /* .isOptional */
10933},
10934{
10935 UA_TYPENAME("ClientDescription") /* .memberName */
10936 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */
10937 offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
10938 false, /* .isArray */
10939 false /* .isOptional */
10940},
10941{
10942 UA_TYPENAME("ServerUri") /* .memberName */
10943 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10944 offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */
10945 false, /* .isArray */
10946 false /* .isOptional */
10947},
10948{
10949 UA_TYPENAME("EndpointUrl") /* .memberName */
10950 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10951 offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String), /* .padding */
10952 false, /* .isArray */
10953 false /* .isOptional */
10954},
10955{
10956 UA_TYPENAME("SessionName") /* .memberName */
10957 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
10958 offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String), /* .padding */
10959 false, /* .isArray */
10960 false /* .isOptional */
10961},
10962{
10963 UA_TYPENAME("ClientNonce") /* .memberName */
10964 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10965 offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String), /* .padding */
10966 false, /* .isArray */
10967 false /* .isOptional */
10968},
10969{
10970 UA_TYPENAME("ClientCertificate") /* .memberName */
10971 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
10972 offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */
10973 false, /* .isArray */
10974 false /* .isOptional */
10975},
10976{
10977 UA_TYPENAME("RequestedSessionTimeout") /* .memberName */
10978 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
10979 offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString), /* .padding */
10980 false, /* .isArray */
10981 false /* .isOptional */
10982},
10983{
10984 UA_TYPENAME("MaxResponseMessageSize") /* .memberName */
10985 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
10986 offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double), /* .padding */
10987 false, /* .isArray */
10988 false /* .isOptional */
10989},};
10990
10991/* CreateSessionResponse */
10992static UA_DataTypeMember CreateSessionResponse_members[10] = {
10993{
10994 UA_TYPENAME("ResponseHeader") /* .memberName */
10995 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
10996 0, /* .padding */
10997 false, /* .isArray */
10998 false /* .isOptional */
10999},
11000{
11001 UA_TYPENAME("SessionId") /* .memberName */
11002 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11003 offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11004 false, /* .isArray */
11005 false /* .isOptional */
11006},
11007{
11008 UA_TYPENAME("AuthenticationToken") /* .memberName */
11009 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11010 offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId), /* .padding */
11011 false, /* .isArray */
11012 false /* .isOptional */
11013},
11014{
11015 UA_TYPENAME("RevisedSessionTimeout") /* .memberName */
11016 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
11017 offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId), /* .padding */
11018 false, /* .isArray */
11019 false /* .isOptional */
11020},
11021{
11022 UA_TYPENAME("ServerNonce") /* .memberName */
11023 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11024 offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double), /* .padding */
11025 false, /* .isArray */
11026 false /* .isOptional */
11027},
11028{
11029 UA_TYPENAME("ServerCertificate") /* .memberName */
11030 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11031 offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
11032 false, /* .isArray */
11033 false /* .isOptional */
11034},
11035{
11036 UA_TYPENAME("ServerEndpoints") /* .memberName */
11037 &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */
11038 offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString), /* .padding */
11039 true, /* .isArray */
11040 false /* .isOptional */
11041},
11042{
11043 UA_TYPENAME("ServerSoftwareCertificates") /* .memberName */
11044 &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
11045 offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void *), /* .padding */
11046 true, /* .isArray */
11047 false /* .isOptional */
11048},
11049{
11050 UA_TYPENAME("ServerSignature") /* .memberName */
11051 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11052 offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void *), /* .padding */
11053 false, /* .isArray */
11054 false /* .isOptional */
11055},
11056{
11057 UA_TYPENAME("MaxRequestMessageSize") /* .memberName */
11058 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11059 offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData), /* .padding */
11060 false, /* .isArray */
11061 false /* .isOptional */
11062},};
11063
11064/* UserIdentityToken */
11065static UA_DataTypeMember UserIdentityToken_members[1] = {
11066{
11067 UA_TYPENAME("PolicyId") /* .memberName */
11068 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11069 0, /* .padding */
11070 false, /* .isArray */
11071 false /* .isOptional */
11072},};
11073
11074/* AnonymousIdentityToken */
11075static UA_DataTypeMember AnonymousIdentityToken_members[1] = {
11076{
11077 UA_TYPENAME("PolicyId") /* .memberName */
11078 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11079 0, /* .padding */
11080 false, /* .isArray */
11081 false /* .isOptional */
11082},};
11083
11084/* UserNameIdentityToken */
11085static UA_DataTypeMember UserNameIdentityToken_members[4] = {
11086{
11087 UA_TYPENAME("PolicyId") /* .memberName */
11088 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11089 0, /* .padding */
11090 false, /* .isArray */
11091 false /* .isOptional */
11092},
11093{
11094 UA_TYPENAME("UserName") /* .memberName */
11095 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11096 offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String), /* .padding */
11097 false, /* .isArray */
11098 false /* .isOptional */
11099},
11100{
11101 UA_TYPENAME("Password") /* .memberName */
11102 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11103 offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String), /* .padding */
11104 false, /* .isArray */
11105 false /* .isOptional */
11106},
11107{
11108 UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
11109 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11110 offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString), /* .padding */
11111 false, /* .isArray */
11112 false /* .isOptional */
11113},};
11114
11115/* X509IdentityToken */
11116static UA_DataTypeMember X509IdentityToken_members[2] = {
11117{
11118 UA_TYPENAME("PolicyId") /* .memberName */
11119 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11120 0, /* .padding */
11121 false, /* .isArray */
11122 false /* .isOptional */
11123},
11124{
11125 UA_TYPENAME("CertificateData") /* .memberName */
11126 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11127 offsetof(UA_X509IdentityToken, certificateData) - offsetof(UA_X509IdentityToken, policyId) - sizeof(UA_String), /* .padding */
11128 false, /* .isArray */
11129 false /* .isOptional */
11130},};
11131
11132/* IssuedIdentityToken */
11133static UA_DataTypeMember IssuedIdentityToken_members[3] = {
11134{
11135 UA_TYPENAME("PolicyId") /* .memberName */
11136 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11137 0, /* .padding */
11138 false, /* .isArray */
11139 false /* .isOptional */
11140},
11141{
11142 UA_TYPENAME("TokenData") /* .memberName */
11143 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11144 offsetof(UA_IssuedIdentityToken, tokenData) - offsetof(UA_IssuedIdentityToken, policyId) - sizeof(UA_String), /* .padding */
11145 false, /* .isArray */
11146 false /* .isOptional */
11147},
11148{
11149 UA_TYPENAME("EncryptionAlgorithm") /* .memberName */
11150 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11151 offsetof(UA_IssuedIdentityToken, encryptionAlgorithm) - offsetof(UA_IssuedIdentityToken, tokenData) - sizeof(UA_ByteString), /* .padding */
11152 false, /* .isArray */
11153 false /* .isOptional */
11154},};
11155
11156/* ActivateSessionRequest */
11157static UA_DataTypeMember ActivateSessionRequest_members[6] = {
11158{
11159 UA_TYPENAME("RequestHeader") /* .memberName */
11160 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11161 0, /* .padding */
11162 false, /* .isArray */
11163 false /* .isOptional */
11164},
11165{
11166 UA_TYPENAME("ClientSignature") /* .memberName */
11167 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11168 offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11169 false, /* .isArray */
11170 false /* .isOptional */
11171},
11172{
11173 UA_TYPENAME("ClientSoftwareCertificates") /* .memberName */
11174 &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */
11175 offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData), /* .padding */
11176 true, /* .isArray */
11177 false /* .isOptional */
11178},
11179{
11180 UA_TYPENAME("LocaleIds") /* .memberName */
11181 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11182 offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void *), /* .padding */
11183 true, /* .isArray */
11184 false /* .isOptional */
11185},
11186{
11187 UA_TYPENAME("UserIdentityToken") /* .memberName */
11188 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
11189 offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void *), /* .padding */
11190 false, /* .isArray */
11191 false /* .isOptional */
11192},
11193{
11194 UA_TYPENAME("UserTokenSignature") /* .memberName */
11195 &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */
11196 offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject), /* .padding */
11197 false, /* .isArray */
11198 false /* .isOptional */
11199},};
11200
11201/* ActivateSessionResponse */
11202static UA_DataTypeMember ActivateSessionResponse_members[4] = {
11203{
11204 UA_TYPENAME("ResponseHeader") /* .memberName */
11205 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11206 0, /* .padding */
11207 false, /* .isArray */
11208 false /* .isOptional */
11209},
11210{
11211 UA_TYPENAME("ServerNonce") /* .memberName */
11212 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
11213 offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11214 false, /* .isArray */
11215 false /* .isOptional */
11216},
11217{
11218 UA_TYPENAME("Results") /* .memberName */
11219 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11220 offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */
11221 true, /* .isArray */
11222 false /* .isOptional */
11223},
11224{
11225 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11226 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11227 offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void *), /* .padding */
11228 true, /* .isArray */
11229 false /* .isOptional */
11230},};
11231
11232/* CloseSessionRequest */
11233static UA_DataTypeMember CloseSessionRequest_members[2] = {
11234{
11235 UA_TYPENAME("RequestHeader") /* .memberName */
11236 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11237 0, /* .padding */
11238 false, /* .isArray */
11239 false /* .isOptional */
11240},
11241{
11242 UA_TYPENAME("DeleteSubscriptions") /* .memberName */
11243 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11244 offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11245 false, /* .isArray */
11246 false /* .isOptional */
11247},};
11248
11249/* CloseSessionResponse */
11250static UA_DataTypeMember CloseSessionResponse_members[1] = {
11251{
11252 UA_TYPENAME("ResponseHeader") /* .memberName */
11253 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11254 0, /* .padding */
11255 false, /* .isArray */
11256 false /* .isOptional */
11257},};
11258
11259/* NodeAttributesMask */
11260#define NodeAttributesMask_members NULL
11261
11262/* NodeAttributes */
11263static UA_DataTypeMember NodeAttributes_members[5] = {
11264{
11265 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11266 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11267 0, /* .padding */
11268 false, /* .isArray */
11269 false /* .isOptional */
11270},
11271{
11272 UA_TYPENAME("DisplayName") /* .memberName */
11273 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11274 offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11275 false, /* .isArray */
11276 false /* .isOptional */
11277},
11278{
11279 UA_TYPENAME("Description") /* .memberName */
11280 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11281 offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11282 false, /* .isArray */
11283 false /* .isOptional */
11284},
11285{
11286 UA_TYPENAME("WriteMask") /* .memberName */
11287 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11288 offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11289 false, /* .isArray */
11290 false /* .isOptional */
11291},
11292{
11293 UA_TYPENAME("UserWriteMask") /* .memberName */
11294 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11295 offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11296 false, /* .isArray */
11297 false /* .isOptional */
11298},};
11299
11300/* ObjectAttributes */
11301static UA_DataTypeMember ObjectAttributes_members[6] = {
11302{
11303 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11304 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11305 0, /* .padding */
11306 false, /* .isArray */
11307 false /* .isOptional */
11308},
11309{
11310 UA_TYPENAME("DisplayName") /* .memberName */
11311 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11312 offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11313 false, /* .isArray */
11314 false /* .isOptional */
11315},
11316{
11317 UA_TYPENAME("Description") /* .memberName */
11318 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11319 offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11320 false, /* .isArray */
11321 false /* .isOptional */
11322},
11323{
11324 UA_TYPENAME("WriteMask") /* .memberName */
11325 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11326 offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11327 false, /* .isArray */
11328 false /* .isOptional */
11329},
11330{
11331 UA_TYPENAME("UserWriteMask") /* .memberName */
11332 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11333 offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11334 false, /* .isArray */
11335 false /* .isOptional */
11336},
11337{
11338 UA_TYPENAME("EventNotifier") /* .memberName */
11339 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11340 offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11341 false, /* .isArray */
11342 false /* .isOptional */
11343},};
11344
11345/* VariableAttributes */
11346static UA_DataTypeMember VariableAttributes_members[13] = {
11347{
11348 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11349 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11350 0, /* .padding */
11351 false, /* .isArray */
11352 false /* .isOptional */
11353},
11354{
11355 UA_TYPENAME("DisplayName") /* .memberName */
11356 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11357 offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11358 false, /* .isArray */
11359 false /* .isOptional */
11360},
11361{
11362 UA_TYPENAME("Description") /* .memberName */
11363 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11364 offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11365 false, /* .isArray */
11366 false /* .isOptional */
11367},
11368{
11369 UA_TYPENAME("WriteMask") /* .memberName */
11370 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11371 offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11372 false, /* .isArray */
11373 false /* .isOptional */
11374},
11375{
11376 UA_TYPENAME("UserWriteMask") /* .memberName */
11377 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11378 offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11379 false, /* .isArray */
11380 false /* .isOptional */
11381},
11382{
11383 UA_TYPENAME("Value") /* .memberName */
11384 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
11385 offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11386 false, /* .isArray */
11387 false /* .isOptional */
11388},
11389{
11390 UA_TYPENAME("DataType") /* .memberName */
11391 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11392 offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant), /* .padding */
11393 false, /* .isArray */
11394 false /* .isOptional */
11395},
11396{
11397 UA_TYPENAME("ValueRank") /* .memberName */
11398 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
11399 offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
11400 false, /* .isArray */
11401 false /* .isOptional */
11402},
11403{
11404 UA_TYPENAME("ArrayDimensions") /* .memberName */
11405 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11406 offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
11407 true, /* .isArray */
11408 false /* .isOptional */
11409},
11410{
11411 UA_TYPENAME("AccessLevel") /* .memberName */
11412 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11413 offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void *), /* .padding */
11414 false, /* .isArray */
11415 false /* .isOptional */
11416},
11417{
11418 UA_TYPENAME("UserAccessLevel") /* .memberName */
11419 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11420 offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte), /* .padding */
11421 false, /* .isArray */
11422 false /* .isOptional */
11423},
11424{
11425 UA_TYPENAME("MinimumSamplingInterval") /* .memberName */
11426 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
11427 offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte), /* .padding */
11428 false, /* .isArray */
11429 false /* .isOptional */
11430},
11431{
11432 UA_TYPENAME("Historizing") /* .memberName */
11433 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11434 offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double), /* .padding */
11435 false, /* .isArray */
11436 false /* .isOptional */
11437},};
11438
11439/* MethodAttributes */
11440static UA_DataTypeMember MethodAttributes_members[7] = {
11441{
11442 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11443 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11444 0, /* .padding */
11445 false, /* .isArray */
11446 false /* .isOptional */
11447},
11448{
11449 UA_TYPENAME("DisplayName") /* .memberName */
11450 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11451 offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11452 false, /* .isArray */
11453 false /* .isOptional */
11454},
11455{
11456 UA_TYPENAME("Description") /* .memberName */
11457 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11458 offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11459 false, /* .isArray */
11460 false /* .isOptional */
11461},
11462{
11463 UA_TYPENAME("WriteMask") /* .memberName */
11464 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11465 offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11466 false, /* .isArray */
11467 false /* .isOptional */
11468},
11469{
11470 UA_TYPENAME("UserWriteMask") /* .memberName */
11471 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11472 offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11473 false, /* .isArray */
11474 false /* .isOptional */
11475},
11476{
11477 UA_TYPENAME("Executable") /* .memberName */
11478 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11479 offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11480 false, /* .isArray */
11481 false /* .isOptional */
11482},
11483{
11484 UA_TYPENAME("UserExecutable") /* .memberName */
11485 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11486 offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean), /* .padding */
11487 false, /* .isArray */
11488 false /* .isOptional */
11489},};
11490
11491/* ObjectTypeAttributes */
11492static UA_DataTypeMember ObjectTypeAttributes_members[6] = {
11493{
11494 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11495 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11496 0, /* .padding */
11497 false, /* .isArray */
11498 false /* .isOptional */
11499},
11500{
11501 UA_TYPENAME("DisplayName") /* .memberName */
11502 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11503 offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11504 false, /* .isArray */
11505 false /* .isOptional */
11506},
11507{
11508 UA_TYPENAME("Description") /* .memberName */
11509 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11510 offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11511 false, /* .isArray */
11512 false /* .isOptional */
11513},
11514{
11515 UA_TYPENAME("WriteMask") /* .memberName */
11516 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11517 offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11518 false, /* .isArray */
11519 false /* .isOptional */
11520},
11521{
11522 UA_TYPENAME("UserWriteMask") /* .memberName */
11523 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11524 offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11525 false, /* .isArray */
11526 false /* .isOptional */
11527},
11528{
11529 UA_TYPENAME("IsAbstract") /* .memberName */
11530 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11531 offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11532 false, /* .isArray */
11533 false /* .isOptional */
11534},};
11535
11536/* VariableTypeAttributes */
11537static UA_DataTypeMember VariableTypeAttributes_members[10] = {
11538{
11539 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11540 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11541 0, /* .padding */
11542 false, /* .isArray */
11543 false /* .isOptional */
11544},
11545{
11546 UA_TYPENAME("DisplayName") /* .memberName */
11547 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11548 offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11549 false, /* .isArray */
11550 false /* .isOptional */
11551},
11552{
11553 UA_TYPENAME("Description") /* .memberName */
11554 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11555 offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11556 false, /* .isArray */
11557 false /* .isOptional */
11558},
11559{
11560 UA_TYPENAME("WriteMask") /* .memberName */
11561 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11562 offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11563 false, /* .isArray */
11564 false /* .isOptional */
11565},
11566{
11567 UA_TYPENAME("UserWriteMask") /* .memberName */
11568 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11569 offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11570 false, /* .isArray */
11571 false /* .isOptional */
11572},
11573{
11574 UA_TYPENAME("Value") /* .memberName */
11575 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
11576 offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11577 false, /* .isArray */
11578 false /* .isOptional */
11579},
11580{
11581 UA_TYPENAME("DataType") /* .memberName */
11582 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11583 offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant), /* .padding */
11584 false, /* .isArray */
11585 false /* .isOptional */
11586},
11587{
11588 UA_TYPENAME("ValueRank") /* .memberName */
11589 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
11590 offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId), /* .padding */
11591 false, /* .isArray */
11592 false /* .isOptional */
11593},
11594{
11595 UA_TYPENAME("ArrayDimensions") /* .memberName */
11596 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11597 offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32), /* .padding */
11598 true, /* .isArray */
11599 false /* .isOptional */
11600},
11601{
11602 UA_TYPENAME("IsAbstract") /* .memberName */
11603 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11604 offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void *), /* .padding */
11605 false, /* .isArray */
11606 false /* .isOptional */
11607},};
11608
11609/* ReferenceTypeAttributes */
11610static UA_DataTypeMember ReferenceTypeAttributes_members[8] = {
11611{
11612 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11613 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11614 0, /* .padding */
11615 false, /* .isArray */
11616 false /* .isOptional */
11617},
11618{
11619 UA_TYPENAME("DisplayName") /* .memberName */
11620 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11621 offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11622 false, /* .isArray */
11623 false /* .isOptional */
11624},
11625{
11626 UA_TYPENAME("Description") /* .memberName */
11627 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11628 offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11629 false, /* .isArray */
11630 false /* .isOptional */
11631},
11632{
11633 UA_TYPENAME("WriteMask") /* .memberName */
11634 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11635 offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11636 false, /* .isArray */
11637 false /* .isOptional */
11638},
11639{
11640 UA_TYPENAME("UserWriteMask") /* .memberName */
11641 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11642 offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11643 false, /* .isArray */
11644 false /* .isOptional */
11645},
11646{
11647 UA_TYPENAME("IsAbstract") /* .memberName */
11648 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11649 offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11650 false, /* .isArray */
11651 false /* .isOptional */
11652},
11653{
11654 UA_TYPENAME("Symmetric") /* .memberName */
11655 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11656 offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean), /* .padding */
11657 false, /* .isArray */
11658 false /* .isOptional */
11659},
11660{
11661 UA_TYPENAME("InverseName") /* .memberName */
11662 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11663 offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean), /* .padding */
11664 false, /* .isArray */
11665 false /* .isOptional */
11666},};
11667
11668/* DataTypeAttributes */
11669static UA_DataTypeMember DataTypeAttributes_members[6] = {
11670{
11671 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11672 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11673 0, /* .padding */
11674 false, /* .isArray */
11675 false /* .isOptional */
11676},
11677{
11678 UA_TYPENAME("DisplayName") /* .memberName */
11679 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11680 offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11681 false, /* .isArray */
11682 false /* .isOptional */
11683},
11684{
11685 UA_TYPENAME("Description") /* .memberName */
11686 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11687 offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11688 false, /* .isArray */
11689 false /* .isOptional */
11690},
11691{
11692 UA_TYPENAME("WriteMask") /* .memberName */
11693 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11694 offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11695 false, /* .isArray */
11696 false /* .isOptional */
11697},
11698{
11699 UA_TYPENAME("UserWriteMask") /* .memberName */
11700 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11701 offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11702 false, /* .isArray */
11703 false /* .isOptional */
11704},
11705{
11706 UA_TYPENAME("IsAbstract") /* .memberName */
11707 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11708 offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11709 false, /* .isArray */
11710 false /* .isOptional */
11711},};
11712
11713/* ViewAttributes */
11714static UA_DataTypeMember ViewAttributes_members[7] = {
11715{
11716 UA_TYPENAME("SpecifiedAttributes") /* .memberName */
11717 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11718 0, /* .padding */
11719 false, /* .isArray */
11720 false /* .isOptional */
11721},
11722{
11723 UA_TYPENAME("DisplayName") /* .memberName */
11724 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11725 offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */
11726 false, /* .isArray */
11727 false /* .isOptional */
11728},
11729{
11730 UA_TYPENAME("Description") /* .memberName */
11731 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
11732 offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */
11733 false, /* .isArray */
11734 false /* .isOptional */
11735},
11736{
11737 UA_TYPENAME("WriteMask") /* .memberName */
11738 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11739 offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText), /* .padding */
11740 false, /* .isArray */
11741 false /* .isOptional */
11742},
11743{
11744 UA_TYPENAME("UserWriteMask") /* .memberName */
11745 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
11746 offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */
11747 false, /* .isArray */
11748 false /* .isOptional */
11749},
11750{
11751 UA_TYPENAME("ContainsNoLoops") /* .memberName */
11752 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11753 offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */
11754 false, /* .isArray */
11755 false /* .isOptional */
11756},
11757{
11758 UA_TYPENAME("EventNotifier") /* .memberName */
11759 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
11760 offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean), /* .padding */
11761 false, /* .isArray */
11762 false /* .isOptional */
11763},};
11764
11765/* AddNodesItem */
11766static UA_DataTypeMember AddNodesItem_members[7] = {
11767{
11768 UA_TYPENAME("ParentNodeId") /* .memberName */
11769 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11770 0, /* .padding */
11771 false, /* .isArray */
11772 false /* .isOptional */
11773},
11774{
11775 UA_TYPENAME("ReferenceTypeId") /* .memberName */
11776 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11777 offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11778 false, /* .isArray */
11779 false /* .isOptional */
11780},
11781{
11782 UA_TYPENAME("RequestedNewNodeId") /* .memberName */
11783 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11784 offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
11785 false, /* .isArray */
11786 false /* .isOptional */
11787},
11788{
11789 UA_TYPENAME("BrowseName") /* .memberName */
11790 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
11791 offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11792 false, /* .isArray */
11793 false /* .isOptional */
11794},
11795{
11796 UA_TYPENAME("NodeClass") /* .memberName */
11797 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
11798 offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName), /* .padding */
11799 false, /* .isArray */
11800 false /* .isOptional */
11801},
11802{
11803 UA_TYPENAME("NodeAttributes") /* .memberName */
11804 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
11805 offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass), /* .padding */
11806 false, /* .isArray */
11807 false /* .isOptional */
11808},
11809{
11810 UA_TYPENAME("TypeDefinition") /* .memberName */
11811 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11812 offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject), /* .padding */
11813 false, /* .isArray */
11814 false /* .isOptional */
11815},};
11816
11817/* AddNodesResult */
11818static UA_DataTypeMember AddNodesResult_members[2] = {
11819{
11820 UA_TYPENAME("StatusCode") /* .memberName */
11821 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11822 0, /* .padding */
11823 false, /* .isArray */
11824 false /* .isOptional */
11825},
11826{
11827 UA_TYPENAME("AddedNodeId") /* .memberName */
11828 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11829 offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
11830 false, /* .isArray */
11831 false /* .isOptional */
11832},};
11833
11834/* AddNodesRequest */
11835static UA_DataTypeMember AddNodesRequest_members[2] = {
11836{
11837 UA_TYPENAME("RequestHeader") /* .memberName */
11838 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11839 0, /* .padding */
11840 false, /* .isArray */
11841 false /* .isOptional */
11842},
11843{
11844 UA_TYPENAME("NodesToAdd") /* .memberName */
11845 &UA_TYPES[UA_TYPES_ADDNODESITEM], /* .memberType */
11846 offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11847 true, /* .isArray */
11848 false /* .isOptional */
11849},};
11850
11851/* AddNodesResponse */
11852static UA_DataTypeMember AddNodesResponse_members[3] = {
11853{
11854 UA_TYPENAME("ResponseHeader") /* .memberName */
11855 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11856 0, /* .padding */
11857 false, /* .isArray */
11858 false /* .isOptional */
11859},
11860{
11861 UA_TYPENAME("Results") /* .memberName */
11862 &UA_TYPES[UA_TYPES_ADDNODESRESULT], /* .memberType */
11863 offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11864 true, /* .isArray */
11865 false /* .isOptional */
11866},
11867{
11868 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11869 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11870 offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void *), /* .padding */
11871 true, /* .isArray */
11872 false /* .isOptional */
11873},};
11874
11875/* AddReferencesItem */
11876static UA_DataTypeMember AddReferencesItem_members[6] = {
11877{
11878 UA_TYPENAME("SourceNodeId") /* .memberName */
11879 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11880 0, /* .padding */
11881 false, /* .isArray */
11882 false /* .isOptional */
11883},
11884{
11885 UA_TYPENAME("ReferenceTypeId") /* .memberName */
11886 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11887 offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
11888 false, /* .isArray */
11889 false /* .isOptional */
11890},
11891{
11892 UA_TYPENAME("IsForward") /* .memberName */
11893 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11894 offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
11895 false, /* .isArray */
11896 false /* .isOptional */
11897},
11898{
11899 UA_TYPENAME("TargetServerUri") /* .memberName */
11900 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
11901 offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
11902 false, /* .isArray */
11903 false /* .isOptional */
11904},
11905{
11906 UA_TYPENAME("TargetNodeId") /* .memberName */
11907 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
11908 offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String), /* .padding */
11909 false, /* .isArray */
11910 false /* .isOptional */
11911},
11912{
11913 UA_TYPENAME("TargetNodeClass") /* .memberName */
11914 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
11915 offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
11916 false, /* .isArray */
11917 false /* .isOptional */
11918},};
11919
11920/* AddReferencesRequest */
11921static UA_DataTypeMember AddReferencesRequest_members[2] = {
11922{
11923 UA_TYPENAME("RequestHeader") /* .memberName */
11924 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11925 0, /* .padding */
11926 false, /* .isArray */
11927 false /* .isOptional */
11928},
11929{
11930 UA_TYPENAME("ReferencesToAdd") /* .memberName */
11931 &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], /* .memberType */
11932 offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11933 true, /* .isArray */
11934 false /* .isOptional */
11935},};
11936
11937/* AddReferencesResponse */
11938static UA_DataTypeMember AddReferencesResponse_members[3] = {
11939{
11940 UA_TYPENAME("ResponseHeader") /* .memberName */
11941 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
11942 0, /* .padding */
11943 false, /* .isArray */
11944 false /* .isOptional */
11945},
11946{
11947 UA_TYPENAME("Results") /* .memberName */
11948 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
11949 offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
11950 true, /* .isArray */
11951 false /* .isOptional */
11952},
11953{
11954 UA_TYPENAME("DiagnosticInfos") /* .memberName */
11955 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
11956 offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void *), /* .padding */
11957 true, /* .isArray */
11958 false /* .isOptional */
11959},};
11960
11961/* DeleteNodesItem */
11962static UA_DataTypeMember DeleteNodesItem_members[2] = {
11963{
11964 UA_TYPENAME("NodeId") /* .memberName */
11965 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
11966 0, /* .padding */
11967 false, /* .isArray */
11968 false /* .isOptional */
11969},
11970{
11971 UA_TYPENAME("DeleteTargetReferences") /* .memberName */
11972 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
11973 offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId), /* .padding */
11974 false, /* .isArray */
11975 false /* .isOptional */
11976},};
11977
11978/* DeleteNodesRequest */
11979static UA_DataTypeMember DeleteNodesRequest_members[2] = {
11980{
11981 UA_TYPENAME("RequestHeader") /* .memberName */
11982 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
11983 0, /* .padding */
11984 false, /* .isArray */
11985 false /* .isOptional */
11986},
11987{
11988 UA_TYPENAME("NodesToDelete") /* .memberName */
11989 &UA_TYPES[UA_TYPES_DELETENODESITEM], /* .memberType */
11990 offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
11991 true, /* .isArray */
11992 false /* .isOptional */
11993},};
11994
11995/* DeleteNodesResponse */
11996static UA_DataTypeMember DeleteNodesResponse_members[3] = {
11997{
11998 UA_TYPENAME("ResponseHeader") /* .memberName */
11999 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12000 0, /* .padding */
12001 false, /* .isArray */
12002 false /* .isOptional */
12003},
12004{
12005 UA_TYPENAME("Results") /* .memberName */
12006 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12007 offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12008 true, /* .isArray */
12009 false /* .isOptional */
12010},
12011{
12012 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12013 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12014 offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void *), /* .padding */
12015 true, /* .isArray */
12016 false /* .isOptional */
12017},};
12018
12019/* DeleteReferencesItem */
12020static UA_DataTypeMember DeleteReferencesItem_members[5] = {
12021{
12022 UA_TYPENAME("SourceNodeId") /* .memberName */
12023 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12024 0, /* .padding */
12025 false, /* .isArray */
12026 false /* .isOptional */
12027},
12028{
12029 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12030 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12031 offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */
12032 false, /* .isArray */
12033 false /* .isOptional */
12034},
12035{
12036 UA_TYPENAME("IsForward") /* .memberName */
12037 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12038 offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12039 false, /* .isArray */
12040 false /* .isOptional */
12041},
12042{
12043 UA_TYPENAME("TargetNodeId") /* .memberName */
12044 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12045 offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */
12046 false, /* .isArray */
12047 false /* .isOptional */
12048},
12049{
12050 UA_TYPENAME("DeleteBidirectional") /* .memberName */
12051 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12052 offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
12053 false, /* .isArray */
12054 false /* .isOptional */
12055},};
12056
12057/* DeleteReferencesRequest */
12058static UA_DataTypeMember DeleteReferencesRequest_members[2] = {
12059{
12060 UA_TYPENAME("RequestHeader") /* .memberName */
12061 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12062 0, /* .padding */
12063 false, /* .isArray */
12064 false /* .isOptional */
12065},
12066{
12067 UA_TYPENAME("ReferencesToDelete") /* .memberName */
12068 &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], /* .memberType */
12069 offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12070 true, /* .isArray */
12071 false /* .isOptional */
12072},};
12073
12074/* DeleteReferencesResponse */
12075static UA_DataTypeMember DeleteReferencesResponse_members[3] = {
12076{
12077 UA_TYPENAME("ResponseHeader") /* .memberName */
12078 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12079 0, /* .padding */
12080 false, /* .isArray */
12081 false /* .isOptional */
12082},
12083{
12084 UA_TYPENAME("Results") /* .memberName */
12085 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12086 offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12087 true, /* .isArray */
12088 false /* .isOptional */
12089},
12090{
12091 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12092 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12093 offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void *), /* .padding */
12094 true, /* .isArray */
12095 false /* .isOptional */
12096},};
12097
12098/* BrowseDirection */
12099#define BrowseDirection_members NULL
12100
12101/* ViewDescription */
12102static UA_DataTypeMember ViewDescription_members[3] = {
12103{
12104 UA_TYPENAME("ViewId") /* .memberName */
12105 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12106 0, /* .padding */
12107 false, /* .isArray */
12108 false /* .isOptional */
12109},
12110{
12111 UA_TYPENAME("Timestamp") /* .memberName */
12112 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12113 offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId), /* .padding */
12114 false, /* .isArray */
12115 false /* .isOptional */
12116},
12117{
12118 UA_TYPENAME("ViewVersion") /* .memberName */
12119 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12120 offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime), /* .padding */
12121 false, /* .isArray */
12122 false /* .isOptional */
12123},};
12124
12125/* BrowseDescription */
12126static UA_DataTypeMember BrowseDescription_members[6] = {
12127{
12128 UA_TYPENAME("NodeId") /* .memberName */
12129 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12130 0, /* .padding */
12131 false, /* .isArray */
12132 false /* .isOptional */
12133},
12134{
12135 UA_TYPENAME("BrowseDirection") /* .memberName */
12136 &UA_TYPES[UA_TYPES_BROWSEDIRECTION], /* .memberType */
12137 offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId), /* .padding */
12138 false, /* .isArray */
12139 false /* .isOptional */
12140},
12141{
12142 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12143 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12144 offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection), /* .padding */
12145 false, /* .isArray */
12146 false /* .isOptional */
12147},
12148{
12149 UA_TYPENAME("IncludeSubtypes") /* .memberName */
12150 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12151 offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12152 false, /* .isArray */
12153 false /* .isOptional */
12154},
12155{
12156 UA_TYPENAME("NodeClassMask") /* .memberName */
12157 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12158 offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
12159 false, /* .isArray */
12160 false /* .isOptional */
12161},
12162{
12163 UA_TYPENAME("ResultMask") /* .memberName */
12164 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12165 offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32), /* .padding */
12166 false, /* .isArray */
12167 false /* .isOptional */
12168},};
12169
12170/* BrowseResultMask */
12171#define BrowseResultMask_members NULL
12172
12173/* ReferenceDescription */
12174static UA_DataTypeMember ReferenceDescription_members[7] = {
12175{
12176 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12177 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12178 0, /* .padding */
12179 false, /* .isArray */
12180 false /* .isOptional */
12181},
12182{
12183 UA_TYPENAME("IsForward") /* .memberName */
12184 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12185 offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12186 false, /* .isArray */
12187 false /* .isOptional */
12188},
12189{
12190 UA_TYPENAME("NodeId") /* .memberName */
12191 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12192 offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean), /* .padding */
12193 false, /* .isArray */
12194 false /* .isOptional */
12195},
12196{
12197 UA_TYPENAME("BrowseName") /* .memberName */
12198 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12199 offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */
12200 false, /* .isArray */
12201 false /* .isOptional */
12202},
12203{
12204 UA_TYPENAME("DisplayName") /* .memberName */
12205 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
12206 offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName), /* .padding */
12207 false, /* .isArray */
12208 false /* .isOptional */
12209},
12210{
12211 UA_TYPENAME("NodeClass") /* .memberName */
12212 &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */
12213 offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText), /* .padding */
12214 false, /* .isArray */
12215 false /* .isOptional */
12216},
12217{
12218 UA_TYPENAME("TypeDefinition") /* .memberName */
12219 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12220 offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass), /* .padding */
12221 false, /* .isArray */
12222 false /* .isOptional */
12223},};
12224
12225/* BrowseResult */
12226static UA_DataTypeMember BrowseResult_members[3] = {
12227{
12228 UA_TYPENAME("StatusCode") /* .memberName */
12229 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12230 0, /* .padding */
12231 false, /* .isArray */
12232 false /* .isOptional */
12233},
12234{
12235 UA_TYPENAME("ContinuationPoint") /* .memberName */
12236 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12237 offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12238 false, /* .isArray */
12239 false /* .isOptional */
12240},
12241{
12242 UA_TYPENAME("References") /* .memberName */
12243 &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], /* .memberType */
12244 offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
12245 true, /* .isArray */
12246 false /* .isOptional */
12247},};
12248
12249/* BrowseRequest */
12250static UA_DataTypeMember BrowseRequest_members[4] = {
12251{
12252 UA_TYPENAME("RequestHeader") /* .memberName */
12253 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12254 0, /* .padding */
12255 false, /* .isArray */
12256 false /* .isOptional */
12257},
12258{
12259 UA_TYPENAME("View") /* .memberName */
12260 &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], /* .memberType */
12261 offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12262 false, /* .isArray */
12263 false /* .isOptional */
12264},
12265{
12266 UA_TYPENAME("RequestedMaxReferencesPerNode") /* .memberName */
12267 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12268 offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription), /* .padding */
12269 false, /* .isArray */
12270 false /* .isOptional */
12271},
12272{
12273 UA_TYPENAME("NodesToBrowse") /* .memberName */
12274 &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], /* .memberType */
12275 offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32), /* .padding */
12276 true, /* .isArray */
12277 false /* .isOptional */
12278},};
12279
12280/* BrowseResponse */
12281static UA_DataTypeMember BrowseResponse_members[3] = {
12282{
12283 UA_TYPENAME("ResponseHeader") /* .memberName */
12284 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12285 0, /* .padding */
12286 false, /* .isArray */
12287 false /* .isOptional */
12288},
12289{
12290 UA_TYPENAME("Results") /* .memberName */
12291 &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
12292 offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12293 true, /* .isArray */
12294 false /* .isOptional */
12295},
12296{
12297 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12298 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12299 offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void *), /* .padding */
12300 true, /* .isArray */
12301 false /* .isOptional */
12302},};
12303
12304/* BrowseNextRequest */
12305static UA_DataTypeMember BrowseNextRequest_members[3] = {
12306{
12307 UA_TYPENAME("RequestHeader") /* .memberName */
12308 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12309 0, /* .padding */
12310 false, /* .isArray */
12311 false /* .isOptional */
12312},
12313{
12314 UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
12315 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12316 offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12317 false, /* .isArray */
12318 false /* .isOptional */
12319},
12320{
12321 UA_TYPENAME("ContinuationPoints") /* .memberName */
12322 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12323 offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
12324 true, /* .isArray */
12325 false /* .isOptional */
12326},};
12327
12328/* BrowseNextResponse */
12329static UA_DataTypeMember BrowseNextResponse_members[3] = {
12330{
12331 UA_TYPENAME("ResponseHeader") /* .memberName */
12332 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12333 0, /* .padding */
12334 false, /* .isArray */
12335 false /* .isOptional */
12336},
12337{
12338 UA_TYPENAME("Results") /* .memberName */
12339 &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */
12340 offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12341 true, /* .isArray */
12342 false /* .isOptional */
12343},
12344{
12345 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12346 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12347 offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void *), /* .padding */
12348 true, /* .isArray */
12349 false /* .isOptional */
12350},};
12351
12352/* RelativePathElement */
12353static UA_DataTypeMember RelativePathElement_members[4] = {
12354{
12355 UA_TYPENAME("ReferenceTypeId") /* .memberName */
12356 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12357 0, /* .padding */
12358 false, /* .isArray */
12359 false /* .isOptional */
12360},
12361{
12362 UA_TYPENAME("IsInverse") /* .memberName */
12363 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12364 offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId), /* .padding */
12365 false, /* .isArray */
12366 false /* .isOptional */
12367},
12368{
12369 UA_TYPENAME("IncludeSubtypes") /* .memberName */
12370 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12371 offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean), /* .padding */
12372 false, /* .isArray */
12373 false /* .isOptional */
12374},
12375{
12376 UA_TYPENAME("TargetName") /* .memberName */
12377 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12378 offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean), /* .padding */
12379 false, /* .isArray */
12380 false /* .isOptional */
12381},};
12382
12383/* RelativePath */
12384static UA_DataTypeMember RelativePath_members[1] = {
12385{
12386 UA_TYPENAME("Elements") /* .memberName */
12387 &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], /* .memberType */
12388 0, /* .padding */
12389 true, /* .isArray */
12390 false /* .isOptional */
12391},};
12392
12393/* BrowsePath */
12394static UA_DataTypeMember BrowsePath_members[2] = {
12395{
12396 UA_TYPENAME("StartingNode") /* .memberName */
12397 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12398 0, /* .padding */
12399 false, /* .isArray */
12400 false /* .isOptional */
12401},
12402{
12403 UA_TYPENAME("RelativePath") /* .memberName */
12404 &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
12405 offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId), /* .padding */
12406 false, /* .isArray */
12407 false /* .isOptional */
12408},};
12409
12410/* BrowsePathTarget */
12411static UA_DataTypeMember BrowsePathTarget_members[2] = {
12412{
12413 UA_TYPENAME("TargetId") /* .memberName */
12414 &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */
12415 0, /* .padding */
12416 false, /* .isArray */
12417 false /* .isOptional */
12418},
12419{
12420 UA_TYPENAME("RemainingPathIndex") /* .memberName */
12421 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12422 offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId), /* .padding */
12423 false, /* .isArray */
12424 false /* .isOptional */
12425},};
12426
12427/* BrowsePathResult */
12428static UA_DataTypeMember BrowsePathResult_members[2] = {
12429{
12430 UA_TYPENAME("StatusCode") /* .memberName */
12431 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12432 0, /* .padding */
12433 false, /* .isArray */
12434 false /* .isOptional */
12435},
12436{
12437 UA_TYPENAME("Targets") /* .memberName */
12438 &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], /* .memberType */
12439 offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12440 true, /* .isArray */
12441 false /* .isOptional */
12442},};
12443
12444/* TranslateBrowsePathsToNodeIdsRequest */
12445static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = {
12446{
12447 UA_TYPENAME("RequestHeader") /* .memberName */
12448 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12449 0, /* .padding */
12450 false, /* .isArray */
12451 false /* .isOptional */
12452},
12453{
12454 UA_TYPENAME("BrowsePaths") /* .memberName */
12455 &UA_TYPES[UA_TYPES_BROWSEPATH], /* .memberType */
12456 offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12457 true, /* .isArray */
12458 false /* .isOptional */
12459},};
12460
12461/* TranslateBrowsePathsToNodeIdsResponse */
12462static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = {
12463{
12464 UA_TYPENAME("ResponseHeader") /* .memberName */
12465 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12466 0, /* .padding */
12467 false, /* .isArray */
12468 false /* .isOptional */
12469},
12470{
12471 UA_TYPENAME("Results") /* .memberName */
12472 &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], /* .memberType */
12473 offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12474 true, /* .isArray */
12475 false /* .isOptional */
12476},
12477{
12478 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12479 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12480 offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void *), /* .padding */
12481 true, /* .isArray */
12482 false /* .isOptional */
12483},};
12484
12485/* RegisterNodesRequest */
12486static UA_DataTypeMember RegisterNodesRequest_members[2] = {
12487{
12488 UA_TYPENAME("RequestHeader") /* .memberName */
12489 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12490 0, /* .padding */
12491 false, /* .isArray */
12492 false /* .isOptional */
12493},
12494{
12495 UA_TYPENAME("NodesToRegister") /* .memberName */
12496 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12497 offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12498 true, /* .isArray */
12499 false /* .isOptional */
12500},};
12501
12502/* RegisterNodesResponse */
12503static UA_DataTypeMember RegisterNodesResponse_members[2] = {
12504{
12505 UA_TYPENAME("ResponseHeader") /* .memberName */
12506 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12507 0, /* .padding */
12508 false, /* .isArray */
12509 false /* .isOptional */
12510},
12511{
12512 UA_TYPENAME("RegisteredNodeIds") /* .memberName */
12513 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12514 offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12515 true, /* .isArray */
12516 false /* .isOptional */
12517},};
12518
12519/* UnregisterNodesRequest */
12520static UA_DataTypeMember UnregisterNodesRequest_members[2] = {
12521{
12522 UA_TYPENAME("RequestHeader") /* .memberName */
12523 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12524 0, /* .padding */
12525 false, /* .isArray */
12526 false /* .isOptional */
12527},
12528{
12529 UA_TYPENAME("NodesToUnregister") /* .memberName */
12530 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12531 offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12532 true, /* .isArray */
12533 false /* .isOptional */
12534},};
12535
12536/* UnregisterNodesResponse */
12537static UA_DataTypeMember UnregisterNodesResponse_members[1] = {
12538{
12539 UA_TYPENAME("ResponseHeader") /* .memberName */
12540 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12541 0, /* .padding */
12542 false, /* .isArray */
12543 false /* .isOptional */
12544},};
12545
12546/* FilterOperator */
12547#define FilterOperator_members NULL
12548
12549/* ContentFilterElement */
12550static UA_DataTypeMember ContentFilterElement_members[2] = {
12551{
12552 UA_TYPENAME("FilterOperator") /* .memberName */
12553 &UA_TYPES[UA_TYPES_FILTEROPERATOR], /* .memberType */
12554 0, /* .padding */
12555 false, /* .isArray */
12556 false /* .isOptional */
12557},
12558{
12559 UA_TYPENAME("FilterOperands") /* .memberName */
12560 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12561 offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator), /* .padding */
12562 true, /* .isArray */
12563 false /* .isOptional */
12564},};
12565
12566/* ContentFilter */
12567static UA_DataTypeMember ContentFilter_members[1] = {
12568{
12569 UA_TYPENAME("Elements") /* .memberName */
12570 &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], /* .memberType */
12571 0, /* .padding */
12572 true, /* .isArray */
12573 false /* .isOptional */
12574},};
12575
12576/* ElementOperand */
12577static UA_DataTypeMember ElementOperand_members[1] = {
12578{
12579 UA_TYPENAME("Index") /* .memberName */
12580 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12581 0, /* .padding */
12582 false, /* .isArray */
12583 false /* .isOptional */
12584},};
12585
12586/* LiteralOperand */
12587static UA_DataTypeMember LiteralOperand_members[1] = {
12588{
12589 UA_TYPENAME("Value") /* .memberName */
12590 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
12591 0, /* .padding */
12592 false, /* .isArray */
12593 false /* .isOptional */
12594},};
12595
12596/* AttributeOperand */
12597static UA_DataTypeMember AttributeOperand_members[5] = {
12598{
12599 UA_TYPENAME("NodeId") /* .memberName */
12600 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12601 0, /* .padding */
12602 false, /* .isArray */
12603 false /* .isOptional */
12604},
12605{
12606 UA_TYPENAME("Alias") /* .memberName */
12607 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12608 offsetof(UA_AttributeOperand, alias) - offsetof(UA_AttributeOperand, nodeId) - sizeof(UA_NodeId), /* .padding */
12609 false, /* .isArray */
12610 false /* .isOptional */
12611},
12612{
12613 UA_TYPENAME("BrowsePath") /* .memberName */
12614 &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */
12615 offsetof(UA_AttributeOperand, browsePath) - offsetof(UA_AttributeOperand, alias) - sizeof(UA_String), /* .padding */
12616 false, /* .isArray */
12617 false /* .isOptional */
12618},
12619{
12620 UA_TYPENAME("AttributeId") /* .memberName */
12621 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12622 offsetof(UA_AttributeOperand, attributeId) - offsetof(UA_AttributeOperand, browsePath) - sizeof(UA_RelativePath), /* .padding */
12623 false, /* .isArray */
12624 false /* .isOptional */
12625},
12626{
12627 UA_TYPENAME("IndexRange") /* .memberName */
12628 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12629 offsetof(UA_AttributeOperand, indexRange) - offsetof(UA_AttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
12630 false, /* .isArray */
12631 false /* .isOptional */
12632},};
12633
12634/* SimpleAttributeOperand */
12635static UA_DataTypeMember SimpleAttributeOperand_members[4] = {
12636{
12637 UA_TYPENAME("TypeDefinitionId") /* .memberName */
12638 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12639 0, /* .padding */
12640 false, /* .isArray */
12641 false /* .isOptional */
12642},
12643{
12644 UA_TYPENAME("BrowsePath") /* .memberName */
12645 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12646 offsetof(UA_SimpleAttributeOperand, browsePathSize) - offsetof(UA_SimpleAttributeOperand, typeDefinitionId) - sizeof(UA_NodeId), /* .padding */
12647 true, /* .isArray */
12648 false /* .isOptional */
12649},
12650{
12651 UA_TYPENAME("AttributeId") /* .memberName */
12652 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12653 offsetof(UA_SimpleAttributeOperand, attributeId) - offsetof(UA_SimpleAttributeOperand, browsePath) - sizeof(void *), /* .padding */
12654 false, /* .isArray */
12655 false /* .isOptional */
12656},
12657{
12658 UA_TYPENAME("IndexRange") /* .memberName */
12659 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12660 offsetof(UA_SimpleAttributeOperand, indexRange) - offsetof(UA_SimpleAttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */
12661 false, /* .isArray */
12662 false /* .isOptional */
12663},};
12664
12665/* ContentFilterElementResult */
12666static UA_DataTypeMember ContentFilterElementResult_members[3] = {
12667{
12668 UA_TYPENAME("StatusCode") /* .memberName */
12669 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12670 0, /* .padding */
12671 false, /* .isArray */
12672 false /* .isOptional */
12673},
12674{
12675 UA_TYPENAME("OperandStatusCodes") /* .memberName */
12676 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12677 offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12678 true, /* .isArray */
12679 false /* .isOptional */
12680},
12681{
12682 UA_TYPENAME("OperandDiagnosticInfos") /* .memberName */
12683 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12684 offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void *), /* .padding */
12685 true, /* .isArray */
12686 false /* .isOptional */
12687},};
12688
12689/* ContentFilterResult */
12690static UA_DataTypeMember ContentFilterResult_members[2] = {
12691{
12692 UA_TYPENAME("ElementResults") /* .memberName */
12693 &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], /* .memberType */
12694 0, /* .padding */
12695 true, /* .isArray */
12696 false /* .isOptional */
12697},
12698{
12699 UA_TYPENAME("ElementDiagnosticInfos") /* .memberName */
12700 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12701 offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void *), /* .padding */
12702 true, /* .isArray */
12703 false /* .isOptional */
12704},};
12705
12706/* TimestampsToReturn */
12707#define TimestampsToReturn_members NULL
12708
12709/* ReadValueId */
12710static UA_DataTypeMember ReadValueId_members[4] = {
12711{
12712 UA_TYPENAME("NodeId") /* .memberName */
12713 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12714 0, /* .padding */
12715 false, /* .isArray */
12716 false /* .isOptional */
12717},
12718{
12719 UA_TYPENAME("AttributeId") /* .memberName */
12720 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12721 offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
12722 false, /* .isArray */
12723 false /* .isOptional */
12724},
12725{
12726 UA_TYPENAME("IndexRange") /* .memberName */
12727 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12728 offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32), /* .padding */
12729 false, /* .isArray */
12730 false /* .isOptional */
12731},
12732{
12733 UA_TYPENAME("DataEncoding") /* .memberName */
12734 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12735 offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String), /* .padding */
12736 false, /* .isArray */
12737 false /* .isOptional */
12738},};
12739
12740/* ReadRequest */
12741static UA_DataTypeMember ReadRequest_members[4] = {
12742{
12743 UA_TYPENAME("RequestHeader") /* .memberName */
12744 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12745 0, /* .padding */
12746 false, /* .isArray */
12747 false /* .isOptional */
12748},
12749{
12750 UA_TYPENAME("MaxAge") /* .memberName */
12751 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
12752 offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12753 false, /* .isArray */
12754 false /* .isOptional */
12755},
12756{
12757 UA_TYPENAME("TimestampsToReturn") /* .memberName */
12758 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
12759 offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double), /* .padding */
12760 false, /* .isArray */
12761 false /* .isOptional */
12762},
12763{
12764 UA_TYPENAME("NodesToRead") /* .memberName */
12765 &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
12766 offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
12767 true, /* .isArray */
12768 false /* .isOptional */
12769},};
12770
12771/* ReadResponse */
12772static UA_DataTypeMember ReadResponse_members[3] = {
12773{
12774 UA_TYPENAME("ResponseHeader") /* .memberName */
12775 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12776 0, /* .padding */
12777 false, /* .isArray */
12778 false /* .isOptional */
12779},
12780{
12781 UA_TYPENAME("Results") /* .memberName */
12782 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
12783 offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12784 true, /* .isArray */
12785 false /* .isOptional */
12786},
12787{
12788 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12789 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12790 offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void *), /* .padding */
12791 true, /* .isArray */
12792 false /* .isOptional */
12793},};
12794
12795/* HistoryReadValueId */
12796static UA_DataTypeMember HistoryReadValueId_members[4] = {
12797{
12798 UA_TYPENAME("NodeId") /* .memberName */
12799 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12800 0, /* .padding */
12801 false, /* .isArray */
12802 false /* .isOptional */
12803},
12804{
12805 UA_TYPENAME("IndexRange") /* .memberName */
12806 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12807 offsetof(UA_HistoryReadValueId, indexRange) - offsetof(UA_HistoryReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */
12808 false, /* .isArray */
12809 false /* .isOptional */
12810},
12811{
12812 UA_TYPENAME("DataEncoding") /* .memberName */
12813 &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */
12814 offsetof(UA_HistoryReadValueId, dataEncoding) - offsetof(UA_HistoryReadValueId, indexRange) - sizeof(UA_String), /* .padding */
12815 false, /* .isArray */
12816 false /* .isOptional */
12817},
12818{
12819 UA_TYPENAME("ContinuationPoint") /* .memberName */
12820 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12821 offsetof(UA_HistoryReadValueId, continuationPoint) - offsetof(UA_HistoryReadValueId, dataEncoding) - sizeof(UA_QualifiedName), /* .padding */
12822 false, /* .isArray */
12823 false /* .isOptional */
12824},};
12825
12826/* HistoryReadResult */
12827static UA_DataTypeMember HistoryReadResult_members[3] = {
12828{
12829 UA_TYPENAME("StatusCode") /* .memberName */
12830 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
12831 0, /* .padding */
12832 false, /* .isArray */
12833 false /* .isOptional */
12834},
12835{
12836 UA_TYPENAME("ContinuationPoint") /* .memberName */
12837 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
12838 offsetof(UA_HistoryReadResult, continuationPoint) - offsetof(UA_HistoryReadResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
12839 false, /* .isArray */
12840 false /* .isOptional */
12841},
12842{
12843 UA_TYPENAME("HistoryData") /* .memberName */
12844 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12845 offsetof(UA_HistoryReadResult, historyData) - offsetof(UA_HistoryReadResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */
12846 false, /* .isArray */
12847 false /* .isOptional */
12848},};
12849
12850/* ReadRawModifiedDetails */
12851static UA_DataTypeMember ReadRawModifiedDetails_members[5] = {
12852{
12853 UA_TYPENAME("IsReadModified") /* .memberName */
12854 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12855 0, /* .padding */
12856 false, /* .isArray */
12857 false /* .isOptional */
12858},
12859{
12860 UA_TYPENAME("StartTime") /* .memberName */
12861 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12862 offsetof(UA_ReadRawModifiedDetails, startTime) - offsetof(UA_ReadRawModifiedDetails, isReadModified) - sizeof(UA_Boolean), /* .padding */
12863 false, /* .isArray */
12864 false /* .isOptional */
12865},
12866{
12867 UA_TYPENAME("EndTime") /* .memberName */
12868 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12869 offsetof(UA_ReadRawModifiedDetails, endTime) - offsetof(UA_ReadRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
12870 false, /* .isArray */
12871 false /* .isOptional */
12872},
12873{
12874 UA_TYPENAME("NumValuesPerNode") /* .memberName */
12875 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12876 offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - offsetof(UA_ReadRawModifiedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
12877 false, /* .isArray */
12878 false /* .isOptional */
12879},
12880{
12881 UA_TYPENAME("ReturnBounds") /* .memberName */
12882 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12883 offsetof(UA_ReadRawModifiedDetails, returnBounds) - offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
12884 false, /* .isArray */
12885 false /* .isOptional */
12886},};
12887
12888/* ReadAtTimeDetails */
12889static UA_DataTypeMember ReadAtTimeDetails_members[2] = {
12890{
12891 UA_TYPENAME("ReqTimes") /* .memberName */
12892 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
12893 0, /* .padding */
12894 true, /* .isArray */
12895 false /* .isOptional */
12896},
12897{
12898 UA_TYPENAME("UseSimpleBounds") /* .memberName */
12899 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12900 offsetof(UA_ReadAtTimeDetails, useSimpleBounds) - offsetof(UA_ReadAtTimeDetails, reqTimes) - sizeof(void *), /* .padding */
12901 false, /* .isArray */
12902 false /* .isOptional */
12903},};
12904
12905/* HistoryData */
12906static UA_DataTypeMember HistoryData_members[1] = {
12907{
12908 UA_TYPENAME("DataValues") /* .memberName */
12909 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
12910 0, /* .padding */
12911 true, /* .isArray */
12912 false /* .isOptional */
12913},};
12914
12915/* HistoryReadRequest */
12916static UA_DataTypeMember HistoryReadRequest_members[5] = {
12917{
12918 UA_TYPENAME("RequestHeader") /* .memberName */
12919 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
12920 0, /* .padding */
12921 false, /* .isArray */
12922 false /* .isOptional */
12923},
12924{
12925 UA_TYPENAME("HistoryReadDetails") /* .memberName */
12926 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
12927 offsetof(UA_HistoryReadRequest, historyReadDetails) - offsetof(UA_HistoryReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
12928 false, /* .isArray */
12929 false /* .isOptional */
12930},
12931{
12932 UA_TYPENAME("TimestampsToReturn") /* .memberName */
12933 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
12934 offsetof(UA_HistoryReadRequest, timestampsToReturn) - offsetof(UA_HistoryReadRequest, historyReadDetails) - sizeof(UA_ExtensionObject), /* .padding */
12935 false, /* .isArray */
12936 false /* .isOptional */
12937},
12938{
12939 UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */
12940 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
12941 offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - offsetof(UA_HistoryReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
12942 false, /* .isArray */
12943 false /* .isOptional */
12944},
12945{
12946 UA_TYPENAME("NodesToRead") /* .memberName */
12947 &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], /* .memberType */
12948 offsetof(UA_HistoryReadRequest, nodesToReadSize) - offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */
12949 true, /* .isArray */
12950 false /* .isOptional */
12951},};
12952
12953/* HistoryReadResponse */
12954static UA_DataTypeMember HistoryReadResponse_members[3] = {
12955{
12956 UA_TYPENAME("ResponseHeader") /* .memberName */
12957 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
12958 0, /* .padding */
12959 false, /* .isArray */
12960 false /* .isOptional */
12961},
12962{
12963 UA_TYPENAME("Results") /* .memberName */
12964 &UA_TYPES[UA_TYPES_HISTORYREADRESULT], /* .memberType */
12965 offsetof(UA_HistoryReadResponse, resultsSize) - offsetof(UA_HistoryReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
12966 true, /* .isArray */
12967 false /* .isOptional */
12968},
12969{
12970 UA_TYPENAME("DiagnosticInfos") /* .memberName */
12971 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
12972 offsetof(UA_HistoryReadResponse, diagnosticInfosSize) - offsetof(UA_HistoryReadResponse, results) - sizeof(void *), /* .padding */
12973 true, /* .isArray */
12974 false /* .isOptional */
12975},};
12976
12977/* WriteValue */
12978static UA_DataTypeMember WriteValue_members[4] = {
12979{
12980 UA_TYPENAME("NodeId") /* .memberName */
12981 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
12982 0, /* .padding */
12983 false, /* .isArray */
12984 false /* .isOptional */
12985},
12986{
12987 UA_TYPENAME("AttributeId") /* .memberName */
12988 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
12989 offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId), /* .padding */
12990 false, /* .isArray */
12991 false /* .isOptional */
12992},
12993{
12994 UA_TYPENAME("IndexRange") /* .memberName */
12995 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
12996 offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32), /* .padding */
12997 false, /* .isArray */
12998 false /* .isOptional */
12999},
13000{
13001 UA_TYPENAME("Value") /* .memberName */
13002 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
13003 offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String), /* .padding */
13004 false, /* .isArray */
13005 false /* .isOptional */
13006},};
13007
13008/* WriteRequest */
13009static UA_DataTypeMember WriteRequest_members[2] = {
13010{
13011 UA_TYPENAME("RequestHeader") /* .memberName */
13012 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13013 0, /* .padding */
13014 false, /* .isArray */
13015 false /* .isOptional */
13016},
13017{
13018 UA_TYPENAME("NodesToWrite") /* .memberName */
13019 &UA_TYPES[UA_TYPES_WRITEVALUE], /* .memberType */
13020 offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13021 true, /* .isArray */
13022 false /* .isOptional */
13023},};
13024
13025/* WriteResponse */
13026static UA_DataTypeMember WriteResponse_members[3] = {
13027{
13028 UA_TYPENAME("ResponseHeader") /* .memberName */
13029 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13030 0, /* .padding */
13031 false, /* .isArray */
13032 false /* .isOptional */
13033},
13034{
13035 UA_TYPENAME("Results") /* .memberName */
13036 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13037 offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13038 true, /* .isArray */
13039 false /* .isOptional */
13040},
13041{
13042 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13043 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13044 offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void *), /* .padding */
13045 true, /* .isArray */
13046 false /* .isOptional */
13047},};
13048
13049/* HistoryUpdateType */
13050#define HistoryUpdateType_members NULL
13051
13052/* PerformUpdateType */
13053#define PerformUpdateType_members NULL
13054
13055/* UpdateDataDetails */
13056static UA_DataTypeMember UpdateDataDetails_members[3] = {
13057{
13058 UA_TYPENAME("NodeId") /* .memberName */
13059 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13060 0, /* .padding */
13061 false, /* .isArray */
13062 false /* .isOptional */
13063},
13064{
13065 UA_TYPENAME("PerformInsertReplace") /* .memberName */
13066 &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */
13067 offsetof(UA_UpdateDataDetails, performInsertReplace) - offsetof(UA_UpdateDataDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
13068 false, /* .isArray */
13069 false /* .isOptional */
13070},
13071{
13072 UA_TYPENAME("UpdateValues") /* .memberName */
13073 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
13074 offsetof(UA_UpdateDataDetails, updateValuesSize) - offsetof(UA_UpdateDataDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */
13075 true, /* .isArray */
13076 false /* .isOptional */
13077},};
13078
13079/* DeleteRawModifiedDetails */
13080static UA_DataTypeMember DeleteRawModifiedDetails_members[4] = {
13081{
13082 UA_TYPENAME("NodeId") /* .memberName */
13083 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13084 0, /* .padding */
13085 false, /* .isArray */
13086 false /* .isOptional */
13087},
13088{
13089 UA_TYPENAME("IsDeleteModified") /* .memberName */
13090 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13091 offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - offsetof(UA_DeleteRawModifiedDetails, nodeId) - sizeof(UA_NodeId), /* .padding */
13092 false, /* .isArray */
13093 false /* .isOptional */
13094},
13095{
13096 UA_TYPENAME("StartTime") /* .memberName */
13097 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13098 offsetof(UA_DeleteRawModifiedDetails, startTime) - offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - sizeof(UA_Boolean), /* .padding */
13099 false, /* .isArray */
13100 false /* .isOptional */
13101},
13102{
13103 UA_TYPENAME("EndTime") /* .memberName */
13104 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13105 offsetof(UA_DeleteRawModifiedDetails, endTime) - offsetof(UA_DeleteRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
13106 false, /* .isArray */
13107 false /* .isOptional */
13108},};
13109
13110/* HistoryUpdateResult */
13111static UA_DataTypeMember HistoryUpdateResult_members[3] = {
13112{
13113 UA_TYPENAME("StatusCode") /* .memberName */
13114 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13115 0, /* .padding */
13116 false, /* .isArray */
13117 false /* .isOptional */
13118},
13119{
13120 UA_TYPENAME("OperationResults") /* .memberName */
13121 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13122 offsetof(UA_HistoryUpdateResult, operationResultsSize) - offsetof(UA_HistoryUpdateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13123 true, /* .isArray */
13124 false /* .isOptional */
13125},
13126{
13127 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13128 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13129 offsetof(UA_HistoryUpdateResult, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResult, operationResults) - sizeof(void *), /* .padding */
13130 true, /* .isArray */
13131 false /* .isOptional */
13132},};
13133
13134/* HistoryUpdateRequest */
13135static UA_DataTypeMember HistoryUpdateRequest_members[2] = {
13136{
13137 UA_TYPENAME("RequestHeader") /* .memberName */
13138 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13139 0, /* .padding */
13140 false, /* .isArray */
13141 false /* .isOptional */
13142},
13143{
13144 UA_TYPENAME("HistoryUpdateDetails") /* .memberName */
13145 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13146 offsetof(UA_HistoryUpdateRequest, historyUpdateDetailsSize) - offsetof(UA_HistoryUpdateRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13147 true, /* .isArray */
13148 false /* .isOptional */
13149},};
13150
13151/* HistoryUpdateResponse */
13152static UA_DataTypeMember HistoryUpdateResponse_members[3] = {
13153{
13154 UA_TYPENAME("ResponseHeader") /* .memberName */
13155 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13156 0, /* .padding */
13157 false, /* .isArray */
13158 false /* .isOptional */
13159},
13160{
13161 UA_TYPENAME("Results") /* .memberName */
13162 &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], /* .memberType */
13163 offsetof(UA_HistoryUpdateResponse, resultsSize) - offsetof(UA_HistoryUpdateResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13164 true, /* .isArray */
13165 false /* .isOptional */
13166},
13167{
13168 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13169 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13170 offsetof(UA_HistoryUpdateResponse, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResponse, results) - sizeof(void *), /* .padding */
13171 true, /* .isArray */
13172 false /* .isOptional */
13173},};
13174
13175/* CallMethodRequest */
13176static UA_DataTypeMember CallMethodRequest_members[3] = {
13177{
13178 UA_TYPENAME("ObjectId") /* .memberName */
13179 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13180 0, /* .padding */
13181 false, /* .isArray */
13182 false /* .isOptional */
13183},
13184{
13185 UA_TYPENAME("MethodId") /* .memberName */
13186 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13187 offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId), /* .padding */
13188 false, /* .isArray */
13189 false /* .isOptional */
13190},
13191{
13192 UA_TYPENAME("InputArguments") /* .memberName */
13193 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
13194 offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId), /* .padding */
13195 true, /* .isArray */
13196 false /* .isOptional */
13197},};
13198
13199/* CallMethodResult */
13200static UA_DataTypeMember CallMethodResult_members[4] = {
13201{
13202 UA_TYPENAME("StatusCode") /* .memberName */
13203 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13204 0, /* .padding */
13205 false, /* .isArray */
13206 false /* .isOptional */
13207},
13208{
13209 UA_TYPENAME("InputArgumentResults") /* .memberName */
13210 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13211 offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13212 true, /* .isArray */
13213 false /* .isOptional */
13214},
13215{
13216 UA_TYPENAME("InputArgumentDiagnosticInfos") /* .memberName */
13217 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13218 offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void *), /* .padding */
13219 true, /* .isArray */
13220 false /* .isOptional */
13221},
13222{
13223 UA_TYPENAME("OutputArguments") /* .memberName */
13224 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
13225 offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void *), /* .padding */
13226 true, /* .isArray */
13227 false /* .isOptional */
13228},};
13229
13230/* CallRequest */
13231static UA_DataTypeMember CallRequest_members[2] = {
13232{
13233 UA_TYPENAME("RequestHeader") /* .memberName */
13234 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13235 0, /* .padding */
13236 false, /* .isArray */
13237 false /* .isOptional */
13238},
13239{
13240 UA_TYPENAME("MethodsToCall") /* .memberName */
13241 &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], /* .memberType */
13242 offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13243 true, /* .isArray */
13244 false /* .isOptional */
13245},};
13246
13247/* CallResponse */
13248static UA_DataTypeMember CallResponse_members[3] = {
13249{
13250 UA_TYPENAME("ResponseHeader") /* .memberName */
13251 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13252 0, /* .padding */
13253 false, /* .isArray */
13254 false /* .isOptional */
13255},
13256{
13257 UA_TYPENAME("Results") /* .memberName */
13258 &UA_TYPES[UA_TYPES_CALLMETHODRESULT], /* .memberType */
13259 offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13260 true, /* .isArray */
13261 false /* .isOptional */
13262},
13263{
13264 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13265 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13266 offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void *), /* .padding */
13267 true, /* .isArray */
13268 false /* .isOptional */
13269},};
13270
13271/* MonitoringMode */
13272#define MonitoringMode_members NULL
13273
13274/* DataChangeTrigger */
13275#define DataChangeTrigger_members NULL
13276
13277/* DeadbandType */
13278#define DeadbandType_members NULL
13279
13280/* DataChangeFilter */
13281static UA_DataTypeMember DataChangeFilter_members[3] = {
13282{
13283 UA_TYPENAME("Trigger") /* .memberName */
13284 &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], /* .memberType */
13285 0, /* .padding */
13286 false, /* .isArray */
13287 false /* .isOptional */
13288},
13289{
13290 UA_TYPENAME("DeadbandType") /* .memberName */
13291 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13292 offsetof(UA_DataChangeFilter, deadbandType) - offsetof(UA_DataChangeFilter, trigger) - sizeof(UA_DataChangeTrigger), /* .padding */
13293 false, /* .isArray */
13294 false /* .isOptional */
13295},
13296{
13297 UA_TYPENAME("DeadbandValue") /* .memberName */
13298 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13299 offsetof(UA_DataChangeFilter, deadbandValue) - offsetof(UA_DataChangeFilter, deadbandType) - sizeof(UA_UInt32), /* .padding */
13300 false, /* .isArray */
13301 false /* .isOptional */
13302},};
13303
13304/* EventFilter */
13305static UA_DataTypeMember EventFilter_members[2] = {
13306{
13307 UA_TYPENAME("SelectClauses") /* .memberName */
13308 &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], /* .memberType */
13309 0, /* .padding */
13310 true, /* .isArray */
13311 false /* .isOptional */
13312},
13313{
13314 UA_TYPENAME("WhereClause") /* .memberName */
13315 &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */
13316 offsetof(UA_EventFilter, whereClause) - offsetof(UA_EventFilter, selectClauses) - sizeof(void *), /* .padding */
13317 false, /* .isArray */
13318 false /* .isOptional */
13319},};
13320
13321/* AggregateConfiguration */
13322static UA_DataTypeMember AggregateConfiguration_members[5] = {
13323{
13324 UA_TYPENAME("UseServerCapabilitiesDefaults") /* .memberName */
13325 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13326 0, /* .padding */
13327 false, /* .isArray */
13328 false /* .isOptional */
13329},
13330{
13331 UA_TYPENAME("TreatUncertainAsBad") /* .memberName */
13332 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13333 offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) - sizeof(UA_Boolean), /* .padding */
13334 false, /* .isArray */
13335 false /* .isOptional */
13336},
13337{
13338 UA_TYPENAME("PercentDataBad") /* .memberName */
13339 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13340 offsetof(UA_AggregateConfiguration, percentDataBad) - offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - sizeof(UA_Boolean), /* .padding */
13341 false, /* .isArray */
13342 false /* .isOptional */
13343},
13344{
13345 UA_TYPENAME("PercentDataGood") /* .memberName */
13346 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13347 offsetof(UA_AggregateConfiguration, percentDataGood) - offsetof(UA_AggregateConfiguration, percentDataBad) - sizeof(UA_Byte), /* .padding */
13348 false, /* .isArray */
13349 false /* .isOptional */
13350},
13351{
13352 UA_TYPENAME("UseSlopedExtrapolation") /* .memberName */
13353 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13354 offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) - offsetof(UA_AggregateConfiguration, percentDataGood) - sizeof(UA_Byte), /* .padding */
13355 false, /* .isArray */
13356 false /* .isOptional */
13357},};
13358
13359/* AggregateFilter */
13360static UA_DataTypeMember AggregateFilter_members[4] = {
13361{
13362 UA_TYPENAME("StartTime") /* .memberName */
13363 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
13364 0, /* .padding */
13365 false, /* .isArray */
13366 false /* .isOptional */
13367},
13368{
13369 UA_TYPENAME("AggregateType") /* .memberName */
13370 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
13371 offsetof(UA_AggregateFilter, aggregateType) - offsetof(UA_AggregateFilter, startTime) - sizeof(UA_DateTime), /* .padding */
13372 false, /* .isArray */
13373 false /* .isOptional */
13374},
13375{
13376 UA_TYPENAME("ProcessingInterval") /* .memberName */
13377 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13378 offsetof(UA_AggregateFilter, processingInterval) - offsetof(UA_AggregateFilter, aggregateType) - sizeof(UA_NodeId), /* .padding */
13379 false, /* .isArray */
13380 false /* .isOptional */
13381},
13382{
13383 UA_TYPENAME("AggregateConfiguration") /* .memberName */
13384 &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
13385 offsetof(UA_AggregateFilter, aggregateConfiguration) - offsetof(UA_AggregateFilter, processingInterval) - sizeof(UA_Double), /* .padding */
13386 false, /* .isArray */
13387 false /* .isOptional */
13388},};
13389
13390/* EventFilterResult */
13391static UA_DataTypeMember EventFilterResult_members[3] = {
13392{
13393 UA_TYPENAME("SelectClauseResults") /* .memberName */
13394 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13395 0, /* .padding */
13396 true, /* .isArray */
13397 false /* .isOptional */
13398},
13399{
13400 UA_TYPENAME("SelectClauseDiagnosticInfos") /* .memberName */
13401 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13402 offsetof(UA_EventFilterResult, selectClauseDiagnosticInfosSize) - offsetof(UA_EventFilterResult, selectClauseResults) - sizeof(void *), /* .padding */
13403 true, /* .isArray */
13404 false /* .isOptional */
13405},
13406{
13407 UA_TYPENAME("WhereClauseResult") /* .memberName */
13408 &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], /* .memberType */
13409 offsetof(UA_EventFilterResult, whereClauseResult) - offsetof(UA_EventFilterResult, selectClauseDiagnosticInfos) - sizeof(void *), /* .padding */
13410 false, /* .isArray */
13411 false /* .isOptional */
13412},};
13413
13414/* MonitoringParameters */
13415static UA_DataTypeMember MonitoringParameters_members[5] = {
13416{
13417 UA_TYPENAME("ClientHandle") /* .memberName */
13418 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13419 0, /* .padding */
13420 false, /* .isArray */
13421 false /* .isOptional */
13422},
13423{
13424 UA_TYPENAME("SamplingInterval") /* .memberName */
13425 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13426 offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32), /* .padding */
13427 false, /* .isArray */
13428 false /* .isOptional */
13429},
13430{
13431 UA_TYPENAME("Filter") /* .memberName */
13432 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13433 offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double), /* .padding */
13434 false, /* .isArray */
13435 false /* .isOptional */
13436},
13437{
13438 UA_TYPENAME("QueueSize") /* .memberName */
13439 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13440 offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject), /* .padding */
13441 false, /* .isArray */
13442 false /* .isOptional */
13443},
13444{
13445 UA_TYPENAME("DiscardOldest") /* .memberName */
13446 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13447 offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32), /* .padding */
13448 false, /* .isArray */
13449 false /* .isOptional */
13450},};
13451
13452/* MonitoredItemCreateRequest */
13453static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = {
13454{
13455 UA_TYPENAME("ItemToMonitor") /* .memberName */
13456 &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */
13457 0, /* .padding */
13458 false, /* .isArray */
13459 false /* .isOptional */
13460},
13461{
13462 UA_TYPENAME("MonitoringMode") /* .memberName */
13463 &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
13464 offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId), /* .padding */
13465 false, /* .isArray */
13466 false /* .isOptional */
13467},
13468{
13469 UA_TYPENAME("RequestedParameters") /* .memberName */
13470 &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
13471 offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
13472 false, /* .isArray */
13473 false /* .isOptional */
13474},};
13475
13476/* MonitoredItemCreateResult */
13477static UA_DataTypeMember MonitoredItemCreateResult_members[5] = {
13478{
13479 UA_TYPENAME("StatusCode") /* .memberName */
13480 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13481 0, /* .padding */
13482 false, /* .isArray */
13483 false /* .isOptional */
13484},
13485{
13486 UA_TYPENAME("MonitoredItemId") /* .memberName */
13487 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13488 offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13489 false, /* .isArray */
13490 false /* .isOptional */
13491},
13492{
13493 UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
13494 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13495 offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
13496 false, /* .isArray */
13497 false /* .isOptional */
13498},
13499{
13500 UA_TYPENAME("RevisedQueueSize") /* .memberName */
13501 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13502 offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
13503 false, /* .isArray */
13504 false /* .isOptional */
13505},
13506{
13507 UA_TYPENAME("FilterResult") /* .memberName */
13508 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13509 offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
13510 false, /* .isArray */
13511 false /* .isOptional */
13512},};
13513
13514/* CreateMonitoredItemsRequest */
13515static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = {
13516{
13517 UA_TYPENAME("RequestHeader") /* .memberName */
13518 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13519 0, /* .padding */
13520 false, /* .isArray */
13521 false /* .isOptional */
13522},
13523{
13524 UA_TYPENAME("SubscriptionId") /* .memberName */
13525 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13526 offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13527 false, /* .isArray */
13528 false /* .isOptional */
13529},
13530{
13531 UA_TYPENAME("TimestampsToReturn") /* .memberName */
13532 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
13533 offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13534 false, /* .isArray */
13535 false /* .isOptional */
13536},
13537{
13538 UA_TYPENAME("ItemsToCreate") /* .memberName */
13539 &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], /* .memberType */
13540 offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
13541 true, /* .isArray */
13542 false /* .isOptional */
13543},};
13544
13545/* CreateMonitoredItemsResponse */
13546static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = {
13547{
13548 UA_TYPENAME("ResponseHeader") /* .memberName */
13549 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13550 0, /* .padding */
13551 false, /* .isArray */
13552 false /* .isOptional */
13553},
13554{
13555 UA_TYPENAME("Results") /* .memberName */
13556 &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], /* .memberType */
13557 offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13558 true, /* .isArray */
13559 false /* .isOptional */
13560},
13561{
13562 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13563 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13564 offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13565 true, /* .isArray */
13566 false /* .isOptional */
13567},};
13568
13569/* MonitoredItemModifyRequest */
13570static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = {
13571{
13572 UA_TYPENAME("MonitoredItemId") /* .memberName */
13573 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13574 0, /* .padding */
13575 false, /* .isArray */
13576 false /* .isOptional */
13577},
13578{
13579 UA_TYPENAME("RequestedParameters") /* .memberName */
13580 &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */
13581 offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32), /* .padding */
13582 false, /* .isArray */
13583 false /* .isOptional */
13584},};
13585
13586/* MonitoredItemModifyResult */
13587static UA_DataTypeMember MonitoredItemModifyResult_members[4] = {
13588{
13589 UA_TYPENAME("StatusCode") /* .memberName */
13590 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13591 0, /* .padding */
13592 false, /* .isArray */
13593 false /* .isOptional */
13594},
13595{
13596 UA_TYPENAME("RevisedSamplingInterval") /* .memberName */
13597 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13598 offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
13599 false, /* .isArray */
13600 false /* .isOptional */
13601},
13602{
13603 UA_TYPENAME("RevisedQueueSize") /* .memberName */
13604 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13605 offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */
13606 false, /* .isArray */
13607 false /* .isOptional */
13608},
13609{
13610 UA_TYPENAME("FilterResult") /* .memberName */
13611 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
13612 offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */
13613 false, /* .isArray */
13614 false /* .isOptional */
13615},};
13616
13617/* ModifyMonitoredItemsRequest */
13618static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = {
13619{
13620 UA_TYPENAME("RequestHeader") /* .memberName */
13621 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13622 0, /* .padding */
13623 false, /* .isArray */
13624 false /* .isOptional */
13625},
13626{
13627 UA_TYPENAME("SubscriptionId") /* .memberName */
13628 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13629 offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13630 false, /* .isArray */
13631 false /* .isOptional */
13632},
13633{
13634 UA_TYPENAME("TimestampsToReturn") /* .memberName */
13635 &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */
13636 offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13637 false, /* .isArray */
13638 false /* .isOptional */
13639},
13640{
13641 UA_TYPENAME("ItemsToModify") /* .memberName */
13642 &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], /* .memberType */
13643 offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */
13644 true, /* .isArray */
13645 false /* .isOptional */
13646},};
13647
13648/* ModifyMonitoredItemsResponse */
13649static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = {
13650{
13651 UA_TYPENAME("ResponseHeader") /* .memberName */
13652 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13653 0, /* .padding */
13654 false, /* .isArray */
13655 false /* .isOptional */
13656},
13657{
13658 UA_TYPENAME("Results") /* .memberName */
13659 &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], /* .memberType */
13660 offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13661 true, /* .isArray */
13662 false /* .isOptional */
13663},
13664{
13665 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13666 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13667 offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13668 true, /* .isArray */
13669 false /* .isOptional */
13670},};
13671
13672/* SetMonitoringModeRequest */
13673static UA_DataTypeMember SetMonitoringModeRequest_members[4] = {
13674{
13675 UA_TYPENAME("RequestHeader") /* .memberName */
13676 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13677 0, /* .padding */
13678 false, /* .isArray */
13679 false /* .isOptional */
13680},
13681{
13682 UA_TYPENAME("SubscriptionId") /* .memberName */
13683 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13684 offsetof(UA_SetMonitoringModeRequest, subscriptionId) - offsetof(UA_SetMonitoringModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13685 false, /* .isArray */
13686 false /* .isOptional */
13687},
13688{
13689 UA_TYPENAME("MonitoringMode") /* .memberName */
13690 &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */
13691 offsetof(UA_SetMonitoringModeRequest, monitoringMode) - offsetof(UA_SetMonitoringModeRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13692 false, /* .isArray */
13693 false /* .isOptional */
13694},
13695{
13696 UA_TYPENAME("MonitoredItemIds") /* .memberName */
13697 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13698 offsetof(UA_SetMonitoringModeRequest, monitoredItemIdsSize) - offsetof(UA_SetMonitoringModeRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */
13699 true, /* .isArray */
13700 false /* .isOptional */
13701},};
13702
13703/* SetMonitoringModeResponse */
13704static UA_DataTypeMember SetMonitoringModeResponse_members[3] = {
13705{
13706 UA_TYPENAME("ResponseHeader") /* .memberName */
13707 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13708 0, /* .padding */
13709 false, /* .isArray */
13710 false /* .isOptional */
13711},
13712{
13713 UA_TYPENAME("Results") /* .memberName */
13714 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13715 offsetof(UA_SetMonitoringModeResponse, resultsSize) - offsetof(UA_SetMonitoringModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13716 true, /* .isArray */
13717 false /* .isOptional */
13718},
13719{
13720 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13721 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13722 offsetof(UA_SetMonitoringModeResponse, diagnosticInfosSize) - offsetof(UA_SetMonitoringModeResponse, results) - sizeof(void *), /* .padding */
13723 true, /* .isArray */
13724 false /* .isOptional */
13725},};
13726
13727/* SetTriggeringRequest */
13728static UA_DataTypeMember SetTriggeringRequest_members[5] = {
13729{
13730 UA_TYPENAME("RequestHeader") /* .memberName */
13731 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13732 0, /* .padding */
13733 false, /* .isArray */
13734 false /* .isOptional */
13735},
13736{
13737 UA_TYPENAME("SubscriptionId") /* .memberName */
13738 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13739 offsetof(UA_SetTriggeringRequest, subscriptionId) - offsetof(UA_SetTriggeringRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13740 false, /* .isArray */
13741 false /* .isOptional */
13742},
13743{
13744 UA_TYPENAME("TriggeringItemId") /* .memberName */
13745 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13746 offsetof(UA_SetTriggeringRequest, triggeringItemId) - offsetof(UA_SetTriggeringRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13747 false, /* .isArray */
13748 false /* .isOptional */
13749},
13750{
13751 UA_TYPENAME("LinksToAdd") /* .memberName */
13752 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13753 offsetof(UA_SetTriggeringRequest, linksToAddSize) - offsetof(UA_SetTriggeringRequest, triggeringItemId) - sizeof(UA_UInt32), /* .padding */
13754 true, /* .isArray */
13755 false /* .isOptional */
13756},
13757{
13758 UA_TYPENAME("LinksToRemove") /* .memberName */
13759 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13760 offsetof(UA_SetTriggeringRequest, linksToRemoveSize) - offsetof(UA_SetTriggeringRequest, linksToAdd) - sizeof(void *), /* .padding */
13761 true, /* .isArray */
13762 false /* .isOptional */
13763},};
13764
13765/* SetTriggeringResponse */
13766static UA_DataTypeMember SetTriggeringResponse_members[5] = {
13767{
13768 UA_TYPENAME("ResponseHeader") /* .memberName */
13769 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13770 0, /* .padding */
13771 false, /* .isArray */
13772 false /* .isOptional */
13773},
13774{
13775 UA_TYPENAME("AddResults") /* .memberName */
13776 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13777 offsetof(UA_SetTriggeringResponse, addResultsSize) - offsetof(UA_SetTriggeringResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13778 true, /* .isArray */
13779 false /* .isOptional */
13780},
13781{
13782 UA_TYPENAME("AddDiagnosticInfos") /* .memberName */
13783 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13784 offsetof(UA_SetTriggeringResponse, addDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, addResults) - sizeof(void *), /* .padding */
13785 true, /* .isArray */
13786 false /* .isOptional */
13787},
13788{
13789 UA_TYPENAME("RemoveResults") /* .memberName */
13790 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13791 offsetof(UA_SetTriggeringResponse, removeResultsSize) - offsetof(UA_SetTriggeringResponse, addDiagnosticInfos) - sizeof(void *), /* .padding */
13792 true, /* .isArray */
13793 false /* .isOptional */
13794},
13795{
13796 UA_TYPENAME("RemoveDiagnosticInfos") /* .memberName */
13797 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13798 offsetof(UA_SetTriggeringResponse, removeDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, removeResults) - sizeof(void *), /* .padding */
13799 true, /* .isArray */
13800 false /* .isOptional */
13801},};
13802
13803/* DeleteMonitoredItemsRequest */
13804static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = {
13805{
13806 UA_TYPENAME("RequestHeader") /* .memberName */
13807 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13808 0, /* .padding */
13809 false, /* .isArray */
13810 false /* .isOptional */
13811},
13812{
13813 UA_TYPENAME("SubscriptionId") /* .memberName */
13814 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13815 offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13816 false, /* .isArray */
13817 false /* .isOptional */
13818},
13819{
13820 UA_TYPENAME("MonitoredItemIds") /* .memberName */
13821 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13822 offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13823 true, /* .isArray */
13824 false /* .isOptional */
13825},};
13826
13827/* DeleteMonitoredItemsResponse */
13828static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = {
13829{
13830 UA_TYPENAME("ResponseHeader") /* .memberName */
13831 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13832 0, /* .padding */
13833 false, /* .isArray */
13834 false /* .isOptional */
13835},
13836{
13837 UA_TYPENAME("Results") /* .memberName */
13838 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
13839 offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13840 true, /* .isArray */
13841 false /* .isOptional */
13842},
13843{
13844 UA_TYPENAME("DiagnosticInfos") /* .memberName */
13845 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
13846 offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void *), /* .padding */
13847 true, /* .isArray */
13848 false /* .isOptional */
13849},};
13850
13851/* CreateSubscriptionRequest */
13852static UA_DataTypeMember CreateSubscriptionRequest_members[7] = {
13853{
13854 UA_TYPENAME("RequestHeader") /* .memberName */
13855 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13856 0, /* .padding */
13857 false, /* .isArray */
13858 false /* .isOptional */
13859},
13860{
13861 UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
13862 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13863 offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13864 false, /* .isArray */
13865 false /* .isOptional */
13866},
13867{
13868 UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
13869 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13870 offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
13871 false, /* .isArray */
13872 false /* .isOptional */
13873},
13874{
13875 UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
13876 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13877 offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13878 false, /* .isArray */
13879 false /* .isOptional */
13880},
13881{
13882 UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
13883 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13884 offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
13885 false, /* .isArray */
13886 false /* .isOptional */
13887},
13888{
13889 UA_TYPENAME("PublishingEnabled") /* .memberName */
13890 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
13891 offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
13892 false, /* .isArray */
13893 false /* .isOptional */
13894},
13895{
13896 UA_TYPENAME("Priority") /* .memberName */
13897 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13898 offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
13899 false, /* .isArray */
13900 false /* .isOptional */
13901},};
13902
13903/* CreateSubscriptionResponse */
13904static UA_DataTypeMember CreateSubscriptionResponse_members[5] = {
13905{
13906 UA_TYPENAME("ResponseHeader") /* .memberName */
13907 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13908 0, /* .padding */
13909 false, /* .isArray */
13910 false /* .isOptional */
13911},
13912{
13913 UA_TYPENAME("SubscriptionId") /* .memberName */
13914 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13915 offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
13916 false, /* .isArray */
13917 false /* .isOptional */
13918},
13919{
13920 UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
13921 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13922 offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13923 false, /* .isArray */
13924 false /* .isOptional */
13925},
13926{
13927 UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
13928 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13929 offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
13930 false, /* .isArray */
13931 false /* .isOptional */
13932},
13933{
13934 UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
13935 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13936 offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13937 false, /* .isArray */
13938 false /* .isOptional */
13939},};
13940
13941/* ModifySubscriptionRequest */
13942static UA_DataTypeMember ModifySubscriptionRequest_members[7] = {
13943{
13944 UA_TYPENAME("RequestHeader") /* .memberName */
13945 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
13946 0, /* .padding */
13947 false, /* .isArray */
13948 false /* .isOptional */
13949},
13950{
13951 UA_TYPENAME("SubscriptionId") /* .memberName */
13952 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13953 offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
13954 false, /* .isArray */
13955 false /* .isOptional */
13956},
13957{
13958 UA_TYPENAME("RequestedPublishingInterval") /* .memberName */
13959 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
13960 offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
13961 false, /* .isArray */
13962 false /* .isOptional */
13963},
13964{
13965 UA_TYPENAME("RequestedLifetimeCount") /* .memberName */
13966 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13967 offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */
13968 false, /* .isArray */
13969 false /* .isOptional */
13970},
13971{
13972 UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */
13973 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13974 offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
13975 false, /* .isArray */
13976 false /* .isOptional */
13977},
13978{
13979 UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */
13980 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
13981 offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */
13982 false, /* .isArray */
13983 false /* .isOptional */
13984},
13985{
13986 UA_TYPENAME("Priority") /* .memberName */
13987 &UA_TYPES[UA_TYPES_BYTE], /* .memberType */
13988 offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */
13989 false, /* .isArray */
13990 false /* .isOptional */
13991},};
13992
13993/* ModifySubscriptionResponse */
13994static UA_DataTypeMember ModifySubscriptionResponse_members[4] = {
13995{
13996 UA_TYPENAME("ResponseHeader") /* .memberName */
13997 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
13998 0, /* .padding */
13999 false, /* .isArray */
14000 false /* .isOptional */
14001},
14002{
14003 UA_TYPENAME("RevisedPublishingInterval") /* .memberName */
14004 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14005 offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14006 false, /* .isArray */
14007 false /* .isOptional */
14008},
14009{
14010 UA_TYPENAME("RevisedLifetimeCount") /* .memberName */
14011 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14012 offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */
14013 false, /* .isArray */
14014 false /* .isOptional */
14015},
14016{
14017 UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */
14018 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14019 offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */
14020 false, /* .isArray */
14021 false /* .isOptional */
14022},};
14023
14024/* SetPublishingModeRequest */
14025static UA_DataTypeMember SetPublishingModeRequest_members[3] = {
14026{
14027 UA_TYPENAME("RequestHeader") /* .memberName */
14028 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14029 0, /* .padding */
14030 false, /* .isArray */
14031 false /* .isOptional */
14032},
14033{
14034 UA_TYPENAME("PublishingEnabled") /* .memberName */
14035 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14036 offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14037 false, /* .isArray */
14038 false /* .isOptional */
14039},
14040{
14041 UA_TYPENAME("SubscriptionIds") /* .memberName */
14042 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14043 offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */
14044 true, /* .isArray */
14045 false /* .isOptional */
14046},};
14047
14048/* SetPublishingModeResponse */
14049static UA_DataTypeMember SetPublishingModeResponse_members[3] = {
14050{
14051 UA_TYPENAME("ResponseHeader") /* .memberName */
14052 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14053 0, /* .padding */
14054 false, /* .isArray */
14055 false /* .isOptional */
14056},
14057{
14058 UA_TYPENAME("Results") /* .memberName */
14059 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14060 offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14061 true, /* .isArray */
14062 false /* .isOptional */
14063},
14064{
14065 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14066 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14067 offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void *), /* .padding */
14068 true, /* .isArray */
14069 false /* .isOptional */
14070},};
14071
14072/* NotificationMessage */
14073static UA_DataTypeMember NotificationMessage_members[3] = {
14074{
14075 UA_TYPENAME("SequenceNumber") /* .memberName */
14076 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14077 0, /* .padding */
14078 false, /* .isArray */
14079 false /* .isOptional */
14080},
14081{
14082 UA_TYPENAME("PublishTime") /* .memberName */
14083 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14084 offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
14085 false, /* .isArray */
14086 false /* .isOptional */
14087},
14088{
14089 UA_TYPENAME("NotificationData") /* .memberName */
14090 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */
14091 offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime), /* .padding */
14092 true, /* .isArray */
14093 false /* .isOptional */
14094},};
14095
14096/* MonitoredItemNotification */
14097static UA_DataTypeMember MonitoredItemNotification_members[2] = {
14098{
14099 UA_TYPENAME("ClientHandle") /* .memberName */
14100 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14101 0, /* .padding */
14102 false, /* .isArray */
14103 false /* .isOptional */
14104},
14105{
14106 UA_TYPENAME("Value") /* .memberName */
14107 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
14108 offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32), /* .padding */
14109 false, /* .isArray */
14110 false /* .isOptional */
14111},};
14112
14113/* EventFieldList */
14114static UA_DataTypeMember EventFieldList_members[2] = {
14115{
14116 UA_TYPENAME("ClientHandle") /* .memberName */
14117 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14118 0, /* .padding */
14119 false, /* .isArray */
14120 false /* .isOptional */
14121},
14122{
14123 UA_TYPENAME("EventFields") /* .memberName */
14124 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
14125 offsetof(UA_EventFieldList, eventFieldsSize) - offsetof(UA_EventFieldList, clientHandle) - sizeof(UA_UInt32), /* .padding */
14126 true, /* .isArray */
14127 false /* .isOptional */
14128},};
14129
14130/* HistoryEventFieldList */
14131static UA_DataTypeMember HistoryEventFieldList_members[1] = {
14132{
14133 UA_TYPENAME("EventFields") /* .memberName */
14134 &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */
14135 0, /* .padding */
14136 true, /* .isArray */
14137 false /* .isOptional */
14138},};
14139
14140/* StatusChangeNotification */
14141static UA_DataTypeMember StatusChangeNotification_members[2] = {
14142{
14143 UA_TYPENAME("Status") /* .memberName */
14144 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14145 0, /* .padding */
14146 false, /* .isArray */
14147 false /* .isOptional */
14148},
14149{
14150 UA_TYPENAME("DiagnosticInfo") /* .memberName */
14151 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14152 offsetof(UA_StatusChangeNotification, diagnosticInfo) - offsetof(UA_StatusChangeNotification, status) - sizeof(UA_StatusCode), /* .padding */
14153 false, /* .isArray */
14154 false /* .isOptional */
14155},};
14156
14157/* SubscriptionAcknowledgement */
14158static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = {
14159{
14160 UA_TYPENAME("SubscriptionId") /* .memberName */
14161 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14162 0, /* .padding */
14163 false, /* .isArray */
14164 false /* .isOptional */
14165},
14166{
14167 UA_TYPENAME("SequenceNumber") /* .memberName */
14168 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14169 offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14170 false, /* .isArray */
14171 false /* .isOptional */
14172},};
14173
14174/* PublishRequest */
14175static UA_DataTypeMember PublishRequest_members[2] = {
14176{
14177 UA_TYPENAME("RequestHeader") /* .memberName */
14178 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14179 0, /* .padding */
14180 false, /* .isArray */
14181 false /* .isOptional */
14182},
14183{
14184 UA_TYPENAME("SubscriptionAcknowledgements") /* .memberName */
14185 &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], /* .memberType */
14186 offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14187 true, /* .isArray */
14188 false /* .isOptional */
14189},};
14190
14191/* PublishResponse */
14192static UA_DataTypeMember PublishResponse_members[7] = {
14193{
14194 UA_TYPENAME("ResponseHeader") /* .memberName */
14195 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14196 0, /* .padding */
14197 false, /* .isArray */
14198 false /* .isOptional */
14199},
14200{
14201 UA_TYPENAME("SubscriptionId") /* .memberName */
14202 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14203 offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14204 false, /* .isArray */
14205 false /* .isOptional */
14206},
14207{
14208 UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
14209 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14210 offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14211 true, /* .isArray */
14212 false /* .isOptional */
14213},
14214{
14215 UA_TYPENAME("MoreNotifications") /* .memberName */
14216 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14217 offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void *), /* .padding */
14218 false, /* .isArray */
14219 false /* .isOptional */
14220},
14221{
14222 UA_TYPENAME("NotificationMessage") /* .memberName */
14223 &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
14224 offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean), /* .padding */
14225 false, /* .isArray */
14226 false /* .isOptional */
14227},
14228{
14229 UA_TYPENAME("Results") /* .memberName */
14230 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14231 offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage), /* .padding */
14232 true, /* .isArray */
14233 false /* .isOptional */
14234},
14235{
14236 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14237 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14238 offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void *), /* .padding */
14239 true, /* .isArray */
14240 false /* .isOptional */
14241},};
14242
14243/* RepublishRequest */
14244static UA_DataTypeMember RepublishRequest_members[3] = {
14245{
14246 UA_TYPENAME("RequestHeader") /* .memberName */
14247 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14248 0, /* .padding */
14249 false, /* .isArray */
14250 false /* .isOptional */
14251},
14252{
14253 UA_TYPENAME("SubscriptionId") /* .memberName */
14254 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14255 offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14256 false, /* .isArray */
14257 false /* .isOptional */
14258},
14259{
14260 UA_TYPENAME("RetransmitSequenceNumber") /* .memberName */
14261 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14262 offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */
14263 false, /* .isArray */
14264 false /* .isOptional */
14265},};
14266
14267/* RepublishResponse */
14268static UA_DataTypeMember RepublishResponse_members[2] = {
14269{
14270 UA_TYPENAME("ResponseHeader") /* .memberName */
14271 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14272 0, /* .padding */
14273 false, /* .isArray */
14274 false /* .isOptional */
14275},
14276{
14277 UA_TYPENAME("NotificationMessage") /* .memberName */
14278 &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */
14279 offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14280 false, /* .isArray */
14281 false /* .isOptional */
14282},};
14283
14284/* TransferResult */
14285static UA_DataTypeMember TransferResult_members[2] = {
14286{
14287 UA_TYPENAME("StatusCode") /* .memberName */
14288 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14289 0, /* .padding */
14290 false, /* .isArray */
14291 false /* .isOptional */
14292},
14293{
14294 UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */
14295 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14296 offsetof(UA_TransferResult, availableSequenceNumbersSize) - offsetof(UA_TransferResult, statusCode) - sizeof(UA_StatusCode), /* .padding */
14297 true, /* .isArray */
14298 false /* .isOptional */
14299},};
14300
14301/* TransferSubscriptionsRequest */
14302static UA_DataTypeMember TransferSubscriptionsRequest_members[3] = {
14303{
14304 UA_TYPENAME("RequestHeader") /* .memberName */
14305 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14306 0, /* .padding */
14307 false, /* .isArray */
14308 false /* .isOptional */
14309},
14310{
14311 UA_TYPENAME("SubscriptionIds") /* .memberName */
14312 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14313 offsetof(UA_TransferSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_TransferSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14314 true, /* .isArray */
14315 false /* .isOptional */
14316},
14317{
14318 UA_TYPENAME("SendInitialValues") /* .memberName */
14319 &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */
14320 offsetof(UA_TransferSubscriptionsRequest, sendInitialValues) - offsetof(UA_TransferSubscriptionsRequest, subscriptionIds) - sizeof(void *), /* .padding */
14321 false, /* .isArray */
14322 false /* .isOptional */
14323},};
14324
14325/* TransferSubscriptionsResponse */
14326static UA_DataTypeMember TransferSubscriptionsResponse_members[3] = {
14327{
14328 UA_TYPENAME("ResponseHeader") /* .memberName */
14329 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14330 0, /* .padding */
14331 false, /* .isArray */
14332 false /* .isOptional */
14333},
14334{
14335 UA_TYPENAME("Results") /* .memberName */
14336 &UA_TYPES[UA_TYPES_TRANSFERRESULT], /* .memberType */
14337 offsetof(UA_TransferSubscriptionsResponse, resultsSize) - offsetof(UA_TransferSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14338 true, /* .isArray */
14339 false /* .isOptional */
14340},
14341{
14342 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14343 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14344 offsetof(UA_TransferSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_TransferSubscriptionsResponse, results) - sizeof(void *), /* .padding */
14345 true, /* .isArray */
14346 false /* .isOptional */
14347},};
14348
14349/* DeleteSubscriptionsRequest */
14350static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = {
14351{
14352 UA_TYPENAME("RequestHeader") /* .memberName */
14353 &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */
14354 0, /* .padding */
14355 false, /* .isArray */
14356 false /* .isOptional */
14357},
14358{
14359 UA_TYPENAME("SubscriptionIds") /* .memberName */
14360 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14361 offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */
14362 true, /* .isArray */
14363 false /* .isOptional */
14364},};
14365
14366/* DeleteSubscriptionsResponse */
14367static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = {
14368{
14369 UA_TYPENAME("ResponseHeader") /* .memberName */
14370 &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */
14371 0, /* .padding */
14372 false, /* .isArray */
14373 false /* .isOptional */
14374},
14375{
14376 UA_TYPENAME("Results") /* .memberName */
14377 &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */
14378 offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */
14379 true, /* .isArray */
14380 false /* .isOptional */
14381},
14382{
14383 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14384 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14385 offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void *), /* .padding */
14386 true, /* .isArray */
14387 false /* .isOptional */
14388},};
14389
14390/* BuildInfo */
14391static UA_DataTypeMember BuildInfo_members[6] = {
14392{
14393 UA_TYPENAME("ProductUri") /* .memberName */
14394 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14395 0, /* .padding */
14396 false, /* .isArray */
14397 false /* .isOptional */
14398},
14399{
14400 UA_TYPENAME("ManufacturerName") /* .memberName */
14401 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14402 offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String), /* .padding */
14403 false, /* .isArray */
14404 false /* .isOptional */
14405},
14406{
14407 UA_TYPENAME("ProductName") /* .memberName */
14408 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14409 offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String), /* .padding */
14410 false, /* .isArray */
14411 false /* .isOptional */
14412},
14413{
14414 UA_TYPENAME("SoftwareVersion") /* .memberName */
14415 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14416 offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String), /* .padding */
14417 false, /* .isArray */
14418 false /* .isOptional */
14419},
14420{
14421 UA_TYPENAME("BuildNumber") /* .memberName */
14422 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14423 offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String), /* .padding */
14424 false, /* .isArray */
14425 false /* .isOptional */
14426},
14427{
14428 UA_TYPENAME("BuildDate") /* .memberName */
14429 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14430 offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String), /* .padding */
14431 false, /* .isArray */
14432 false /* .isOptional */
14433},};
14434
14435/* RedundancySupport */
14436#define RedundancySupport_members NULL
14437
14438/* ServerState */
14439#define ServerState_members NULL
14440
14441/* ServerDiagnosticsSummaryDataType */
14442static UA_DataTypeMember ServerDiagnosticsSummaryDataType_members[12] = {
14443{
14444 UA_TYPENAME("ServerViewCount") /* .memberName */
14445 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14446 0, /* .padding */
14447 false, /* .isArray */
14448 false /* .isOptional */
14449},
14450{
14451 UA_TYPENAME("CurrentSessionCount") /* .memberName */
14452 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14453 offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) - sizeof(UA_UInt32), /* .padding */
14454 false, /* .isArray */
14455 false /* .isOptional */
14456},
14457{
14458 UA_TYPENAME("CumulatedSessionCount") /* .memberName */
14459 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14460 offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - sizeof(UA_UInt32), /* .padding */
14461 false, /* .isArray */
14462 false /* .isOptional */
14463},
14464{
14465 UA_TYPENAME("SecurityRejectedSessionCount") /* .memberName */
14466 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14467 offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - sizeof(UA_UInt32), /* .padding */
14468 false, /* .isArray */
14469 false /* .isOptional */
14470},
14471{
14472 UA_TYPENAME("RejectedSessionCount") /* .memberName */
14473 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14474 offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
14475 false, /* .isArray */
14476 false /* .isOptional */
14477},
14478{
14479 UA_TYPENAME("SessionTimeoutCount") /* .memberName */
14480 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14481 offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - sizeof(UA_UInt32), /* .padding */
14482 false, /* .isArray */
14483 false /* .isOptional */
14484},
14485{
14486 UA_TYPENAME("SessionAbortCount") /* .memberName */
14487 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14488 offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - sizeof(UA_UInt32), /* .padding */
14489 false, /* .isArray */
14490 false /* .isOptional */
14491},
14492{
14493 UA_TYPENAME("CurrentSubscriptionCount") /* .memberName */
14494 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14495 offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - sizeof(UA_UInt32), /* .padding */
14496 false, /* .isArray */
14497 false /* .isOptional */
14498},
14499{
14500 UA_TYPENAME("CumulatedSubscriptionCount") /* .memberName */
14501 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14502 offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
14503 false, /* .isArray */
14504 false /* .isOptional */
14505},
14506{
14507 UA_TYPENAME("PublishingIntervalCount") /* .memberName */
14508 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14509 offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - sizeof(UA_UInt32), /* .padding */
14510 false, /* .isArray */
14511 false /* .isOptional */
14512},
14513{
14514 UA_TYPENAME("SecurityRejectedRequestsCount") /* .memberName */
14515 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14516 offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - sizeof(UA_UInt32), /* .padding */
14517 false, /* .isArray */
14518 false /* .isOptional */
14519},
14520{
14521 UA_TYPENAME("RejectedRequestsCount") /* .memberName */
14522 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14523 offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - sizeof(UA_UInt32), /* .padding */
14524 false, /* .isArray */
14525 false /* .isOptional */
14526},};
14527
14528/* ServerStatusDataType */
14529static UA_DataTypeMember ServerStatusDataType_members[6] = {
14530{
14531 UA_TYPENAME("StartTime") /* .memberName */
14532 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14533 0, /* .padding */
14534 false, /* .isArray */
14535 false /* .isOptional */
14536},
14537{
14538 UA_TYPENAME("CurrentTime") /* .memberName */
14539 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14540 offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime), /* .padding */
14541 false, /* .isArray */
14542 false /* .isOptional */
14543},
14544{
14545 UA_TYPENAME("State") /* .memberName */
14546 &UA_TYPES[UA_TYPES_SERVERSTATE], /* .memberType */
14547 offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime), /* .padding */
14548 false, /* .isArray */
14549 false /* .isOptional */
14550},
14551{
14552 UA_TYPENAME("BuildInfo") /* .memberName */
14553 &UA_TYPES[UA_TYPES_BUILDINFO], /* .memberType */
14554 offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState), /* .padding */
14555 false, /* .isArray */
14556 false /* .isOptional */
14557},
14558{
14559 UA_TYPENAME("SecondsTillShutdown") /* .memberName */
14560 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14561 offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo), /* .padding */
14562 false, /* .isArray */
14563 false /* .isOptional */
14564},
14565{
14566 UA_TYPENAME("ShutdownReason") /* .memberName */
14567 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14568 offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32), /* .padding */
14569 false, /* .isArray */
14570 false /* .isOptional */
14571},};
14572
14573/* Range */
14574static UA_DataTypeMember Range_members[2] = {
14575{
14576 UA_TYPENAME("Low") /* .memberName */
14577 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14578 0, /* .padding */
14579 false, /* .isArray */
14580 false /* .isOptional */
14581},
14582{
14583 UA_TYPENAME("High") /* .memberName */
14584 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14585 offsetof(UA_Range, high) - offsetof(UA_Range, low) - sizeof(UA_Double), /* .padding */
14586 false, /* .isArray */
14587 false /* .isOptional */
14588},};
14589
14590/* EUInformation */
14591static UA_DataTypeMember EUInformation_members[4] = {
14592{
14593 UA_TYPENAME("NamespaceUri") /* .memberName */
14594 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14595 0, /* .padding */
14596 false, /* .isArray */
14597 false /* .isOptional */
14598},
14599{
14600 UA_TYPENAME("UnitId") /* .memberName */
14601 &UA_TYPES[UA_TYPES_INT32], /* .memberType */
14602 offsetof(UA_EUInformation, unitId) - offsetof(UA_EUInformation, namespaceUri) - sizeof(UA_String), /* .padding */
14603 false, /* .isArray */
14604 false /* .isOptional */
14605},
14606{
14607 UA_TYPENAME("DisplayName") /* .memberName */
14608 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14609 offsetof(UA_EUInformation, displayName) - offsetof(UA_EUInformation, unitId) - sizeof(UA_Int32), /* .padding */
14610 false, /* .isArray */
14611 false /* .isOptional */
14612},
14613{
14614 UA_TYPENAME("Description") /* .memberName */
14615 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14616 offsetof(UA_EUInformation, description) - offsetof(UA_EUInformation, displayName) - sizeof(UA_LocalizedText), /* .padding */
14617 false, /* .isArray */
14618 false /* .isOptional */
14619},};
14620
14621/* AxisScaleEnumeration */
14622#define AxisScaleEnumeration_members NULL
14623
14624/* ComplexNumberType */
14625static UA_DataTypeMember ComplexNumberType_members[2] = {
14626{
14627 UA_TYPENAME("Real") /* .memberName */
14628 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14629 0, /* .padding */
14630 false, /* .isArray */
14631 false /* .isOptional */
14632},
14633{
14634 UA_TYPENAME("Imaginary") /* .memberName */
14635 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14636 offsetof(UA_ComplexNumberType, imaginary) - offsetof(UA_ComplexNumberType, real) - sizeof(UA_Float), /* .padding */
14637 false, /* .isArray */
14638 false /* .isOptional */
14639},};
14640
14641/* DoubleComplexNumberType */
14642static UA_DataTypeMember DoubleComplexNumberType_members[2] = {
14643{
14644 UA_TYPENAME("Real") /* .memberName */
14645 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14646 0, /* .padding */
14647 false, /* .isArray */
14648 false /* .isOptional */
14649},
14650{
14651 UA_TYPENAME("Imaginary") /* .memberName */
14652 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14653 offsetof(UA_DoubleComplexNumberType, imaginary) - offsetof(UA_DoubleComplexNumberType, real) - sizeof(UA_Double), /* .padding */
14654 false, /* .isArray */
14655 false /* .isOptional */
14656},};
14657
14658/* AxisInformation */
14659static UA_DataTypeMember AxisInformation_members[5] = {
14660{
14661 UA_TYPENAME("EngineeringUnits") /* .memberName */
14662 &UA_TYPES[UA_TYPES_EUINFORMATION], /* .memberType */
14663 0, /* .padding */
14664 false, /* .isArray */
14665 false /* .isOptional */
14666},
14667{
14668 UA_TYPENAME("EURange") /* .memberName */
14669 &UA_TYPES[UA_TYPES_RANGE], /* .memberType */
14670 offsetof(UA_AxisInformation, eURange) - offsetof(UA_AxisInformation, engineeringUnits) - sizeof(UA_EUInformation), /* .padding */
14671 false, /* .isArray */
14672 false /* .isOptional */
14673},
14674{
14675 UA_TYPENAME("Title") /* .memberName */
14676 &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */
14677 offsetof(UA_AxisInformation, title) - offsetof(UA_AxisInformation, eURange) - sizeof(UA_Range), /* .padding */
14678 false, /* .isArray */
14679 false /* .isOptional */
14680},
14681{
14682 UA_TYPENAME("AxisScaleType") /* .memberName */
14683 &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], /* .memberType */
14684 offsetof(UA_AxisInformation, axisScaleType) - offsetof(UA_AxisInformation, title) - sizeof(UA_LocalizedText), /* .padding */
14685 false, /* .isArray */
14686 false /* .isOptional */
14687},
14688{
14689 UA_TYPENAME("AxisSteps") /* .memberName */
14690 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14691 offsetof(UA_AxisInformation, axisStepsSize) - offsetof(UA_AxisInformation, axisScaleType) - sizeof(UA_AxisScaleEnumeration), /* .padding */
14692 true, /* .isArray */
14693 false /* .isOptional */
14694},};
14695
14696/* XVType */
14697static UA_DataTypeMember XVType_members[2] = {
14698{
14699 UA_TYPENAME("X") /* .memberName */
14700 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14701 0, /* .padding */
14702 false, /* .isArray */
14703 false /* .isOptional */
14704},
14705{
14706 UA_TYPENAME("Value") /* .memberName */
14707 &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */
14708 offsetof(UA_XVType, value) - offsetof(UA_XVType, x) - sizeof(UA_Double), /* .padding */
14709 false, /* .isArray */
14710 false /* .isOptional */
14711},};
14712
14713/* EnumDefinition */
14714static UA_DataTypeMember EnumDefinition_members[1] = {
14715{
14716 UA_TYPENAME("Fields") /* .memberName */
14717 &UA_TYPES[UA_TYPES_ENUMFIELD], /* .memberType */
14718 0, /* .padding */
14719 true, /* .isArray */
14720 false /* .isOptional */
14721},};
14722
14723/* ReadEventDetails */
14724static UA_DataTypeMember ReadEventDetails_members[4] = {
14725{
14726 UA_TYPENAME("NumValuesPerNode") /* .memberName */
14727 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
14728 0, /* .padding */
14729 false, /* .isArray */
14730 false /* .isOptional */
14731},
14732{
14733 UA_TYPENAME("StartTime") /* .memberName */
14734 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14735 offsetof(UA_ReadEventDetails, startTime) - offsetof(UA_ReadEventDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */
14736 false, /* .isArray */
14737 false /* .isOptional */
14738},
14739{
14740 UA_TYPENAME("EndTime") /* .memberName */
14741 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14742 offsetof(UA_ReadEventDetails, endTime) - offsetof(UA_ReadEventDetails, startTime) - sizeof(UA_DateTime), /* .padding */
14743 false, /* .isArray */
14744 false /* .isOptional */
14745},
14746{
14747 UA_TYPENAME("Filter") /* .memberName */
14748 &UA_TYPES[UA_TYPES_EVENTFILTER], /* .memberType */
14749 offsetof(UA_ReadEventDetails, filter) - offsetof(UA_ReadEventDetails, endTime) - sizeof(UA_DateTime), /* .padding */
14750 false, /* .isArray */
14751 false /* .isOptional */
14752},};
14753
14754/* ReadProcessedDetails */
14755static UA_DataTypeMember ReadProcessedDetails_members[5] = {
14756{
14757 UA_TYPENAME("StartTime") /* .memberName */
14758 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14759 0, /* .padding */
14760 false, /* .isArray */
14761 false /* .isOptional */
14762},
14763{
14764 UA_TYPENAME("EndTime") /* .memberName */
14765 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14766 offsetof(UA_ReadProcessedDetails, endTime) - offsetof(UA_ReadProcessedDetails, startTime) - sizeof(UA_DateTime), /* .padding */
14767 false, /* .isArray */
14768 false /* .isOptional */
14769},
14770{
14771 UA_TYPENAME("ProcessingInterval") /* .memberName */
14772 &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */
14773 offsetof(UA_ReadProcessedDetails, processingInterval) - offsetof(UA_ReadProcessedDetails, endTime) - sizeof(UA_DateTime), /* .padding */
14774 false, /* .isArray */
14775 false /* .isOptional */
14776},
14777{
14778 UA_TYPENAME("AggregateType") /* .memberName */
14779 &UA_TYPES[UA_TYPES_NODEID], /* .memberType */
14780 offsetof(UA_ReadProcessedDetails, aggregateTypeSize) - offsetof(UA_ReadProcessedDetails, processingInterval) - sizeof(UA_Double), /* .padding */
14781 true, /* .isArray */
14782 false /* .isOptional */
14783},
14784{
14785 UA_TYPENAME("AggregateConfiguration") /* .memberName */
14786 &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */
14787 offsetof(UA_ReadProcessedDetails, aggregateConfiguration) - offsetof(UA_ReadProcessedDetails, aggregateType) - sizeof(void *), /* .padding */
14788 false, /* .isArray */
14789 false /* .isOptional */
14790},};
14791
14792/* ModificationInfo */
14793static UA_DataTypeMember ModificationInfo_members[3] = {
14794{
14795 UA_TYPENAME("ModificationTime") /* .memberName */
14796 &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */
14797 0, /* .padding */
14798 false, /* .isArray */
14799 false /* .isOptional */
14800},
14801{
14802 UA_TYPENAME("UpdateType") /* .memberName */
14803 &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], /* .memberType */
14804 offsetof(UA_ModificationInfo, updateType) - offsetof(UA_ModificationInfo, modificationTime) - sizeof(UA_DateTime), /* .padding */
14805 false, /* .isArray */
14806 false /* .isOptional */
14807},
14808{
14809 UA_TYPENAME("UserName") /* .memberName */
14810 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
14811 offsetof(UA_ModificationInfo, userName) - offsetof(UA_ModificationInfo, updateType) - sizeof(UA_HistoryUpdateType), /* .padding */
14812 false, /* .isArray */
14813 false /* .isOptional */
14814},};
14815
14816/* HistoryModifiedData */
14817static UA_DataTypeMember HistoryModifiedData_members[2] = {
14818{
14819 UA_TYPENAME("DataValues") /* .memberName */
14820 &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */
14821 0, /* .padding */
14822 true, /* .isArray */
14823 false /* .isOptional */
14824},
14825{
14826 UA_TYPENAME("ModificationInfos") /* .memberName */
14827 &UA_TYPES[UA_TYPES_MODIFICATIONINFO], /* .memberType */
14828 offsetof(UA_HistoryModifiedData, modificationInfosSize) - offsetof(UA_HistoryModifiedData, dataValues) - sizeof(void *), /* .padding */
14829 true, /* .isArray */
14830 false /* .isOptional */
14831},};
14832
14833/* HistoryEvent */
14834static UA_DataTypeMember HistoryEvent_members[1] = {
14835{
14836 UA_TYPENAME("Events") /* .memberName */
14837 &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], /* .memberType */
14838 0, /* .padding */
14839 true, /* .isArray */
14840 false /* .isOptional */
14841},};
14842
14843/* DataChangeNotification */
14844static UA_DataTypeMember DataChangeNotification_members[2] = {
14845{
14846 UA_TYPENAME("MonitoredItems") /* .memberName */
14847 &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], /* .memberType */
14848 0, /* .padding */
14849 true, /* .isArray */
14850 false /* .isOptional */
14851},
14852{
14853 UA_TYPENAME("DiagnosticInfos") /* .memberName */
14854 &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */
14855 offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void *), /* .padding */
14856 true, /* .isArray */
14857 false /* .isOptional */
14858},};
14859
14860/* EventNotificationList */
14861static UA_DataTypeMember EventNotificationList_members[1] = {
14862{
14863 UA_TYPENAME("Events") /* .memberName */
14864 &UA_TYPES[UA_TYPES_EVENTFIELDLIST], /* .memberType */
14865 0, /* .padding */
14866 true, /* .isArray */
14867 false /* .isOptional */
14868},};
14869const UA_DataType UA_TYPES[UA_TYPES_COUNT] = {
14870/* Boolean */
14871{
14872 UA_TYPENAME("Boolean") /* .typeName */
14873 {.namespaceIndex: 0, .identifierType: UA_NODEIDTYPE_NUMERIC, .identifier: {.numeric: 1LU}}, /* .typeId */
14874 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14875 sizeof(UA_Boolean), /* .memSize */
14876 UA_DATATYPEKIND_BOOLEAN, /* .typeKind */
14877 true, /* .pointerFree */
14878 false, /* .overlayable */
14879 .typeId: 0, /* .membersSize */
14880 Boolean_members /* .members */
14881},
14882/* SByte */
14883{
14884 UA_TYPENAME("SByte") /* .typeName */
14885 {0, UA_NODEIDTYPE_NUMERIC, {2LU}}, /* .typeId */
14886 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14887 sizeof(UA_SByte), /* .memSize */
14888 UA_DATATYPEKIND_SBYTE, /* .typeKind */
14889 true, /* .pointerFree */
14890 true, /* .overlayable */
14891 0, /* .membersSize */
14892 SByte_members /* .members */
14893},
14894/* Byte */
14895{
14896 UA_TYPENAME("Byte") /* .typeName */
14897 {0, UA_NODEIDTYPE_NUMERIC, {3LU}}, /* .typeId */
14898 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14899 sizeof(UA_Byte), /* .memSize */
14900 UA_DATATYPEKIND_BYTE, /* .typeKind */
14901 true, /* .pointerFree */
14902 true, /* .overlayable */
14903 0, /* .membersSize */
14904 Byte_members /* .members */
14905},
14906/* Int16 */
14907{
14908 UA_TYPENAME("Int16") /* .typeName */
14909 {0, UA_NODEIDTYPE_NUMERIC, {4LU}}, /* .typeId */
14910 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14911 sizeof(UA_Int16), /* .memSize */
14912 UA_DATATYPEKIND_INT16, /* .typeKind */
14913 true, /* .pointerFree */
14914 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14915 0, /* .membersSize */
14916 Int16_members /* .members */
14917},
14918/* UInt16 */
14919{
14920 UA_TYPENAME("UInt16") /* .typeName */
14921 {0, UA_NODEIDTYPE_NUMERIC, {5LU}}, /* .typeId */
14922 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14923 sizeof(UA_UInt16), /* .memSize */
14924 UA_DATATYPEKIND_UINT16, /* .typeKind */
14925 true, /* .pointerFree */
14926 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14927 0, /* .membersSize */
14928 UInt16_members /* .members */
14929},
14930/* Int32 */
14931{
14932 UA_TYPENAME("Int32") /* .typeName */
14933 {0, UA_NODEIDTYPE_NUMERIC, {6LU}}, /* .typeId */
14934 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14935 sizeof(UA_Int32), /* .memSize */
14936 UA_DATATYPEKIND_INT32, /* .typeKind */
14937 true, /* .pointerFree */
14938 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14939 0, /* .membersSize */
14940 Int32_members /* .members */
14941},
14942/* UInt32 */
14943{
14944 UA_TYPENAME("UInt32") /* .typeName */
14945 {0, UA_NODEIDTYPE_NUMERIC, {7LU}}, /* .typeId */
14946 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14947 sizeof(UA_UInt32), /* .memSize */
14948 UA_DATATYPEKIND_UINT32, /* .typeKind */
14949 true, /* .pointerFree */
14950 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14951 0, /* .membersSize */
14952 UInt32_members /* .members */
14953},
14954/* Int64 */
14955{
14956 UA_TYPENAME("Int64") /* .typeName */
14957 {0, UA_NODEIDTYPE_NUMERIC, {8LU}}, /* .typeId */
14958 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14959 sizeof(UA_Int64), /* .memSize */
14960 UA_DATATYPEKIND_INT64, /* .typeKind */
14961 true, /* .pointerFree */
14962 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14963 0, /* .membersSize */
14964 Int64_members /* .members */
14965},
14966/* UInt64 */
14967{
14968 UA_TYPENAME("UInt64") /* .typeName */
14969 {0, UA_NODEIDTYPE_NUMERIC, {9LU}}, /* .typeId */
14970 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14971 sizeof(UA_UInt64), /* .memSize */
14972 UA_DATATYPEKIND_UINT64, /* .typeKind */
14973 true, /* .pointerFree */
14974 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
14975 0, /* .membersSize */
14976 UInt64_members /* .members */
14977},
14978/* Float */
14979{
14980 UA_TYPENAME("Float") /* .typeName */
14981 {0, UA_NODEIDTYPE_NUMERIC, {10LU}}, /* .typeId */
14982 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14983 sizeof(UA_Float), /* .memSize */
14984 UA_DATATYPEKIND_FLOAT, /* .typeKind */
14985 true, /* .pointerFree */
14986 UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
14987 0, /* .membersSize */
14988 Float_members /* .members */
14989},
14990/* Double */
14991{
14992 UA_TYPENAME("Double") /* .typeName */
14993 {0, UA_NODEIDTYPE_NUMERIC, {11LU}}, /* .typeId */
14994 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
14995 sizeof(UA_Double), /* .memSize */
14996 UA_DATATYPEKIND_DOUBLE, /* .typeKind */
14997 true, /* .pointerFree */
14998 UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */
14999 0, /* .membersSize */
15000 Double_members /* .members */
15001},
15002/* String */
15003{
15004 UA_TYPENAME("String") /* .typeName */
15005 {0, UA_NODEIDTYPE_NUMERIC, {12LU}}, /* .typeId */
15006 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15007 sizeof(UA_String), /* .memSize */
15008 UA_DATATYPEKIND_STRING, /* .typeKind */
15009 false, /* .pointerFree */
15010 false, /* .overlayable */
15011 0, /* .membersSize */
15012 String_members /* .members */
15013},
15014/* DateTime */
15015{
15016 UA_TYPENAME("DateTime") /* .typeName */
15017 {0, UA_NODEIDTYPE_NUMERIC, {13LU}}, /* .typeId */
15018 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15019 sizeof(UA_DateTime), /* .memSize */
15020 UA_DATATYPEKIND_DATETIME, /* .typeKind */
15021 true, /* .pointerFree */
15022 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15023 0, /* .membersSize */
15024 DateTime_members /* .members */
15025},
15026/* Guid */
15027{
15028 UA_TYPENAME("Guid") /* .typeName */
15029 {0, UA_NODEIDTYPE_NUMERIC, {14LU}}, /* .typeId */
15030 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15031 sizeof(UA_Guid), /* .memSize */
15032 UA_DATATYPEKIND_GUID, /* .typeKind */
15033 true, /* .pointerFree */
15034 (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 */
15035 0, /* .membersSize */
15036 Guid_members /* .members */
15037},
15038/* ByteString */
15039{
15040 UA_TYPENAME("ByteString") /* .typeName */
15041 {0, UA_NODEIDTYPE_NUMERIC, {15LU}}, /* .typeId */
15042 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15043 sizeof(UA_ByteString), /* .memSize */
15044 UA_DATATYPEKIND_BYTESTRING, /* .typeKind */
15045 false, /* .pointerFree */
15046 false, /* .overlayable */
15047 0, /* .membersSize */
15048 ByteString_members /* .members */
15049},
15050/* XmlElement */
15051{
15052 UA_TYPENAME("XmlElement") /* .typeName */
15053 {0, UA_NODEIDTYPE_NUMERIC, {16LU}}, /* .typeId */
15054 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15055 sizeof(UA_XmlElement), /* .memSize */
15056 UA_DATATYPEKIND_XMLELEMENT, /* .typeKind */
15057 false, /* .pointerFree */
15058 false, /* .overlayable */
15059 0, /* .membersSize */
15060 XmlElement_members /* .members */
15061},
15062/* NodeId */
15063{
15064 UA_TYPENAME("NodeId") /* .typeName */
15065 {0, UA_NODEIDTYPE_NUMERIC, {17LU}}, /* .typeId */
15066 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15067 sizeof(UA_NodeId), /* .memSize */
15068 UA_DATATYPEKIND_NODEID, /* .typeKind */
15069 false, /* .pointerFree */
15070 false, /* .overlayable */
15071 0, /* .membersSize */
15072 NodeId_members /* .members */
15073},
15074/* ExpandedNodeId */
15075{
15076 UA_TYPENAME("ExpandedNodeId") /* .typeName */
15077 {0, UA_NODEIDTYPE_NUMERIC, {18LU}}, /* .typeId */
15078 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15079 sizeof(UA_ExpandedNodeId), /* .memSize */
15080 UA_DATATYPEKIND_EXPANDEDNODEID, /* .typeKind */
15081 false, /* .pointerFree */
15082 false, /* .overlayable */
15083 0, /* .membersSize */
15084 ExpandedNodeId_members /* .members */
15085},
15086/* StatusCode */
15087{
15088 UA_TYPENAME("StatusCode") /* .typeName */
15089 {0, UA_NODEIDTYPE_NUMERIC, {19LU}}, /* .typeId */
15090 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15091 sizeof(UA_StatusCode), /* .memSize */
15092 UA_DATATYPEKIND_STATUSCODE, /* .typeKind */
15093 true, /* .pointerFree */
15094 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15095 0, /* .membersSize */
15096 StatusCode_members /* .members */
15097},
15098/* QualifiedName */
15099{
15100 UA_TYPENAME("QualifiedName") /* .typeName */
15101 {0, UA_NODEIDTYPE_NUMERIC, {20LU}}, /* .typeId */
15102 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15103 sizeof(UA_QualifiedName), /* .memSize */
15104 UA_DATATYPEKIND_QUALIFIEDNAME, /* .typeKind */
15105 false, /* .pointerFree */
15106 false, /* .overlayable */
15107 0, /* .membersSize */
15108 QualifiedName_members /* .members */
15109},
15110/* LocalizedText */
15111{
15112 UA_TYPENAME("LocalizedText") /* .typeName */
15113 {0, UA_NODEIDTYPE_NUMERIC, {21LU}}, /* .typeId */
15114 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15115 sizeof(UA_LocalizedText), /* .memSize */
15116 UA_DATATYPEKIND_LOCALIZEDTEXT, /* .typeKind */
15117 false, /* .pointerFree */
15118 false, /* .overlayable */
15119 0, /* .membersSize */
15120 LocalizedText_members /* .members */
15121},
15122/* ExtensionObject */
15123{
15124 UA_TYPENAME("ExtensionObject") /* .typeName */
15125 {0, UA_NODEIDTYPE_NUMERIC, {22LU}}, /* .typeId */
15126 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15127 sizeof(UA_ExtensionObject), /* .memSize */
15128 UA_DATATYPEKIND_EXTENSIONOBJECT, /* .typeKind */
15129 false, /* .pointerFree */
15130 false, /* .overlayable */
15131 0, /* .membersSize */
15132 ExtensionObject_members /* .members */
15133},
15134/* DataValue */
15135{
15136 UA_TYPENAME("DataValue") /* .typeName */
15137 {0, UA_NODEIDTYPE_NUMERIC, {23LU}}, /* .typeId */
15138 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15139 sizeof(UA_DataValue), /* .memSize */
15140 UA_DATATYPEKIND_DATAVALUE, /* .typeKind */
15141 false, /* .pointerFree */
15142 false, /* .overlayable */
15143 0, /* .membersSize */
15144 DataValue_members /* .members */
15145},
15146/* Variant */
15147{
15148 UA_TYPENAME("Variant") /* .typeName */
15149 {0, UA_NODEIDTYPE_NUMERIC, {24LU}}, /* .typeId */
15150 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15151 sizeof(UA_Variant), /* .memSize */
15152 UA_DATATYPEKIND_VARIANT, /* .typeKind */
15153 false, /* .pointerFree */
15154 false, /* .overlayable */
15155 0, /* .membersSize */
15156 Variant_members /* .members */
15157},
15158/* DiagnosticInfo */
15159{
15160 UA_TYPENAME("DiagnosticInfo") /* .typeName */
15161 {0, UA_NODEIDTYPE_NUMERIC, {25LU}}, /* .typeId */
15162 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15163 sizeof(UA_DiagnosticInfo), /* .memSize */
15164 UA_DATATYPEKIND_DIAGNOSTICINFO, /* .typeKind */
15165 false, /* .pointerFree */
15166 false, /* .overlayable */
15167 0, /* .membersSize */
15168 DiagnosticInfo_members /* .members */
15169},
15170/* KeyValuePair */
15171{
15172 UA_TYPENAME("KeyValuePair") /* .typeName */
15173 {0, UA_NODEIDTYPE_NUMERIC, {14533LU}}, /* .typeId */
15174 {0, UA_NODEIDTYPE_NUMERIC, {14846LU}}, /* .binaryEncodingId */
15175 sizeof(UA_KeyValuePair), /* .memSize */
15176 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15177 false, /* .pointerFree */
15178 false, /* .overlayable */
15179 2, /* .membersSize */
15180 KeyValuePair_members /* .members */
15181},
15182/* NodeClass */
15183{
15184 UA_TYPENAME("NodeClass") /* .typeName */
15185 {0, UA_NODEIDTYPE_NUMERIC, {257LU}}, /* .typeId */
15186 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15187 sizeof(UA_NodeClass), /* .memSize */
15188 UA_DATATYPEKIND_ENUM, /* .typeKind */
15189 true, /* .pointerFree */
15190 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15191 0, /* .membersSize */
15192 NodeClass_members /* .members */
15193},
15194/* StructureType */
15195{
15196 UA_TYPENAME("StructureType") /* .typeName */
15197 {0, UA_NODEIDTYPE_NUMERIC, {98LU}}, /* .typeId */
15198 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15199 sizeof(UA_StructureType), /* .memSize */
15200 UA_DATATYPEKIND_ENUM, /* .typeKind */
15201 true, /* .pointerFree */
15202 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15203 0, /* .membersSize */
15204 StructureType_members /* .members */
15205},
15206/* StructureField */
15207{
15208 UA_TYPENAME("StructureField") /* .typeName */
15209 {0, UA_NODEIDTYPE_NUMERIC, {101LU}}, /* .typeId */
15210 {0, UA_NODEIDTYPE_NUMERIC, {14844LU}}, /* .binaryEncodingId */
15211 sizeof(UA_StructureField), /* .memSize */
15212 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15213 false, /* .pointerFree */
15214 false, /* .overlayable */
15215 7, /* .membersSize */
15216 StructureField_members /* .members */
15217},
15218/* StructureDefinition */
15219{
15220 UA_TYPENAME("StructureDefinition") /* .typeName */
15221 {0, UA_NODEIDTYPE_NUMERIC, {99LU}}, /* .typeId */
15222 {0, UA_NODEIDTYPE_NUMERIC, {122LU}}, /* .binaryEncodingId */
15223 sizeof(UA_StructureDefinition), /* .memSize */
15224 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15225 false, /* .pointerFree */
15226 false, /* .overlayable */
15227 4, /* .membersSize */
15228 StructureDefinition_members /* .members */
15229},
15230/* Argument */
15231{
15232 UA_TYPENAME("Argument") /* .typeName */
15233 {0, UA_NODEIDTYPE_NUMERIC, {296LU}}, /* .typeId */
15234 {0, UA_NODEIDTYPE_NUMERIC, {298LU}}, /* .binaryEncodingId */
15235 sizeof(UA_Argument), /* .memSize */
15236 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15237 false, /* .pointerFree */
15238 false, /* .overlayable */
15239 5, /* .membersSize */
15240 Argument_members /* .members */
15241},
15242/* EnumValueType */
15243{
15244 UA_TYPENAME("EnumValueType") /* .typeName */
15245 {0, UA_NODEIDTYPE_NUMERIC, {7594LU}}, /* .typeId */
15246 {0, UA_NODEIDTYPE_NUMERIC, {8251LU}}, /* .binaryEncodingId */
15247 sizeof(UA_EnumValueType), /* .memSize */
15248 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15249 false, /* .pointerFree */
15250 false, /* .overlayable */
15251 3, /* .membersSize */
15252 EnumValueType_members /* .members */
15253},
15254/* EnumField */
15255{
15256 UA_TYPENAME("EnumField") /* .typeName */
15257 {0, UA_NODEIDTYPE_NUMERIC, {102LU}}, /* .typeId */
15258 {0, UA_NODEIDTYPE_NUMERIC, {14845LU}}, /* .binaryEncodingId */
15259 sizeof(UA_EnumField), /* .memSize */
15260 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15261 false, /* .pointerFree */
15262 false, /* .overlayable */
15263 4, /* .membersSize */
15264 EnumField_members /* .members */
15265},
15266/* Duration */
15267{
15268 UA_TYPENAME("Duration") /* .typeName */
15269 {0, UA_NODEIDTYPE_NUMERIC, {290LU}}, /* .typeId */
15270 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15271 sizeof(UA_Duration), /* .memSize */
15272 UA_DATATYPEKIND_DOUBLE, /* .typeKind */
15273 false, /* .pointerFree */
15274 false, /* .overlayable */
15275 0, /* .membersSize */
15276 Duration_members /* .members */
15277},
15278/* UtcTime */
15279{
15280 UA_TYPENAME("UtcTime") /* .typeName */
15281 {0, UA_NODEIDTYPE_NUMERIC, {294LU}}, /* .typeId */
15282 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15283 sizeof(UA_UtcTime), /* .memSize */
15284 UA_DATATYPEKIND_DATETIME, /* .typeKind */
15285 false, /* .pointerFree */
15286 false, /* .overlayable */
15287 0, /* .membersSize */
15288 UtcTime_members /* .members */
15289},
15290/* LocaleId */
15291{
15292 UA_TYPENAME("LocaleId") /* .typeName */
15293 {0, UA_NODEIDTYPE_NUMERIC, {295LU}}, /* .typeId */
15294 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15295 sizeof(UA_LocaleId), /* .memSize */
15296 UA_DATATYPEKIND_STRING, /* .typeKind */
15297 false, /* .pointerFree */
15298 false, /* .overlayable */
15299 0, /* .membersSize */
15300 LocaleId_members /* .members */
15301},
15302/* TimeZoneDataType */
15303{
15304 UA_TYPENAME("TimeZoneDataType") /* .typeName */
15305 {0, UA_NODEIDTYPE_NUMERIC, {8912LU}}, /* .typeId */
15306 {0, UA_NODEIDTYPE_NUMERIC, {8917LU}}, /* .binaryEncodingId */
15307 sizeof(UA_TimeZoneDataType), /* .memSize */
15308 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15309 true, /* .pointerFree */
15310 false, /* .overlayable */
15311 2, /* .membersSize */
15312 TimeZoneDataType_members /* .members */
15313},
15314/* ApplicationType */
15315{
15316 UA_TYPENAME("ApplicationType") /* .typeName */
15317 {0, UA_NODEIDTYPE_NUMERIC, {307LU}}, /* .typeId */
15318 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15319 sizeof(UA_ApplicationType), /* .memSize */
15320 UA_DATATYPEKIND_ENUM, /* .typeKind */
15321 true, /* .pointerFree */
15322 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15323 0, /* .membersSize */
15324 ApplicationType_members /* .members */
15325},
15326/* ApplicationDescription */
15327{
15328 UA_TYPENAME("ApplicationDescription") /* .typeName */
15329 {0, UA_NODEIDTYPE_NUMERIC, {308LU}}, /* .typeId */
15330 {0, UA_NODEIDTYPE_NUMERIC, {310LU}}, /* .binaryEncodingId */
15331 sizeof(UA_ApplicationDescription), /* .memSize */
15332 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15333 false, /* .pointerFree */
15334 false, /* .overlayable */
15335 7, /* .membersSize */
15336 ApplicationDescription_members /* .members */
15337},
15338/* RequestHeader */
15339{
15340 UA_TYPENAME("RequestHeader") /* .typeName */
15341 {0, UA_NODEIDTYPE_NUMERIC, {389LU}}, /* .typeId */
15342 {0, UA_NODEIDTYPE_NUMERIC, {391LU}}, /* .binaryEncodingId */
15343 sizeof(UA_RequestHeader), /* .memSize */
15344 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15345 false, /* .pointerFree */
15346 false, /* .overlayable */
15347 7, /* .membersSize */
15348 RequestHeader_members /* .members */
15349},
15350/* ResponseHeader */
15351{
15352 UA_TYPENAME("ResponseHeader") /* .typeName */
15353 {0, UA_NODEIDTYPE_NUMERIC, {392LU}}, /* .typeId */
15354 {0, UA_NODEIDTYPE_NUMERIC, {394LU}}, /* .binaryEncodingId */
15355 sizeof(UA_ResponseHeader), /* .memSize */
15356 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15357 false, /* .pointerFree */
15358 false, /* .overlayable */
15359 6, /* .membersSize */
15360 ResponseHeader_members /* .members */
15361},
15362/* ServiceFault */
15363{
15364 UA_TYPENAME("ServiceFault") /* .typeName */
15365 {0, UA_NODEIDTYPE_NUMERIC, {395LU}}, /* .typeId */
15366 {0, UA_NODEIDTYPE_NUMERIC, {397LU}}, /* .binaryEncodingId */
15367 sizeof(UA_ServiceFault), /* .memSize */
15368 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15369 false, /* .pointerFree */
15370 false, /* .overlayable */
15371 1, /* .membersSize */
15372 ServiceFault_members /* .members */
15373},
15374/* FindServersRequest */
15375{
15376 UA_TYPENAME("FindServersRequest") /* .typeName */
15377 {0, UA_NODEIDTYPE_NUMERIC, {420LU}}, /* .typeId */
15378 {0, UA_NODEIDTYPE_NUMERIC, {422LU}}, /* .binaryEncodingId */
15379 sizeof(UA_FindServersRequest), /* .memSize */
15380 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15381 false, /* .pointerFree */
15382 false, /* .overlayable */
15383 4, /* .membersSize */
15384 FindServersRequest_members /* .members */
15385},
15386/* FindServersResponse */
15387{
15388 UA_TYPENAME("FindServersResponse") /* .typeName */
15389 {0, UA_NODEIDTYPE_NUMERIC, {423LU}}, /* .typeId */
15390 {0, UA_NODEIDTYPE_NUMERIC, {425LU}}, /* .binaryEncodingId */
15391 sizeof(UA_FindServersResponse), /* .memSize */
15392 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15393 false, /* .pointerFree */
15394 false, /* .overlayable */
15395 2, /* .membersSize */
15396 FindServersResponse_members /* .members */
15397},
15398/* MessageSecurityMode */
15399{
15400 UA_TYPENAME("MessageSecurityMode") /* .typeName */
15401 {0, UA_NODEIDTYPE_NUMERIC, {302LU}}, /* .typeId */
15402 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15403 sizeof(UA_MessageSecurityMode), /* .memSize */
15404 UA_DATATYPEKIND_ENUM, /* .typeKind */
15405 true, /* .pointerFree */
15406 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15407 0, /* .membersSize */
15408 MessageSecurityMode_members /* .members */
15409},
15410/* UserTokenType */
15411{
15412 UA_TYPENAME("UserTokenType") /* .typeName */
15413 {0, UA_NODEIDTYPE_NUMERIC, {303LU}}, /* .typeId */
15414 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15415 sizeof(UA_UserTokenType), /* .memSize */
15416 UA_DATATYPEKIND_ENUM, /* .typeKind */
15417 true, /* .pointerFree */
15418 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15419 0, /* .membersSize */
15420 UserTokenType_members /* .members */
15421},
15422/* UserTokenPolicy */
15423{
15424 UA_TYPENAME("UserTokenPolicy") /* .typeName */
15425 {0, UA_NODEIDTYPE_NUMERIC, {304LU}}, /* .typeId */
15426 {0, UA_NODEIDTYPE_NUMERIC, {306LU}}, /* .binaryEncodingId */
15427 sizeof(UA_UserTokenPolicy), /* .memSize */
15428 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15429 false, /* .pointerFree */
15430 false, /* .overlayable */
15431 5, /* .membersSize */
15432 UserTokenPolicy_members /* .members */
15433},
15434/* EndpointDescription */
15435{
15436 UA_TYPENAME("EndpointDescription") /* .typeName */
15437 {0, UA_NODEIDTYPE_NUMERIC, {312LU}}, /* .typeId */
15438 {0, UA_NODEIDTYPE_NUMERIC, {314LU}}, /* .binaryEncodingId */
15439 sizeof(UA_EndpointDescription), /* .memSize */
15440 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15441 false, /* .pointerFree */
15442 false, /* .overlayable */
15443 8, /* .membersSize */
15444 EndpointDescription_members /* .members */
15445},
15446/* GetEndpointsRequest */
15447{
15448 UA_TYPENAME("GetEndpointsRequest") /* .typeName */
15449 {0, UA_NODEIDTYPE_NUMERIC, {426LU}}, /* .typeId */
15450 {0, UA_NODEIDTYPE_NUMERIC, {428LU}}, /* .binaryEncodingId */
15451 sizeof(UA_GetEndpointsRequest), /* .memSize */
15452 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15453 false, /* .pointerFree */
15454 false, /* .overlayable */
15455 4, /* .membersSize */
15456 GetEndpointsRequest_members /* .members */
15457},
15458/* GetEndpointsResponse */
15459{
15460 UA_TYPENAME("GetEndpointsResponse") /* .typeName */
15461 {0, UA_NODEIDTYPE_NUMERIC, {429LU}}, /* .typeId */
15462 {0, UA_NODEIDTYPE_NUMERIC, {431LU}}, /* .binaryEncodingId */
15463 sizeof(UA_GetEndpointsResponse), /* .memSize */
15464 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15465 false, /* .pointerFree */
15466 false, /* .overlayable */
15467 2, /* .membersSize */
15468 GetEndpointsResponse_members /* .members */
15469},
15470/* SecurityTokenRequestType */
15471{
15472 UA_TYPENAME("SecurityTokenRequestType") /* .typeName */
15473 {0, UA_NODEIDTYPE_NUMERIC, {315LU}}, /* .typeId */
15474 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15475 sizeof(UA_SecurityTokenRequestType), /* .memSize */
15476 UA_DATATYPEKIND_ENUM, /* .typeKind */
15477 true, /* .pointerFree */
15478 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15479 0, /* .membersSize */
15480 SecurityTokenRequestType_members /* .members */
15481},
15482/* ChannelSecurityToken */
15483{
15484 UA_TYPENAME("ChannelSecurityToken") /* .typeName */
15485 {0, UA_NODEIDTYPE_NUMERIC, {441LU}}, /* .typeId */
15486 {0, UA_NODEIDTYPE_NUMERIC, {443LU}}, /* .binaryEncodingId */
15487 sizeof(UA_ChannelSecurityToken), /* .memSize */
15488 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15489 true, /* .pointerFree */
15490 false, /* .overlayable */
15491 4, /* .membersSize */
15492 ChannelSecurityToken_members /* .members */
15493},
15494/* OpenSecureChannelRequest */
15495{
15496 UA_TYPENAME("OpenSecureChannelRequest") /* .typeName */
15497 {0, UA_NODEIDTYPE_NUMERIC, {444LU}}, /* .typeId */
15498 {0, UA_NODEIDTYPE_NUMERIC, {446LU}}, /* .binaryEncodingId */
15499 sizeof(UA_OpenSecureChannelRequest), /* .memSize */
15500 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15501 false, /* .pointerFree */
15502 false, /* .overlayable */
15503 6, /* .membersSize */
15504 OpenSecureChannelRequest_members /* .members */
15505},
15506/* OpenSecureChannelResponse */
15507{
15508 UA_TYPENAME("OpenSecureChannelResponse") /* .typeName */
15509 {0, UA_NODEIDTYPE_NUMERIC, {447LU}}, /* .typeId */
15510 {0, UA_NODEIDTYPE_NUMERIC, {449LU}}, /* .binaryEncodingId */
15511 sizeof(UA_OpenSecureChannelResponse), /* .memSize */
15512 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15513 false, /* .pointerFree */
15514 false, /* .overlayable */
15515 4, /* .membersSize */
15516 OpenSecureChannelResponse_members /* .members */
15517},
15518/* CloseSecureChannelRequest */
15519{
15520 UA_TYPENAME("CloseSecureChannelRequest") /* .typeName */
15521 {0, UA_NODEIDTYPE_NUMERIC, {450LU}}, /* .typeId */
15522 {0, UA_NODEIDTYPE_NUMERIC, {452LU}}, /* .binaryEncodingId */
15523 sizeof(UA_CloseSecureChannelRequest), /* .memSize */
15524 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15525 false, /* .pointerFree */
15526 false, /* .overlayable */
15527 1, /* .membersSize */
15528 CloseSecureChannelRequest_members /* .members */
15529},
15530/* CloseSecureChannelResponse */
15531{
15532 UA_TYPENAME("CloseSecureChannelResponse") /* .typeName */
15533 {0, UA_NODEIDTYPE_NUMERIC, {453LU}}, /* .typeId */
15534 {0, UA_NODEIDTYPE_NUMERIC, {455LU}}, /* .binaryEncodingId */
15535 sizeof(UA_CloseSecureChannelResponse), /* .memSize */
15536 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15537 false, /* .pointerFree */
15538 false, /* .overlayable */
15539 1, /* .membersSize */
15540 CloseSecureChannelResponse_members /* .members */
15541},
15542/* SignedSoftwareCertificate */
15543{
15544 UA_TYPENAME("SignedSoftwareCertificate") /* .typeName */
15545 {0, UA_NODEIDTYPE_NUMERIC, {344LU}}, /* .typeId */
15546 {0, UA_NODEIDTYPE_NUMERIC, {346LU}}, /* .binaryEncodingId */
15547 sizeof(UA_SignedSoftwareCertificate), /* .memSize */
15548 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15549 false, /* .pointerFree */
15550 false, /* .overlayable */
15551 2, /* .membersSize */
15552 SignedSoftwareCertificate_members /* .members */
15553},
15554/* SignatureData */
15555{
15556 UA_TYPENAME("SignatureData") /* .typeName */
15557 {0, UA_NODEIDTYPE_NUMERIC, {456LU}}, /* .typeId */
15558 {0, UA_NODEIDTYPE_NUMERIC, {458LU}}, /* .binaryEncodingId */
15559 sizeof(UA_SignatureData), /* .memSize */
15560 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15561 false, /* .pointerFree */
15562 false, /* .overlayable */
15563 2, /* .membersSize */
15564 SignatureData_members /* .members */
15565},
15566/* CreateSessionRequest */
15567{
15568 UA_TYPENAME("CreateSessionRequest") /* .typeName */
15569 {0, UA_NODEIDTYPE_NUMERIC, {459LU}}, /* .typeId */
15570 {0, UA_NODEIDTYPE_NUMERIC, {461LU}}, /* .binaryEncodingId */
15571 sizeof(UA_CreateSessionRequest), /* .memSize */
15572 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15573 false, /* .pointerFree */
15574 false, /* .overlayable */
15575 9, /* .membersSize */
15576 CreateSessionRequest_members /* .members */
15577},
15578/* CreateSessionResponse */
15579{
15580 UA_TYPENAME("CreateSessionResponse") /* .typeName */
15581 {0, UA_NODEIDTYPE_NUMERIC, {462LU}}, /* .typeId */
15582 {0, UA_NODEIDTYPE_NUMERIC, {464LU}}, /* .binaryEncodingId */
15583 sizeof(UA_CreateSessionResponse), /* .memSize */
15584 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15585 false, /* .pointerFree */
15586 false, /* .overlayable */
15587 10, /* .membersSize */
15588 CreateSessionResponse_members /* .members */
15589},
15590/* UserIdentityToken */
15591{
15592 UA_TYPENAME("UserIdentityToken") /* .typeName */
15593 {0, UA_NODEIDTYPE_NUMERIC, {316LU}}, /* .typeId */
15594 {0, UA_NODEIDTYPE_NUMERIC, {318LU}}, /* .binaryEncodingId */
15595 sizeof(UA_UserIdentityToken), /* .memSize */
15596 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15597 false, /* .pointerFree */
15598 false, /* .overlayable */
15599 1, /* .membersSize */
15600 UserIdentityToken_members /* .members */
15601},
15602/* AnonymousIdentityToken */
15603{
15604 UA_TYPENAME("AnonymousIdentityToken") /* .typeName */
15605 {0, UA_NODEIDTYPE_NUMERIC, {319LU}}, /* .typeId */
15606 {0, UA_NODEIDTYPE_NUMERIC, {321LU}}, /* .binaryEncodingId */
15607 sizeof(UA_AnonymousIdentityToken), /* .memSize */
15608 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15609 false, /* .pointerFree */
15610 false, /* .overlayable */
15611 1, /* .membersSize */
15612 AnonymousIdentityToken_members /* .members */
15613},
15614/* UserNameIdentityToken */
15615{
15616 UA_TYPENAME("UserNameIdentityToken") /* .typeName */
15617 {0, UA_NODEIDTYPE_NUMERIC, {322LU}}, /* .typeId */
15618 {0, UA_NODEIDTYPE_NUMERIC, {324LU}}, /* .binaryEncodingId */
15619 sizeof(UA_UserNameIdentityToken), /* .memSize */
15620 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15621 false, /* .pointerFree */
15622 false, /* .overlayable */
15623 4, /* .membersSize */
15624 UserNameIdentityToken_members /* .members */
15625},
15626/* X509IdentityToken */
15627{
15628 UA_TYPENAME("X509IdentityToken") /* .typeName */
15629 {0, UA_NODEIDTYPE_NUMERIC, {325LU}}, /* .typeId */
15630 {0, UA_NODEIDTYPE_NUMERIC, {327LU}}, /* .binaryEncodingId */
15631 sizeof(UA_X509IdentityToken), /* .memSize */
15632 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15633 false, /* .pointerFree */
15634 false, /* .overlayable */
15635 2, /* .membersSize */
15636 X509IdentityToken_members /* .members */
15637},
15638/* IssuedIdentityToken */
15639{
15640 UA_TYPENAME("IssuedIdentityToken") /* .typeName */
15641 {0, UA_NODEIDTYPE_NUMERIC, {938LU}}, /* .typeId */
15642 {0, UA_NODEIDTYPE_NUMERIC, {940LU}}, /* .binaryEncodingId */
15643 sizeof(UA_IssuedIdentityToken), /* .memSize */
15644 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15645 false, /* .pointerFree */
15646 false, /* .overlayable */
15647 3, /* .membersSize */
15648 IssuedIdentityToken_members /* .members */
15649},
15650/* ActivateSessionRequest */
15651{
15652 UA_TYPENAME("ActivateSessionRequest") /* .typeName */
15653 {0, UA_NODEIDTYPE_NUMERIC, {465LU}}, /* .typeId */
15654 {0, UA_NODEIDTYPE_NUMERIC, {467LU}}, /* .binaryEncodingId */
15655 sizeof(UA_ActivateSessionRequest), /* .memSize */
15656 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15657 false, /* .pointerFree */
15658 false, /* .overlayable */
15659 6, /* .membersSize */
15660 ActivateSessionRequest_members /* .members */
15661},
15662/* ActivateSessionResponse */
15663{
15664 UA_TYPENAME("ActivateSessionResponse") /* .typeName */
15665 {0, UA_NODEIDTYPE_NUMERIC, {468LU}}, /* .typeId */
15666 {0, UA_NODEIDTYPE_NUMERIC, {470LU}}, /* .binaryEncodingId */
15667 sizeof(UA_ActivateSessionResponse), /* .memSize */
15668 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15669 false, /* .pointerFree */
15670 false, /* .overlayable */
15671 4, /* .membersSize */
15672 ActivateSessionResponse_members /* .members */
15673},
15674/* CloseSessionRequest */
15675{
15676 UA_TYPENAME("CloseSessionRequest") /* .typeName */
15677 {0, UA_NODEIDTYPE_NUMERIC, {471LU}}, /* .typeId */
15678 {0, UA_NODEIDTYPE_NUMERIC, {473LU}}, /* .binaryEncodingId */
15679 sizeof(UA_CloseSessionRequest), /* .memSize */
15680 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15681 false, /* .pointerFree */
15682 false, /* .overlayable */
15683 2, /* .membersSize */
15684 CloseSessionRequest_members /* .members */
15685},
15686/* CloseSessionResponse */
15687{
15688 UA_TYPENAME("CloseSessionResponse") /* .typeName */
15689 {0, UA_NODEIDTYPE_NUMERIC, {474LU}}, /* .typeId */
15690 {0, UA_NODEIDTYPE_NUMERIC, {476LU}}, /* .binaryEncodingId */
15691 sizeof(UA_CloseSessionResponse), /* .memSize */
15692 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15693 false, /* .pointerFree */
15694 false, /* .overlayable */
15695 1, /* .membersSize */
15696 CloseSessionResponse_members /* .members */
15697},
15698/* NodeAttributesMask */
15699{
15700 UA_TYPENAME("NodeAttributesMask") /* .typeName */
15701 {0, UA_NODEIDTYPE_NUMERIC, {348LU}}, /* .typeId */
15702 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15703 sizeof(UA_NodeAttributesMask), /* .memSize */
15704 UA_DATATYPEKIND_ENUM, /* .typeKind */
15705 true, /* .pointerFree */
15706 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15707 0, /* .membersSize */
15708 NodeAttributesMask_members /* .members */
15709},
15710/* NodeAttributes */
15711{
15712 UA_TYPENAME("NodeAttributes") /* .typeName */
15713 {0, UA_NODEIDTYPE_NUMERIC, {349LU}}, /* .typeId */
15714 {0, UA_NODEIDTYPE_NUMERIC, {351LU}}, /* .binaryEncodingId */
15715 sizeof(UA_NodeAttributes), /* .memSize */
15716 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15717 false, /* .pointerFree */
15718 false, /* .overlayable */
15719 5, /* .membersSize */
15720 NodeAttributes_members /* .members */
15721},
15722/* ObjectAttributes */
15723{
15724 UA_TYPENAME("ObjectAttributes") /* .typeName */
15725 {0, UA_NODEIDTYPE_NUMERIC, {352LU}}, /* .typeId */
15726 {0, UA_NODEIDTYPE_NUMERIC, {354LU}}, /* .binaryEncodingId */
15727 sizeof(UA_ObjectAttributes), /* .memSize */
15728 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15729 false, /* .pointerFree */
15730 false, /* .overlayable */
15731 6, /* .membersSize */
15732 ObjectAttributes_members /* .members */
15733},
15734/* VariableAttributes */
15735{
15736 UA_TYPENAME("VariableAttributes") /* .typeName */
15737 {0, UA_NODEIDTYPE_NUMERIC, {355LU}}, /* .typeId */
15738 {0, UA_NODEIDTYPE_NUMERIC, {357LU}}, /* .binaryEncodingId */
15739 sizeof(UA_VariableAttributes), /* .memSize */
15740 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15741 false, /* .pointerFree */
15742 false, /* .overlayable */
15743 13, /* .membersSize */
15744 VariableAttributes_members /* .members */
15745},
15746/* MethodAttributes */
15747{
15748 UA_TYPENAME("MethodAttributes") /* .typeName */
15749 {0, UA_NODEIDTYPE_NUMERIC, {358LU}}, /* .typeId */
15750 {0, UA_NODEIDTYPE_NUMERIC, {360LU}}, /* .binaryEncodingId */
15751 sizeof(UA_MethodAttributes), /* .memSize */
15752 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15753 false, /* .pointerFree */
15754 false, /* .overlayable */
15755 7, /* .membersSize */
15756 MethodAttributes_members /* .members */
15757},
15758/* ObjectTypeAttributes */
15759{
15760 UA_TYPENAME("ObjectTypeAttributes") /* .typeName */
15761 {0, UA_NODEIDTYPE_NUMERIC, {361LU}}, /* .typeId */
15762 {0, UA_NODEIDTYPE_NUMERIC, {363LU}}, /* .binaryEncodingId */
15763 sizeof(UA_ObjectTypeAttributes), /* .memSize */
15764 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15765 false, /* .pointerFree */
15766 false, /* .overlayable */
15767 6, /* .membersSize */
15768 ObjectTypeAttributes_members /* .members */
15769},
15770/* VariableTypeAttributes */
15771{
15772 UA_TYPENAME("VariableTypeAttributes") /* .typeName */
15773 {0, UA_NODEIDTYPE_NUMERIC, {364LU}}, /* .typeId */
15774 {0, UA_NODEIDTYPE_NUMERIC, {366LU}}, /* .binaryEncodingId */
15775 sizeof(UA_VariableTypeAttributes), /* .memSize */
15776 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15777 false, /* .pointerFree */
15778 false, /* .overlayable */
15779 10, /* .membersSize */
15780 VariableTypeAttributes_members /* .members */
15781},
15782/* ReferenceTypeAttributes */
15783{
15784 UA_TYPENAME("ReferenceTypeAttributes") /* .typeName */
15785 {0, UA_NODEIDTYPE_NUMERIC, {367LU}}, /* .typeId */
15786 {0, UA_NODEIDTYPE_NUMERIC, {369LU}}, /* .binaryEncodingId */
15787 sizeof(UA_ReferenceTypeAttributes), /* .memSize */
15788 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15789 false, /* .pointerFree */
15790 false, /* .overlayable */
15791 8, /* .membersSize */
15792 ReferenceTypeAttributes_members /* .members */
15793},
15794/* DataTypeAttributes */
15795{
15796 UA_TYPENAME("DataTypeAttributes") /* .typeName */
15797 {0, UA_NODEIDTYPE_NUMERIC, {370LU}}, /* .typeId */
15798 {0, UA_NODEIDTYPE_NUMERIC, {372LU}}, /* .binaryEncodingId */
15799 sizeof(UA_DataTypeAttributes), /* .memSize */
15800 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15801 false, /* .pointerFree */
15802 false, /* .overlayable */
15803 6, /* .membersSize */
15804 DataTypeAttributes_members /* .members */
15805},
15806/* ViewAttributes */
15807{
15808 UA_TYPENAME("ViewAttributes") /* .typeName */
15809 {0, UA_NODEIDTYPE_NUMERIC, {373LU}}, /* .typeId */
15810 {0, UA_NODEIDTYPE_NUMERIC, {375LU}}, /* .binaryEncodingId */
15811 sizeof(UA_ViewAttributes), /* .memSize */
15812 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15813 false, /* .pointerFree */
15814 false, /* .overlayable */
15815 7, /* .membersSize */
15816 ViewAttributes_members /* .members */
15817},
15818/* AddNodesItem */
15819{
15820 UA_TYPENAME("AddNodesItem") /* .typeName */
15821 {0, UA_NODEIDTYPE_NUMERIC, {376LU}}, /* .typeId */
15822 {0, UA_NODEIDTYPE_NUMERIC, {378LU}}, /* .binaryEncodingId */
15823 sizeof(UA_AddNodesItem), /* .memSize */
15824 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15825 false, /* .pointerFree */
15826 false, /* .overlayable */
15827 7, /* .membersSize */
15828 AddNodesItem_members /* .members */
15829},
15830/* AddNodesResult */
15831{
15832 UA_TYPENAME("AddNodesResult") /* .typeName */
15833 {0, UA_NODEIDTYPE_NUMERIC, {483LU}}, /* .typeId */
15834 {0, UA_NODEIDTYPE_NUMERIC, {485LU}}, /* .binaryEncodingId */
15835 sizeof(UA_AddNodesResult), /* .memSize */
15836 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15837 false, /* .pointerFree */
15838 false, /* .overlayable */
15839 2, /* .membersSize */
15840 AddNodesResult_members /* .members */
15841},
15842/* AddNodesRequest */
15843{
15844 UA_TYPENAME("AddNodesRequest") /* .typeName */
15845 {0, UA_NODEIDTYPE_NUMERIC, {486LU}}, /* .typeId */
15846 {0, UA_NODEIDTYPE_NUMERIC, {488LU}}, /* .binaryEncodingId */
15847 sizeof(UA_AddNodesRequest), /* .memSize */
15848 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15849 false, /* .pointerFree */
15850 false, /* .overlayable */
15851 2, /* .membersSize */
15852 AddNodesRequest_members /* .members */
15853},
15854/* AddNodesResponse */
15855{
15856 UA_TYPENAME("AddNodesResponse") /* .typeName */
15857 {0, UA_NODEIDTYPE_NUMERIC, {489LU}}, /* .typeId */
15858 {0, UA_NODEIDTYPE_NUMERIC, {491LU}}, /* .binaryEncodingId */
15859 sizeof(UA_AddNodesResponse), /* .memSize */
15860 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15861 false, /* .pointerFree */
15862 false, /* .overlayable */
15863 3, /* .membersSize */
15864 AddNodesResponse_members /* .members */
15865},
15866/* AddReferencesItem */
15867{
15868 UA_TYPENAME("AddReferencesItem") /* .typeName */
15869 {0, UA_NODEIDTYPE_NUMERIC, {379LU}}, /* .typeId */
15870 {0, UA_NODEIDTYPE_NUMERIC, {381LU}}, /* .binaryEncodingId */
15871 sizeof(UA_AddReferencesItem), /* .memSize */
15872 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15873 false, /* .pointerFree */
15874 false, /* .overlayable */
15875 6, /* .membersSize */
15876 AddReferencesItem_members /* .members */
15877},
15878/* AddReferencesRequest */
15879{
15880 UA_TYPENAME("AddReferencesRequest") /* .typeName */
15881 {0, UA_NODEIDTYPE_NUMERIC, {492LU}}, /* .typeId */
15882 {0, UA_NODEIDTYPE_NUMERIC, {494LU}}, /* .binaryEncodingId */
15883 sizeof(UA_AddReferencesRequest), /* .memSize */
15884 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15885 false, /* .pointerFree */
15886 false, /* .overlayable */
15887 2, /* .membersSize */
15888 AddReferencesRequest_members /* .members */
15889},
15890/* AddReferencesResponse */
15891{
15892 UA_TYPENAME("AddReferencesResponse") /* .typeName */
15893 {0, UA_NODEIDTYPE_NUMERIC, {495LU}}, /* .typeId */
15894 {0, UA_NODEIDTYPE_NUMERIC, {497LU}}, /* .binaryEncodingId */
15895 sizeof(UA_AddReferencesResponse), /* .memSize */
15896 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15897 false, /* .pointerFree */
15898 false, /* .overlayable */
15899 3, /* .membersSize */
15900 AddReferencesResponse_members /* .members */
15901},
15902/* DeleteNodesItem */
15903{
15904 UA_TYPENAME("DeleteNodesItem") /* .typeName */
15905 {0, UA_NODEIDTYPE_NUMERIC, {382LU}}, /* .typeId */
15906 {0, UA_NODEIDTYPE_NUMERIC, {384LU}}, /* .binaryEncodingId */
15907 sizeof(UA_DeleteNodesItem), /* .memSize */
15908 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15909 false, /* .pointerFree */
15910 false, /* .overlayable */
15911 2, /* .membersSize */
15912 DeleteNodesItem_members /* .members */
15913},
15914/* DeleteNodesRequest */
15915{
15916 UA_TYPENAME("DeleteNodesRequest") /* .typeName */
15917 {0, UA_NODEIDTYPE_NUMERIC, {498LU}}, /* .typeId */
15918 {0, UA_NODEIDTYPE_NUMERIC, {500LU}}, /* .binaryEncodingId */
15919 sizeof(UA_DeleteNodesRequest), /* .memSize */
15920 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15921 false, /* .pointerFree */
15922 false, /* .overlayable */
15923 2, /* .membersSize */
15924 DeleteNodesRequest_members /* .members */
15925},
15926/* DeleteNodesResponse */
15927{
15928 UA_TYPENAME("DeleteNodesResponse") /* .typeName */
15929 {0, UA_NODEIDTYPE_NUMERIC, {501LU}}, /* .typeId */
15930 {0, UA_NODEIDTYPE_NUMERIC, {503LU}}, /* .binaryEncodingId */
15931 sizeof(UA_DeleteNodesResponse), /* .memSize */
15932 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15933 false, /* .pointerFree */
15934 false, /* .overlayable */
15935 3, /* .membersSize */
15936 DeleteNodesResponse_members /* .members */
15937},
15938/* DeleteReferencesItem */
15939{
15940 UA_TYPENAME("DeleteReferencesItem") /* .typeName */
15941 {0, UA_NODEIDTYPE_NUMERIC, {385LU}}, /* .typeId */
15942 {0, UA_NODEIDTYPE_NUMERIC, {387LU}}, /* .binaryEncodingId */
15943 sizeof(UA_DeleteReferencesItem), /* .memSize */
15944 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15945 false, /* .pointerFree */
15946 false, /* .overlayable */
15947 5, /* .membersSize */
15948 DeleteReferencesItem_members /* .members */
15949},
15950/* DeleteReferencesRequest */
15951{
15952 UA_TYPENAME("DeleteReferencesRequest") /* .typeName */
15953 {0, UA_NODEIDTYPE_NUMERIC, {504LU}}, /* .typeId */
15954 {0, UA_NODEIDTYPE_NUMERIC, {506LU}}, /* .binaryEncodingId */
15955 sizeof(UA_DeleteReferencesRequest), /* .memSize */
15956 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15957 false, /* .pointerFree */
15958 false, /* .overlayable */
15959 2, /* .membersSize */
15960 DeleteReferencesRequest_members /* .members */
15961},
15962/* DeleteReferencesResponse */
15963{
15964 UA_TYPENAME("DeleteReferencesResponse") /* .typeName */
15965 {0, UA_NODEIDTYPE_NUMERIC, {507LU}}, /* .typeId */
15966 {0, UA_NODEIDTYPE_NUMERIC, {509LU}}, /* .binaryEncodingId */
15967 sizeof(UA_DeleteReferencesResponse), /* .memSize */
15968 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15969 false, /* .pointerFree */
15970 false, /* .overlayable */
15971 3, /* .membersSize */
15972 DeleteReferencesResponse_members /* .members */
15973},
15974/* BrowseDirection */
15975{
15976 UA_TYPENAME("BrowseDirection") /* .typeName */
15977 {0, UA_NODEIDTYPE_NUMERIC, {510LU}}, /* .typeId */
15978 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
15979 sizeof(UA_BrowseDirection), /* .memSize */
15980 UA_DATATYPEKIND_ENUM, /* .typeKind */
15981 true, /* .pointerFree */
15982 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
15983 0, /* .membersSize */
15984 BrowseDirection_members /* .members */
15985},
15986/* ViewDescription */
15987{
15988 UA_TYPENAME("ViewDescription") /* .typeName */
15989 {0, UA_NODEIDTYPE_NUMERIC, {511LU}}, /* .typeId */
15990 {0, UA_NODEIDTYPE_NUMERIC, {513LU}}, /* .binaryEncodingId */
15991 sizeof(UA_ViewDescription), /* .memSize */
15992 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
15993 false, /* .pointerFree */
15994 false, /* .overlayable */
15995 3, /* .membersSize */
15996 ViewDescription_members /* .members */
15997},
15998/* BrowseDescription */
15999{
16000 UA_TYPENAME("BrowseDescription") /* .typeName */
16001 {0, UA_NODEIDTYPE_NUMERIC, {514LU}}, /* .typeId */
16002 {0, UA_NODEIDTYPE_NUMERIC, {516LU}}, /* .binaryEncodingId */
16003 sizeof(UA_BrowseDescription), /* .memSize */
16004 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16005 false, /* .pointerFree */
16006 false, /* .overlayable */
16007 6, /* .membersSize */
16008 BrowseDescription_members /* .members */
16009},
16010/* BrowseResultMask */
16011{
16012 UA_TYPENAME("BrowseResultMask") /* .typeName */
16013 {0, UA_NODEIDTYPE_NUMERIC, {517LU}}, /* .typeId */
16014 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16015 sizeof(UA_BrowseResultMask), /* .memSize */
16016 UA_DATATYPEKIND_ENUM, /* .typeKind */
16017 true, /* .pointerFree */
16018 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16019 0, /* .membersSize */
16020 BrowseResultMask_members /* .members */
16021},
16022/* ReferenceDescription */
16023{
16024 UA_TYPENAME("ReferenceDescription") /* .typeName */
16025 {0, UA_NODEIDTYPE_NUMERIC, {518LU}}, /* .typeId */
16026 {0, UA_NODEIDTYPE_NUMERIC, {520LU}}, /* .binaryEncodingId */
16027 sizeof(UA_ReferenceDescription), /* .memSize */
16028 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16029 false, /* .pointerFree */
16030 false, /* .overlayable */
16031 7, /* .membersSize */
16032 ReferenceDescription_members /* .members */
16033},
16034/* BrowseResult */
16035{
16036 UA_TYPENAME("BrowseResult") /* .typeName */
16037 {0, UA_NODEIDTYPE_NUMERIC, {522LU}}, /* .typeId */
16038 {0, UA_NODEIDTYPE_NUMERIC, {524LU}}, /* .binaryEncodingId */
16039 sizeof(UA_BrowseResult), /* .memSize */
16040 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16041 false, /* .pointerFree */
16042 false, /* .overlayable */
16043 3, /* .membersSize */
16044 BrowseResult_members /* .members */
16045},
16046/* BrowseRequest */
16047{
16048 UA_TYPENAME("BrowseRequest") /* .typeName */
16049 {0, UA_NODEIDTYPE_NUMERIC, {525LU}}, /* .typeId */
16050 {0, UA_NODEIDTYPE_NUMERIC, {527LU}}, /* .binaryEncodingId */
16051 sizeof(UA_BrowseRequest), /* .memSize */
16052 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16053 false, /* .pointerFree */
16054 false, /* .overlayable */
16055 4, /* .membersSize */
16056 BrowseRequest_members /* .members */
16057},
16058/* BrowseResponse */
16059{
16060 UA_TYPENAME("BrowseResponse") /* .typeName */
16061 {0, UA_NODEIDTYPE_NUMERIC, {528LU}}, /* .typeId */
16062 {0, UA_NODEIDTYPE_NUMERIC, {530LU}}, /* .binaryEncodingId */
16063 sizeof(UA_BrowseResponse), /* .memSize */
16064 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16065 false, /* .pointerFree */
16066 false, /* .overlayable */
16067 3, /* .membersSize */
16068 BrowseResponse_members /* .members */
16069},
16070/* BrowseNextRequest */
16071{
16072 UA_TYPENAME("BrowseNextRequest") /* .typeName */
16073 {0, UA_NODEIDTYPE_NUMERIC, {531LU}}, /* .typeId */
16074 {0, UA_NODEIDTYPE_NUMERIC, {533LU}}, /* .binaryEncodingId */
16075 sizeof(UA_BrowseNextRequest), /* .memSize */
16076 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16077 false, /* .pointerFree */
16078 false, /* .overlayable */
16079 3, /* .membersSize */
16080 BrowseNextRequest_members /* .members */
16081},
16082/* BrowseNextResponse */
16083{
16084 UA_TYPENAME("BrowseNextResponse") /* .typeName */
16085 {0, UA_NODEIDTYPE_NUMERIC, {534LU}}, /* .typeId */
16086 {0, UA_NODEIDTYPE_NUMERIC, {536LU}}, /* .binaryEncodingId */
16087 sizeof(UA_BrowseNextResponse), /* .memSize */
16088 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16089 false, /* .pointerFree */
16090 false, /* .overlayable */
16091 3, /* .membersSize */
16092 BrowseNextResponse_members /* .members */
16093},
16094/* RelativePathElement */
16095{
16096 UA_TYPENAME("RelativePathElement") /* .typeName */
16097 {0, UA_NODEIDTYPE_NUMERIC, {537LU}}, /* .typeId */
16098 {0, UA_NODEIDTYPE_NUMERIC, {539LU}}, /* .binaryEncodingId */
16099 sizeof(UA_RelativePathElement), /* .memSize */
16100 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16101 false, /* .pointerFree */
16102 false, /* .overlayable */
16103 4, /* .membersSize */
16104 RelativePathElement_members /* .members */
16105},
16106/* RelativePath */
16107{
16108 UA_TYPENAME("RelativePath") /* .typeName */
16109 {0, UA_NODEIDTYPE_NUMERIC, {540LU}}, /* .typeId */
16110 {0, UA_NODEIDTYPE_NUMERIC, {542LU}}, /* .binaryEncodingId */
16111 sizeof(UA_RelativePath), /* .memSize */
16112 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16113 false, /* .pointerFree */
16114 false, /* .overlayable */
16115 1, /* .membersSize */
16116 RelativePath_members /* .members */
16117},
16118/* BrowsePath */
16119{
16120 UA_TYPENAME("BrowsePath") /* .typeName */
16121 {0, UA_NODEIDTYPE_NUMERIC, {543LU}}, /* .typeId */
16122 {0, UA_NODEIDTYPE_NUMERIC, {545LU}}, /* .binaryEncodingId */
16123 sizeof(UA_BrowsePath), /* .memSize */
16124 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16125 false, /* .pointerFree */
16126 false, /* .overlayable */
16127 2, /* .membersSize */
16128 BrowsePath_members /* .members */
16129},
16130/* BrowsePathTarget */
16131{
16132 UA_TYPENAME("BrowsePathTarget") /* .typeName */
16133 {0, UA_NODEIDTYPE_NUMERIC, {546LU}}, /* .typeId */
16134 {0, UA_NODEIDTYPE_NUMERIC, {548LU}}, /* .binaryEncodingId */
16135 sizeof(UA_BrowsePathTarget), /* .memSize */
16136 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16137 false, /* .pointerFree */
16138 false, /* .overlayable */
16139 2, /* .membersSize */
16140 BrowsePathTarget_members /* .members */
16141},
16142/* BrowsePathResult */
16143{
16144 UA_TYPENAME("BrowsePathResult") /* .typeName */
16145 {0, UA_NODEIDTYPE_NUMERIC, {549LU}}, /* .typeId */
16146 {0, UA_NODEIDTYPE_NUMERIC, {551LU}}, /* .binaryEncodingId */
16147 sizeof(UA_BrowsePathResult), /* .memSize */
16148 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16149 false, /* .pointerFree */
16150 false, /* .overlayable */
16151 2, /* .membersSize */
16152 BrowsePathResult_members /* .members */
16153},
16154/* TranslateBrowsePathsToNodeIdsRequest */
16155{
16156 UA_TYPENAME("TranslateBrowsePathsToNodeIdsRequest") /* .typeName */
16157 {0, UA_NODEIDTYPE_NUMERIC, {552LU}}, /* .typeId */
16158 {0, UA_NODEIDTYPE_NUMERIC, {554LU}}, /* .binaryEncodingId */
16159 sizeof(UA_TranslateBrowsePathsToNodeIdsRequest), /* .memSize */
16160 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16161 false, /* .pointerFree */
16162 false, /* .overlayable */
16163 2, /* .membersSize */
16164 TranslateBrowsePathsToNodeIdsRequest_members /* .members */
16165},
16166/* TranslateBrowsePathsToNodeIdsResponse */
16167{
16168 UA_TYPENAME("TranslateBrowsePathsToNodeIdsResponse") /* .typeName */
16169 {0, UA_NODEIDTYPE_NUMERIC, {555LU}}, /* .typeId */
16170 {0, UA_NODEIDTYPE_NUMERIC, {557LU}}, /* .binaryEncodingId */
16171 sizeof(UA_TranslateBrowsePathsToNodeIdsResponse), /* .memSize */
16172 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16173 false, /* .pointerFree */
16174 false, /* .overlayable */
16175 3, /* .membersSize */
16176 TranslateBrowsePathsToNodeIdsResponse_members /* .members */
16177},
16178/* RegisterNodesRequest */
16179{
16180 UA_TYPENAME("RegisterNodesRequest") /* .typeName */
16181 {0, UA_NODEIDTYPE_NUMERIC, {558LU}}, /* .typeId */
16182 {0, UA_NODEIDTYPE_NUMERIC, {560LU}}, /* .binaryEncodingId */
16183 sizeof(UA_RegisterNodesRequest), /* .memSize */
16184 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16185 false, /* .pointerFree */
16186 false, /* .overlayable */
16187 2, /* .membersSize */
16188 RegisterNodesRequest_members /* .members */
16189},
16190/* RegisterNodesResponse */
16191{
16192 UA_TYPENAME("RegisterNodesResponse") /* .typeName */
16193 {0, UA_NODEIDTYPE_NUMERIC, {561LU}}, /* .typeId */
16194 {0, UA_NODEIDTYPE_NUMERIC, {563LU}}, /* .binaryEncodingId */
16195 sizeof(UA_RegisterNodesResponse), /* .memSize */
16196 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16197 false, /* .pointerFree */
16198 false, /* .overlayable */
16199 2, /* .membersSize */
16200 RegisterNodesResponse_members /* .members */
16201},
16202/* UnregisterNodesRequest */
16203{
16204 UA_TYPENAME("UnregisterNodesRequest") /* .typeName */
16205 {0, UA_NODEIDTYPE_NUMERIC, {564LU}}, /* .typeId */
16206 {0, UA_NODEIDTYPE_NUMERIC, {566LU}}, /* .binaryEncodingId */
16207 sizeof(UA_UnregisterNodesRequest), /* .memSize */
16208 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16209 false, /* .pointerFree */
16210 false, /* .overlayable */
16211 2, /* .membersSize */
16212 UnregisterNodesRequest_members /* .members */
16213},
16214/* UnregisterNodesResponse */
16215{
16216 UA_TYPENAME("UnregisterNodesResponse") /* .typeName */
16217 {0, UA_NODEIDTYPE_NUMERIC, {567LU}}, /* .typeId */
16218 {0, UA_NODEIDTYPE_NUMERIC, {569LU}}, /* .binaryEncodingId */
16219 sizeof(UA_UnregisterNodesResponse), /* .memSize */
16220 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16221 false, /* .pointerFree */
16222 false, /* .overlayable */
16223 1, /* .membersSize */
16224 UnregisterNodesResponse_members /* .members */
16225},
16226/* FilterOperator */
16227{
16228 UA_TYPENAME("FilterOperator") /* .typeName */
16229 {0, UA_NODEIDTYPE_NUMERIC, {576LU}}, /* .typeId */
16230 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16231 sizeof(UA_FilterOperator), /* .memSize */
16232 UA_DATATYPEKIND_ENUM, /* .typeKind */
16233 true, /* .pointerFree */
16234 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16235 0, /* .membersSize */
16236 FilterOperator_members /* .members */
16237},
16238/* ContentFilterElement */
16239{
16240 UA_TYPENAME("ContentFilterElement") /* .typeName */
16241 {0, UA_NODEIDTYPE_NUMERIC, {583LU}}, /* .typeId */
16242 {0, UA_NODEIDTYPE_NUMERIC, {585LU}}, /* .binaryEncodingId */
16243 sizeof(UA_ContentFilterElement), /* .memSize */
16244 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16245 false, /* .pointerFree */
16246 false, /* .overlayable */
16247 2, /* .membersSize */
16248 ContentFilterElement_members /* .members */
16249},
16250/* ContentFilter */
16251{
16252 UA_TYPENAME("ContentFilter") /* .typeName */
16253 {0, UA_NODEIDTYPE_NUMERIC, {586LU}}, /* .typeId */
16254 {0, UA_NODEIDTYPE_NUMERIC, {588LU}}, /* .binaryEncodingId */
16255 sizeof(UA_ContentFilter), /* .memSize */
16256 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16257 false, /* .pointerFree */
16258 false, /* .overlayable */
16259 1, /* .membersSize */
16260 ContentFilter_members /* .members */
16261},
16262/* ElementOperand */
16263{
16264 UA_TYPENAME("ElementOperand") /* .typeName */
16265 {0, UA_NODEIDTYPE_NUMERIC, {592LU}}, /* .typeId */
16266 {0, UA_NODEIDTYPE_NUMERIC, {594LU}}, /* .binaryEncodingId */
16267 sizeof(UA_ElementOperand), /* .memSize */
16268 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16269 true, /* .pointerFree */
16270 false, /* .overlayable */
16271 1, /* .membersSize */
16272 ElementOperand_members /* .members */
16273},
16274/* LiteralOperand */
16275{
16276 UA_TYPENAME("LiteralOperand") /* .typeName */
16277 {0, UA_NODEIDTYPE_NUMERIC, {595LU}}, /* .typeId */
16278 {0, UA_NODEIDTYPE_NUMERIC, {597LU}}, /* .binaryEncodingId */
16279 sizeof(UA_LiteralOperand), /* .memSize */
16280 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16281 false, /* .pointerFree */
16282 false, /* .overlayable */
16283 1, /* .membersSize */
16284 LiteralOperand_members /* .members */
16285},
16286/* AttributeOperand */
16287{
16288 UA_TYPENAME("AttributeOperand") /* .typeName */
16289 {0, UA_NODEIDTYPE_NUMERIC, {598LU}}, /* .typeId */
16290 {0, UA_NODEIDTYPE_NUMERIC, {600LU}}, /* .binaryEncodingId */
16291 sizeof(UA_AttributeOperand), /* .memSize */
16292 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16293 false, /* .pointerFree */
16294 false, /* .overlayable */
16295 5, /* .membersSize */
16296 AttributeOperand_members /* .members */
16297},
16298/* SimpleAttributeOperand */
16299{
16300 UA_TYPENAME("SimpleAttributeOperand") /* .typeName */
16301 {0, UA_NODEIDTYPE_NUMERIC, {601LU}}, /* .typeId */
16302 {0, UA_NODEIDTYPE_NUMERIC, {603LU}}, /* .binaryEncodingId */
16303 sizeof(UA_SimpleAttributeOperand), /* .memSize */
16304 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16305 false, /* .pointerFree */
16306 false, /* .overlayable */
16307 4, /* .membersSize */
16308 SimpleAttributeOperand_members /* .members */
16309},
16310/* ContentFilterElementResult */
16311{
16312 UA_TYPENAME("ContentFilterElementResult") /* .typeName */
16313 {0, UA_NODEIDTYPE_NUMERIC, {604LU}}, /* .typeId */
16314 {0, UA_NODEIDTYPE_NUMERIC, {606LU}}, /* .binaryEncodingId */
16315 sizeof(UA_ContentFilterElementResult), /* .memSize */
16316 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16317 false, /* .pointerFree */
16318 false, /* .overlayable */
16319 3, /* .membersSize */
16320 ContentFilterElementResult_members /* .members */
16321},
16322/* ContentFilterResult */
16323{
16324 UA_TYPENAME("ContentFilterResult") /* .typeName */
16325 {0, UA_NODEIDTYPE_NUMERIC, {607LU}}, /* .typeId */
16326 {0, UA_NODEIDTYPE_NUMERIC, {609LU}}, /* .binaryEncodingId */
16327 sizeof(UA_ContentFilterResult), /* .memSize */
16328 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16329 false, /* .pointerFree */
16330 false, /* .overlayable */
16331 2, /* .membersSize */
16332 ContentFilterResult_members /* .members */
16333},
16334/* TimestampsToReturn */
16335{
16336 UA_TYPENAME("TimestampsToReturn") /* .typeName */
16337 {0, UA_NODEIDTYPE_NUMERIC, {625LU}}, /* .typeId */
16338 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16339 sizeof(UA_TimestampsToReturn), /* .memSize */
16340 UA_DATATYPEKIND_ENUM, /* .typeKind */
16341 true, /* .pointerFree */
16342 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16343 0, /* .membersSize */
16344 TimestampsToReturn_members /* .members */
16345},
16346/* ReadValueId */
16347{
16348 UA_TYPENAME("ReadValueId") /* .typeName */
16349 {0, UA_NODEIDTYPE_NUMERIC, {626LU}}, /* .typeId */
16350 {0, UA_NODEIDTYPE_NUMERIC, {628LU}}, /* .binaryEncodingId */
16351 sizeof(UA_ReadValueId), /* .memSize */
16352 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16353 false, /* .pointerFree */
16354 false, /* .overlayable */
16355 4, /* .membersSize */
16356 ReadValueId_members /* .members */
16357},
16358/* ReadRequest */
16359{
16360 UA_TYPENAME("ReadRequest") /* .typeName */
16361 {0, UA_NODEIDTYPE_NUMERIC, {629LU}}, /* .typeId */
16362 {0, UA_NODEIDTYPE_NUMERIC, {631LU}}, /* .binaryEncodingId */
16363 sizeof(UA_ReadRequest), /* .memSize */
16364 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16365 false, /* .pointerFree */
16366 false, /* .overlayable */
16367 4, /* .membersSize */
16368 ReadRequest_members /* .members */
16369},
16370/* ReadResponse */
16371{
16372 UA_TYPENAME("ReadResponse") /* .typeName */
16373 {0, UA_NODEIDTYPE_NUMERIC, {632LU}}, /* .typeId */
16374 {0, UA_NODEIDTYPE_NUMERIC, {634LU}}, /* .binaryEncodingId */
16375 sizeof(UA_ReadResponse), /* .memSize */
16376 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16377 false, /* .pointerFree */
16378 false, /* .overlayable */
16379 3, /* .membersSize */
16380 ReadResponse_members /* .members */
16381},
16382/* HistoryReadValueId */
16383{
16384 UA_TYPENAME("HistoryReadValueId") /* .typeName */
16385 {0, UA_NODEIDTYPE_NUMERIC, {635LU}}, /* .typeId */
16386 {0, UA_NODEIDTYPE_NUMERIC, {637LU}}, /* .binaryEncodingId */
16387 sizeof(UA_HistoryReadValueId), /* .memSize */
16388 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16389 false, /* .pointerFree */
16390 false, /* .overlayable */
16391 4, /* .membersSize */
16392 HistoryReadValueId_members /* .members */
16393},
16394/* HistoryReadResult */
16395{
16396 UA_TYPENAME("HistoryReadResult") /* .typeName */
16397 {0, UA_NODEIDTYPE_NUMERIC, {638LU}}, /* .typeId */
16398 {0, UA_NODEIDTYPE_NUMERIC, {640LU}}, /* .binaryEncodingId */
16399 sizeof(UA_HistoryReadResult), /* .memSize */
16400 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16401 false, /* .pointerFree */
16402 false, /* .overlayable */
16403 3, /* .membersSize */
16404 HistoryReadResult_members /* .members */
16405},
16406/* ReadRawModifiedDetails */
16407{
16408 UA_TYPENAME("ReadRawModifiedDetails") /* .typeName */
16409 {0, UA_NODEIDTYPE_NUMERIC, {647LU}}, /* .typeId */
16410 {0, UA_NODEIDTYPE_NUMERIC, {649LU}}, /* .binaryEncodingId */
16411 sizeof(UA_ReadRawModifiedDetails), /* .memSize */
16412 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16413 true, /* .pointerFree */
16414 false, /* .overlayable */
16415 5, /* .membersSize */
16416 ReadRawModifiedDetails_members /* .members */
16417},
16418/* ReadAtTimeDetails */
16419{
16420 UA_TYPENAME("ReadAtTimeDetails") /* .typeName */
16421 {0, UA_NODEIDTYPE_NUMERIC, {653LU}}, /* .typeId */
16422 {0, UA_NODEIDTYPE_NUMERIC, {655LU}}, /* .binaryEncodingId */
16423 sizeof(UA_ReadAtTimeDetails), /* .memSize */
16424 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16425 false, /* .pointerFree */
16426 false, /* .overlayable */
16427 2, /* .membersSize */
16428 ReadAtTimeDetails_members /* .members */
16429},
16430/* HistoryData */
16431{
16432 UA_TYPENAME("HistoryData") /* .typeName */
16433 {0, UA_NODEIDTYPE_NUMERIC, {656LU}}, /* .typeId */
16434 {0, UA_NODEIDTYPE_NUMERIC, {658LU}}, /* .binaryEncodingId */
16435 sizeof(UA_HistoryData), /* .memSize */
16436 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16437 false, /* .pointerFree */
16438 false, /* .overlayable */
16439 1, /* .membersSize */
16440 HistoryData_members /* .members */
16441},
16442/* HistoryReadRequest */
16443{
16444 UA_TYPENAME("HistoryReadRequest") /* .typeName */
16445 {0, UA_NODEIDTYPE_NUMERIC, {662LU}}, /* .typeId */
16446 {0, UA_NODEIDTYPE_NUMERIC, {664LU}}, /* .binaryEncodingId */
16447 sizeof(UA_HistoryReadRequest), /* .memSize */
16448 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16449 false, /* .pointerFree */
16450 false, /* .overlayable */
16451 5, /* .membersSize */
16452 HistoryReadRequest_members /* .members */
16453},
16454/* HistoryReadResponse */
16455{
16456 UA_TYPENAME("HistoryReadResponse") /* .typeName */
16457 {0, UA_NODEIDTYPE_NUMERIC, {665LU}}, /* .typeId */
16458 {0, UA_NODEIDTYPE_NUMERIC, {667LU}}, /* .binaryEncodingId */
16459 sizeof(UA_HistoryReadResponse), /* .memSize */
16460 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16461 false, /* .pointerFree */
16462 false, /* .overlayable */
16463 3, /* .membersSize */
16464 HistoryReadResponse_members /* .members */
16465},
16466/* WriteValue */
16467{
16468 UA_TYPENAME("WriteValue") /* .typeName */
16469 {0, UA_NODEIDTYPE_NUMERIC, {668LU}}, /* .typeId */
16470 {0, UA_NODEIDTYPE_NUMERIC, {670LU}}, /* .binaryEncodingId */
16471 sizeof(UA_WriteValue), /* .memSize */
16472 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16473 false, /* .pointerFree */
16474 false, /* .overlayable */
16475 4, /* .membersSize */
16476 WriteValue_members /* .members */
16477},
16478/* WriteRequest */
16479{
16480 UA_TYPENAME("WriteRequest") /* .typeName */
16481 {0, UA_NODEIDTYPE_NUMERIC, {671LU}}, /* .typeId */
16482 {0, UA_NODEIDTYPE_NUMERIC, {673LU}}, /* .binaryEncodingId */
16483 sizeof(UA_WriteRequest), /* .memSize */
16484 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16485 false, /* .pointerFree */
16486 false, /* .overlayable */
16487 2, /* .membersSize */
16488 WriteRequest_members /* .members */
16489},
16490/* WriteResponse */
16491{
16492 UA_TYPENAME("WriteResponse") /* .typeName */
16493 {0, UA_NODEIDTYPE_NUMERIC, {674LU}}, /* .typeId */
16494 {0, UA_NODEIDTYPE_NUMERIC, {676LU}}, /* .binaryEncodingId */
16495 sizeof(UA_WriteResponse), /* .memSize */
16496 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16497 false, /* .pointerFree */
16498 false, /* .overlayable */
16499 3, /* .membersSize */
16500 WriteResponse_members /* .members */
16501},
16502/* HistoryUpdateType */
16503{
16504 UA_TYPENAME("HistoryUpdateType") /* .typeName */
16505 {0, UA_NODEIDTYPE_NUMERIC, {11234LU}}, /* .typeId */
16506 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16507 sizeof(UA_HistoryUpdateType), /* .memSize */
16508 UA_DATATYPEKIND_ENUM, /* .typeKind */
16509 true, /* .pointerFree */
16510 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16511 0, /* .membersSize */
16512 HistoryUpdateType_members /* .members */
16513},
16514/* PerformUpdateType */
16515{
16516 UA_TYPENAME("PerformUpdateType") /* .typeName */
16517 {0, UA_NODEIDTYPE_NUMERIC, {11293LU}}, /* .typeId */
16518 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16519 sizeof(UA_PerformUpdateType), /* .memSize */
16520 UA_DATATYPEKIND_ENUM, /* .typeKind */
16521 true, /* .pointerFree */
16522 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16523 0, /* .membersSize */
16524 PerformUpdateType_members /* .members */
16525},
16526/* UpdateDataDetails */
16527{
16528 UA_TYPENAME("UpdateDataDetails") /* .typeName */
16529 {0, UA_NODEIDTYPE_NUMERIC, {680LU}}, /* .typeId */
16530 {0, UA_NODEIDTYPE_NUMERIC, {682LU}}, /* .binaryEncodingId */
16531 sizeof(UA_UpdateDataDetails), /* .memSize */
16532 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16533 false, /* .pointerFree */
16534 false, /* .overlayable */
16535 3, /* .membersSize */
16536 UpdateDataDetails_members /* .members */
16537},
16538/* DeleteRawModifiedDetails */
16539{
16540 UA_TYPENAME("DeleteRawModifiedDetails") /* .typeName */
16541 {0, UA_NODEIDTYPE_NUMERIC, {686LU}}, /* .typeId */
16542 {0, UA_NODEIDTYPE_NUMERIC, {688LU}}, /* .binaryEncodingId */
16543 sizeof(UA_DeleteRawModifiedDetails), /* .memSize */
16544 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16545 false, /* .pointerFree */
16546 false, /* .overlayable */
16547 4, /* .membersSize */
16548 DeleteRawModifiedDetails_members /* .members */
16549},
16550/* HistoryUpdateResult */
16551{
16552 UA_TYPENAME("HistoryUpdateResult") /* .typeName */
16553 {0, UA_NODEIDTYPE_NUMERIC, {695LU}}, /* .typeId */
16554 {0, UA_NODEIDTYPE_NUMERIC, {697LU}}, /* .binaryEncodingId */
16555 sizeof(UA_HistoryUpdateResult), /* .memSize */
16556 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16557 false, /* .pointerFree */
16558 false, /* .overlayable */
16559 3, /* .membersSize */
16560 HistoryUpdateResult_members /* .members */
16561},
16562/* HistoryUpdateRequest */
16563{
16564 UA_TYPENAME("HistoryUpdateRequest") /* .typeName */
16565 {0, UA_NODEIDTYPE_NUMERIC, {698LU}}, /* .typeId */
16566 {0, UA_NODEIDTYPE_NUMERIC, {700LU}}, /* .binaryEncodingId */
16567 sizeof(UA_HistoryUpdateRequest), /* .memSize */
16568 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16569 false, /* .pointerFree */
16570 false, /* .overlayable */
16571 2, /* .membersSize */
16572 HistoryUpdateRequest_members /* .members */
16573},
16574/* HistoryUpdateResponse */
16575{
16576 UA_TYPENAME("HistoryUpdateResponse") /* .typeName */
16577 {0, UA_NODEIDTYPE_NUMERIC, {701LU}}, /* .typeId */
16578 {0, UA_NODEIDTYPE_NUMERIC, {703LU}}, /* .binaryEncodingId */
16579 sizeof(UA_HistoryUpdateResponse), /* .memSize */
16580 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16581 false, /* .pointerFree */
16582 false, /* .overlayable */
16583 3, /* .membersSize */
16584 HistoryUpdateResponse_members /* .members */
16585},
16586/* CallMethodRequest */
16587{
16588 UA_TYPENAME("CallMethodRequest") /* .typeName */
16589 {0, UA_NODEIDTYPE_NUMERIC, {704LU}}, /* .typeId */
16590 {0, UA_NODEIDTYPE_NUMERIC, {706LU}}, /* .binaryEncodingId */
16591 sizeof(UA_CallMethodRequest), /* .memSize */
16592 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16593 false, /* .pointerFree */
16594 false, /* .overlayable */
16595 3, /* .membersSize */
16596 CallMethodRequest_members /* .members */
16597},
16598/* CallMethodResult */
16599{
16600 UA_TYPENAME("CallMethodResult") /* .typeName */
16601 {0, UA_NODEIDTYPE_NUMERIC, {707LU}}, /* .typeId */
16602 {0, UA_NODEIDTYPE_NUMERIC, {709LU}}, /* .binaryEncodingId */
16603 sizeof(UA_CallMethodResult), /* .memSize */
16604 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16605 false, /* .pointerFree */
16606 false, /* .overlayable */
16607 4, /* .membersSize */
16608 CallMethodResult_members /* .members */
16609},
16610/* CallRequest */
16611{
16612 UA_TYPENAME("CallRequest") /* .typeName */
16613 {0, UA_NODEIDTYPE_NUMERIC, {710LU}}, /* .typeId */
16614 {0, UA_NODEIDTYPE_NUMERIC, {712LU}}, /* .binaryEncodingId */
16615 sizeof(UA_CallRequest), /* .memSize */
16616 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16617 false, /* .pointerFree */
16618 false, /* .overlayable */
16619 2, /* .membersSize */
16620 CallRequest_members /* .members */
16621},
16622/* CallResponse */
16623{
16624 UA_TYPENAME("CallResponse") /* .typeName */
16625 {0, UA_NODEIDTYPE_NUMERIC, {713LU}}, /* .typeId */
16626 {0, UA_NODEIDTYPE_NUMERIC, {715LU}}, /* .binaryEncodingId */
16627 sizeof(UA_CallResponse), /* .memSize */
16628 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16629 false, /* .pointerFree */
16630 false, /* .overlayable */
16631 3, /* .membersSize */
16632 CallResponse_members /* .members */
16633},
16634/* MonitoringMode */
16635{
16636 UA_TYPENAME("MonitoringMode") /* .typeName */
16637 {0, UA_NODEIDTYPE_NUMERIC, {716LU}}, /* .typeId */
16638 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16639 sizeof(UA_MonitoringMode), /* .memSize */
16640 UA_DATATYPEKIND_ENUM, /* .typeKind */
16641 true, /* .pointerFree */
16642 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16643 0, /* .membersSize */
16644 MonitoringMode_members /* .members */
16645},
16646/* DataChangeTrigger */
16647{
16648 UA_TYPENAME("DataChangeTrigger") /* .typeName */
16649 {0, UA_NODEIDTYPE_NUMERIC, {717LU}}, /* .typeId */
16650 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16651 sizeof(UA_DataChangeTrigger), /* .memSize */
16652 UA_DATATYPEKIND_ENUM, /* .typeKind */
16653 true, /* .pointerFree */
16654 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16655 0, /* .membersSize */
16656 DataChangeTrigger_members /* .members */
16657},
16658/* DeadbandType */
16659{
16660 UA_TYPENAME("DeadbandType") /* .typeName */
16661 {0, UA_NODEIDTYPE_NUMERIC, {718LU}}, /* .typeId */
16662 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
16663 sizeof(UA_DeadbandType), /* .memSize */
16664 UA_DATATYPEKIND_ENUM, /* .typeKind */
16665 true, /* .pointerFree */
16666 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
16667 0, /* .membersSize */
16668 DeadbandType_members /* .members */
16669},
16670/* DataChangeFilter */
16671{
16672 UA_TYPENAME("DataChangeFilter") /* .typeName */
16673 {0, UA_NODEIDTYPE_NUMERIC, {722LU}}, /* .typeId */
16674 {0, UA_NODEIDTYPE_NUMERIC, {724LU}}, /* .binaryEncodingId */
16675 sizeof(UA_DataChangeFilter), /* .memSize */
16676 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16677 true, /* .pointerFree */
16678 false, /* .overlayable */
16679 3, /* .membersSize */
16680 DataChangeFilter_members /* .members */
16681},
16682/* EventFilter */
16683{
16684 UA_TYPENAME("EventFilter") /* .typeName */
16685 {0, UA_NODEIDTYPE_NUMERIC, {725LU}}, /* .typeId */
16686 {0, UA_NODEIDTYPE_NUMERIC, {727LU}}, /* .binaryEncodingId */
16687 sizeof(UA_EventFilter), /* .memSize */
16688 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16689 false, /* .pointerFree */
16690 false, /* .overlayable */
16691 2, /* .membersSize */
16692 EventFilter_members /* .members */
16693},
16694/* AggregateConfiguration */
16695{
16696 UA_TYPENAME("AggregateConfiguration") /* .typeName */
16697 {0, UA_NODEIDTYPE_NUMERIC, {948LU}}, /* .typeId */
16698 {0, UA_NODEIDTYPE_NUMERIC, {950LU}}, /* .binaryEncodingId */
16699 sizeof(UA_AggregateConfiguration), /* .memSize */
16700 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16701 true, /* .pointerFree */
16702 false, /* .overlayable */
16703 5, /* .membersSize */
16704 AggregateConfiguration_members /* .members */
16705},
16706/* AggregateFilter */
16707{
16708 UA_TYPENAME("AggregateFilter") /* .typeName */
16709 {0, UA_NODEIDTYPE_NUMERIC, {728LU}}, /* .typeId */
16710 {0, UA_NODEIDTYPE_NUMERIC, {730LU}}, /* .binaryEncodingId */
16711 sizeof(UA_AggregateFilter), /* .memSize */
16712 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16713 false, /* .pointerFree */
16714 false, /* .overlayable */
16715 4, /* .membersSize */
16716 AggregateFilter_members /* .members */
16717},
16718/* EventFilterResult */
16719{
16720 UA_TYPENAME("EventFilterResult") /* .typeName */
16721 {0, UA_NODEIDTYPE_NUMERIC, {734LU}}, /* .typeId */
16722 {0, UA_NODEIDTYPE_NUMERIC, {736LU}}, /* .binaryEncodingId */
16723 sizeof(UA_EventFilterResult), /* .memSize */
16724 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16725 false, /* .pointerFree */
16726 false, /* .overlayable */
16727 3, /* .membersSize */
16728 EventFilterResult_members /* .members */
16729},
16730/* MonitoringParameters */
16731{
16732 UA_TYPENAME("MonitoringParameters") /* .typeName */
16733 {0, UA_NODEIDTYPE_NUMERIC, {740LU}}, /* .typeId */
16734 {0, UA_NODEIDTYPE_NUMERIC, {742LU}}, /* .binaryEncodingId */
16735 sizeof(UA_MonitoringParameters), /* .memSize */
16736 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16737 false, /* .pointerFree */
16738 false, /* .overlayable */
16739 5, /* .membersSize */
16740 MonitoringParameters_members /* .members */
16741},
16742/* MonitoredItemCreateRequest */
16743{
16744 UA_TYPENAME("MonitoredItemCreateRequest") /* .typeName */
16745 {0, UA_NODEIDTYPE_NUMERIC, {743LU}}, /* .typeId */
16746 {0, UA_NODEIDTYPE_NUMERIC, {745LU}}, /* .binaryEncodingId */
16747 sizeof(UA_MonitoredItemCreateRequest), /* .memSize */
16748 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16749 false, /* .pointerFree */
16750 false, /* .overlayable */
16751 3, /* .membersSize */
16752 MonitoredItemCreateRequest_members /* .members */
16753},
16754/* MonitoredItemCreateResult */
16755{
16756 UA_TYPENAME("MonitoredItemCreateResult") /* .typeName */
16757 {0, UA_NODEIDTYPE_NUMERIC, {746LU}}, /* .typeId */
16758 {0, UA_NODEIDTYPE_NUMERIC, {748LU}}, /* .binaryEncodingId */
16759 sizeof(UA_MonitoredItemCreateResult), /* .memSize */
16760 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16761 false, /* .pointerFree */
16762 false, /* .overlayable */
16763 5, /* .membersSize */
16764 MonitoredItemCreateResult_members /* .members */
16765},
16766/* CreateMonitoredItemsRequest */
16767{
16768 UA_TYPENAME("CreateMonitoredItemsRequest") /* .typeName */
16769 {0, UA_NODEIDTYPE_NUMERIC, {749LU}}, /* .typeId */
16770 {0, UA_NODEIDTYPE_NUMERIC, {751LU}}, /* .binaryEncodingId */
16771 sizeof(UA_CreateMonitoredItemsRequest), /* .memSize */
16772 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16773 false, /* .pointerFree */
16774 false, /* .overlayable */
16775 4, /* .membersSize */
16776 CreateMonitoredItemsRequest_members /* .members */
16777},
16778/* CreateMonitoredItemsResponse */
16779{
16780 UA_TYPENAME("CreateMonitoredItemsResponse") /* .typeName */
16781 {0, UA_NODEIDTYPE_NUMERIC, {752LU}}, /* .typeId */
16782 {0, UA_NODEIDTYPE_NUMERIC, {754LU}}, /* .binaryEncodingId */
16783 sizeof(UA_CreateMonitoredItemsResponse), /* .memSize */
16784 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16785 false, /* .pointerFree */
16786 false, /* .overlayable */
16787 3, /* .membersSize */
16788 CreateMonitoredItemsResponse_members /* .members */
16789},
16790/* MonitoredItemModifyRequest */
16791{
16792 UA_TYPENAME("MonitoredItemModifyRequest") /* .typeName */
16793 {0, UA_NODEIDTYPE_NUMERIC, {755LU}}, /* .typeId */
16794 {0, UA_NODEIDTYPE_NUMERIC, {757LU}}, /* .binaryEncodingId */
16795 sizeof(UA_MonitoredItemModifyRequest), /* .memSize */
16796 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16797 false, /* .pointerFree */
16798 false, /* .overlayable */
16799 2, /* .membersSize */
16800 MonitoredItemModifyRequest_members /* .members */
16801},
16802/* MonitoredItemModifyResult */
16803{
16804 UA_TYPENAME("MonitoredItemModifyResult") /* .typeName */
16805 {0, UA_NODEIDTYPE_NUMERIC, {758LU}}, /* .typeId */
16806 {0, UA_NODEIDTYPE_NUMERIC, {760LU}}, /* .binaryEncodingId */
16807 sizeof(UA_MonitoredItemModifyResult), /* .memSize */
16808 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16809 false, /* .pointerFree */
16810 false, /* .overlayable */
16811 4, /* .membersSize */
16812 MonitoredItemModifyResult_members /* .members */
16813},
16814/* ModifyMonitoredItemsRequest */
16815{
16816 UA_TYPENAME("ModifyMonitoredItemsRequest") /* .typeName */
16817 {0, UA_NODEIDTYPE_NUMERIC, {761LU}}, /* .typeId */
16818 {0, UA_NODEIDTYPE_NUMERIC, {763LU}}, /* .binaryEncodingId */
16819 sizeof(UA_ModifyMonitoredItemsRequest), /* .memSize */
16820 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16821 false, /* .pointerFree */
16822 false, /* .overlayable */
16823 4, /* .membersSize */
16824 ModifyMonitoredItemsRequest_members /* .members */
16825},
16826/* ModifyMonitoredItemsResponse */
16827{
16828 UA_TYPENAME("ModifyMonitoredItemsResponse") /* .typeName */
16829 {0, UA_NODEIDTYPE_NUMERIC, {764LU}}, /* .typeId */
16830 {0, UA_NODEIDTYPE_NUMERIC, {766LU}}, /* .binaryEncodingId */
16831 sizeof(UA_ModifyMonitoredItemsResponse), /* .memSize */
16832 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16833 false, /* .pointerFree */
16834 false, /* .overlayable */
16835 3, /* .membersSize */
16836 ModifyMonitoredItemsResponse_members /* .members */
16837},
16838/* SetMonitoringModeRequest */
16839{
16840 UA_TYPENAME("SetMonitoringModeRequest") /* .typeName */
16841 {0, UA_NODEIDTYPE_NUMERIC, {767LU}}, /* .typeId */
16842 {0, UA_NODEIDTYPE_NUMERIC, {769LU}}, /* .binaryEncodingId */
16843 sizeof(UA_SetMonitoringModeRequest), /* .memSize */
16844 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16845 false, /* .pointerFree */
16846 false, /* .overlayable */
16847 4, /* .membersSize */
16848 SetMonitoringModeRequest_members /* .members */
16849},
16850/* SetMonitoringModeResponse */
16851{
16852 UA_TYPENAME("SetMonitoringModeResponse") /* .typeName */
16853 {0, UA_NODEIDTYPE_NUMERIC, {770LU}}, /* .typeId */
16854 {0, UA_NODEIDTYPE_NUMERIC, {772LU}}, /* .binaryEncodingId */
16855 sizeof(UA_SetMonitoringModeResponse), /* .memSize */
16856 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16857 false, /* .pointerFree */
16858 false, /* .overlayable */
16859 3, /* .membersSize */
16860 SetMonitoringModeResponse_members /* .members */
16861},
16862/* SetTriggeringRequest */
16863{
16864 UA_TYPENAME("SetTriggeringRequest") /* .typeName */
16865 {0, UA_NODEIDTYPE_NUMERIC, {773LU}}, /* .typeId */
16866 {0, UA_NODEIDTYPE_NUMERIC, {775LU}}, /* .binaryEncodingId */
16867 sizeof(UA_SetTriggeringRequest), /* .memSize */
16868 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16869 false, /* .pointerFree */
16870 false, /* .overlayable */
16871 5, /* .membersSize */
16872 SetTriggeringRequest_members /* .members */
16873},
16874/* SetTriggeringResponse */
16875{
16876 UA_TYPENAME("SetTriggeringResponse") /* .typeName */
16877 {0, UA_NODEIDTYPE_NUMERIC, {776LU}}, /* .typeId */
16878 {0, UA_NODEIDTYPE_NUMERIC, {778LU}}, /* .binaryEncodingId */
16879 sizeof(UA_SetTriggeringResponse), /* .memSize */
16880 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16881 false, /* .pointerFree */
16882 false, /* .overlayable */
16883 5, /* .membersSize */
16884 SetTriggeringResponse_members /* .members */
16885},
16886/* DeleteMonitoredItemsRequest */
16887{
16888 UA_TYPENAME("DeleteMonitoredItemsRequest") /* .typeName */
16889 {0, UA_NODEIDTYPE_NUMERIC, {779LU}}, /* .typeId */
16890 {0, UA_NODEIDTYPE_NUMERIC, {781LU}}, /* .binaryEncodingId */
16891 sizeof(UA_DeleteMonitoredItemsRequest), /* .memSize */
16892 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16893 false, /* .pointerFree */
16894 false, /* .overlayable */
16895 3, /* .membersSize */
16896 DeleteMonitoredItemsRequest_members /* .members */
16897},
16898/* DeleteMonitoredItemsResponse */
16899{
16900 UA_TYPENAME("DeleteMonitoredItemsResponse") /* .typeName */
16901 {0, UA_NODEIDTYPE_NUMERIC, {782LU}}, /* .typeId */
16902 {0, UA_NODEIDTYPE_NUMERIC, {784LU}}, /* .binaryEncodingId */
16903 sizeof(UA_DeleteMonitoredItemsResponse), /* .memSize */
16904 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16905 false, /* .pointerFree */
16906 false, /* .overlayable */
16907 3, /* .membersSize */
16908 DeleteMonitoredItemsResponse_members /* .members */
16909},
16910/* CreateSubscriptionRequest */
16911{
16912 UA_TYPENAME("CreateSubscriptionRequest") /* .typeName */
16913 {0, UA_NODEIDTYPE_NUMERIC, {785LU}}, /* .typeId */
16914 {0, UA_NODEIDTYPE_NUMERIC, {787LU}}, /* .binaryEncodingId */
16915 sizeof(UA_CreateSubscriptionRequest), /* .memSize */
16916 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16917 false, /* .pointerFree */
16918 false, /* .overlayable */
16919 7, /* .membersSize */
16920 CreateSubscriptionRequest_members /* .members */
16921},
16922/* CreateSubscriptionResponse */
16923{
16924 UA_TYPENAME("CreateSubscriptionResponse") /* .typeName */
16925 {0, UA_NODEIDTYPE_NUMERIC, {788LU}}, /* .typeId */
16926 {0, UA_NODEIDTYPE_NUMERIC, {790LU}}, /* .binaryEncodingId */
16927 sizeof(UA_CreateSubscriptionResponse), /* .memSize */
16928 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16929 false, /* .pointerFree */
16930 false, /* .overlayable */
16931 5, /* .membersSize */
16932 CreateSubscriptionResponse_members /* .members */
16933},
16934/* ModifySubscriptionRequest */
16935{
16936 UA_TYPENAME("ModifySubscriptionRequest") /* .typeName */
16937 {0, UA_NODEIDTYPE_NUMERIC, {791LU}}, /* .typeId */
16938 {0, UA_NODEIDTYPE_NUMERIC, {793LU}}, /* .binaryEncodingId */
16939 sizeof(UA_ModifySubscriptionRequest), /* .memSize */
16940 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16941 false, /* .pointerFree */
16942 false, /* .overlayable */
16943 7, /* .membersSize */
16944 ModifySubscriptionRequest_members /* .members */
16945},
16946/* ModifySubscriptionResponse */
16947{
16948 UA_TYPENAME("ModifySubscriptionResponse") /* .typeName */
16949 {0, UA_NODEIDTYPE_NUMERIC, {794LU}}, /* .typeId */
16950 {0, UA_NODEIDTYPE_NUMERIC, {796LU}}, /* .binaryEncodingId */
16951 sizeof(UA_ModifySubscriptionResponse), /* .memSize */
16952 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16953 false, /* .pointerFree */
16954 false, /* .overlayable */
16955 4, /* .membersSize */
16956 ModifySubscriptionResponse_members /* .members */
16957},
16958/* SetPublishingModeRequest */
16959{
16960 UA_TYPENAME("SetPublishingModeRequest") /* .typeName */
16961 {0, UA_NODEIDTYPE_NUMERIC, {797LU}}, /* .typeId */
16962 {0, UA_NODEIDTYPE_NUMERIC, {799LU}}, /* .binaryEncodingId */
16963 sizeof(UA_SetPublishingModeRequest), /* .memSize */
16964 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16965 false, /* .pointerFree */
16966 false, /* .overlayable */
16967 3, /* .membersSize */
16968 SetPublishingModeRequest_members /* .members */
16969},
16970/* SetPublishingModeResponse */
16971{
16972 UA_TYPENAME("SetPublishingModeResponse") /* .typeName */
16973 {0, UA_NODEIDTYPE_NUMERIC, {800LU}}, /* .typeId */
16974 {0, UA_NODEIDTYPE_NUMERIC, {802LU}}, /* .binaryEncodingId */
16975 sizeof(UA_SetPublishingModeResponse), /* .memSize */
16976 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16977 false, /* .pointerFree */
16978 false, /* .overlayable */
16979 3, /* .membersSize */
16980 SetPublishingModeResponse_members /* .members */
16981},
16982/* NotificationMessage */
16983{
16984 UA_TYPENAME("NotificationMessage") /* .typeName */
16985 {0, UA_NODEIDTYPE_NUMERIC, {803LU}}, /* .typeId */
16986 {0, UA_NODEIDTYPE_NUMERIC, {805LU}}, /* .binaryEncodingId */
16987 sizeof(UA_NotificationMessage), /* .memSize */
16988 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
16989 false, /* .pointerFree */
16990 false, /* .overlayable */
16991 3, /* .membersSize */
16992 NotificationMessage_members /* .members */
16993},
16994/* MonitoredItemNotification */
16995{
16996 UA_TYPENAME("MonitoredItemNotification") /* .typeName */
16997 {0, UA_NODEIDTYPE_NUMERIC, {806LU}}, /* .typeId */
16998 {0, UA_NODEIDTYPE_NUMERIC, {808LU}}, /* .binaryEncodingId */
16999 sizeof(UA_MonitoredItemNotification), /* .memSize */
17000 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17001 false, /* .pointerFree */
17002 false, /* .overlayable */
17003 2, /* .membersSize */
17004 MonitoredItemNotification_members /* .members */
17005},
17006/* EventFieldList */
17007{
17008 UA_TYPENAME("EventFieldList") /* .typeName */
17009 {0, UA_NODEIDTYPE_NUMERIC, {917LU}}, /* .typeId */
17010 {0, UA_NODEIDTYPE_NUMERIC, {919LU}}, /* .binaryEncodingId */
17011 sizeof(UA_EventFieldList), /* .memSize */
17012 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17013 false, /* .pointerFree */
17014 false, /* .overlayable */
17015 2, /* .membersSize */
17016 EventFieldList_members /* .members */
17017},
17018/* HistoryEventFieldList */
17019{
17020 UA_TYPENAME("HistoryEventFieldList") /* .typeName */
17021 {0, UA_NODEIDTYPE_NUMERIC, {920LU}}, /* .typeId */
17022 {0, UA_NODEIDTYPE_NUMERIC, {922LU}}, /* .binaryEncodingId */
17023 sizeof(UA_HistoryEventFieldList), /* .memSize */
17024 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17025 false, /* .pointerFree */
17026 false, /* .overlayable */
17027 1, /* .membersSize */
17028 HistoryEventFieldList_members /* .members */
17029},
17030/* StatusChangeNotification */
17031{
17032 UA_TYPENAME("StatusChangeNotification") /* .typeName */
17033 {0, UA_NODEIDTYPE_NUMERIC, {818LU}}, /* .typeId */
17034 {0, UA_NODEIDTYPE_NUMERIC, {820LU}}, /* .binaryEncodingId */
17035 sizeof(UA_StatusChangeNotification), /* .memSize */
17036 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17037 false, /* .pointerFree */
17038 false, /* .overlayable */
17039 2, /* .membersSize */
17040 StatusChangeNotification_members /* .members */
17041},
17042/* SubscriptionAcknowledgement */
17043{
17044 UA_TYPENAME("SubscriptionAcknowledgement") /* .typeName */
17045 {0, UA_NODEIDTYPE_NUMERIC, {821LU}}, /* .typeId */
17046 {0, UA_NODEIDTYPE_NUMERIC, {823LU}}, /* .binaryEncodingId */
17047 sizeof(UA_SubscriptionAcknowledgement), /* .memSize */
17048 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17049 true, /* .pointerFree */
17050 false, /* .overlayable */
17051 2, /* .membersSize */
17052 SubscriptionAcknowledgement_members /* .members */
17053},
17054/* PublishRequest */
17055{
17056 UA_TYPENAME("PublishRequest") /* .typeName */
17057 {0, UA_NODEIDTYPE_NUMERIC, {824LU}}, /* .typeId */
17058 {0, UA_NODEIDTYPE_NUMERIC, {826LU}}, /* .binaryEncodingId */
17059 sizeof(UA_PublishRequest), /* .memSize */
17060 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17061 false, /* .pointerFree */
17062 false, /* .overlayable */
17063 2, /* .membersSize */
17064 PublishRequest_members /* .members */
17065},
17066/* PublishResponse */
17067{
17068 UA_TYPENAME("PublishResponse") /* .typeName */
17069 {0, UA_NODEIDTYPE_NUMERIC, {827LU}}, /* .typeId */
17070 {0, UA_NODEIDTYPE_NUMERIC, {829LU}}, /* .binaryEncodingId */
17071 sizeof(UA_PublishResponse), /* .memSize */
17072 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17073 false, /* .pointerFree */
17074 false, /* .overlayable */
17075 7, /* .membersSize */
17076 PublishResponse_members /* .members */
17077},
17078/* RepublishRequest */
17079{
17080 UA_TYPENAME("RepublishRequest") /* .typeName */
17081 {0, UA_NODEIDTYPE_NUMERIC, {830LU}}, /* .typeId */
17082 {0, UA_NODEIDTYPE_NUMERIC, {832LU}}, /* .binaryEncodingId */
17083 sizeof(UA_RepublishRequest), /* .memSize */
17084 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17085 false, /* .pointerFree */
17086 false, /* .overlayable */
17087 3, /* .membersSize */
17088 RepublishRequest_members /* .members */
17089},
17090/* RepublishResponse */
17091{
17092 UA_TYPENAME("RepublishResponse") /* .typeName */
17093 {0, UA_NODEIDTYPE_NUMERIC, {833LU}}, /* .typeId */
17094 {0, UA_NODEIDTYPE_NUMERIC, {835LU}}, /* .binaryEncodingId */
17095 sizeof(UA_RepublishResponse), /* .memSize */
17096 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17097 false, /* .pointerFree */
17098 false, /* .overlayable */
17099 2, /* .membersSize */
17100 RepublishResponse_members /* .members */
17101},
17102/* TransferResult */
17103{
17104 UA_TYPENAME("TransferResult") /* .typeName */
17105 {0, UA_NODEIDTYPE_NUMERIC, {836LU}}, /* .typeId */
17106 {0, UA_NODEIDTYPE_NUMERIC, {838LU}}, /* .binaryEncodingId */
17107 sizeof(UA_TransferResult), /* .memSize */
17108 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17109 false, /* .pointerFree */
17110 false, /* .overlayable */
17111 2, /* .membersSize */
17112 TransferResult_members /* .members */
17113},
17114/* TransferSubscriptionsRequest */
17115{
17116 UA_TYPENAME("TransferSubscriptionsRequest") /* .typeName */
17117 {0, UA_NODEIDTYPE_NUMERIC, {839LU}}, /* .typeId */
17118 {0, UA_NODEIDTYPE_NUMERIC, {841LU}}, /* .binaryEncodingId */
17119 sizeof(UA_TransferSubscriptionsRequest), /* .memSize */
17120 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17121 false, /* .pointerFree */
17122 false, /* .overlayable */
17123 3, /* .membersSize */
17124 TransferSubscriptionsRequest_members /* .members */
17125},
17126/* TransferSubscriptionsResponse */
17127{
17128 UA_TYPENAME("TransferSubscriptionsResponse") /* .typeName */
17129 {0, UA_NODEIDTYPE_NUMERIC, {842LU}}, /* .typeId */
17130 {0, UA_NODEIDTYPE_NUMERIC, {844LU}}, /* .binaryEncodingId */
17131 sizeof(UA_TransferSubscriptionsResponse), /* .memSize */
17132 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17133 false, /* .pointerFree */
17134 false, /* .overlayable */
17135 3, /* .membersSize */
17136 TransferSubscriptionsResponse_members /* .members */
17137},
17138/* DeleteSubscriptionsRequest */
17139{
17140 UA_TYPENAME("DeleteSubscriptionsRequest") /* .typeName */
17141 {0, UA_NODEIDTYPE_NUMERIC, {845LU}}, /* .typeId */
17142 {0, UA_NODEIDTYPE_NUMERIC, {847LU}}, /* .binaryEncodingId */
17143 sizeof(UA_DeleteSubscriptionsRequest), /* .memSize */
17144 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17145 false, /* .pointerFree */
17146 false, /* .overlayable */
17147 2, /* .membersSize */
17148 DeleteSubscriptionsRequest_members /* .members */
17149},
17150/* DeleteSubscriptionsResponse */
17151{
17152 UA_TYPENAME("DeleteSubscriptionsResponse") /* .typeName */
17153 {0, UA_NODEIDTYPE_NUMERIC, {848LU}}, /* .typeId */
17154 {0, UA_NODEIDTYPE_NUMERIC, {850LU}}, /* .binaryEncodingId */
17155 sizeof(UA_DeleteSubscriptionsResponse), /* .memSize */
17156 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17157 false, /* .pointerFree */
17158 false, /* .overlayable */
17159 3, /* .membersSize */
17160 DeleteSubscriptionsResponse_members /* .members */
17161},
17162/* BuildInfo */
17163{
17164 UA_TYPENAME("BuildInfo") /* .typeName */
17165 {0, UA_NODEIDTYPE_NUMERIC, {338LU}}, /* .typeId */
17166 {0, UA_NODEIDTYPE_NUMERIC, {340LU}}, /* .binaryEncodingId */
17167 sizeof(UA_BuildInfo), /* .memSize */
17168 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17169 false, /* .pointerFree */
17170 false, /* .overlayable */
17171 6, /* .membersSize */
17172 BuildInfo_members /* .members */
17173},
17174/* RedundancySupport */
17175{
17176 UA_TYPENAME("RedundancySupport") /* .typeName */
17177 {0, UA_NODEIDTYPE_NUMERIC, {851LU}}, /* .typeId */
17178 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17179 sizeof(UA_RedundancySupport), /* .memSize */
17180 UA_DATATYPEKIND_ENUM, /* .typeKind */
17181 true, /* .pointerFree */
17182 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17183 0, /* .membersSize */
17184 RedundancySupport_members /* .members */
17185},
17186/* ServerState */
17187{
17188 UA_TYPENAME("ServerState") /* .typeName */
17189 {0, UA_NODEIDTYPE_NUMERIC, {852LU}}, /* .typeId */
17190 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17191 sizeof(UA_ServerState), /* .memSize */
17192 UA_DATATYPEKIND_ENUM, /* .typeKind */
17193 true, /* .pointerFree */
17194 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17195 0, /* .membersSize */
17196 ServerState_members /* .members */
17197},
17198/* ServerDiagnosticsSummaryDataType */
17199{
17200 UA_TYPENAME("ServerDiagnosticsSummaryDataType") /* .typeName */
17201 {0, UA_NODEIDTYPE_NUMERIC, {859LU}}, /* .typeId */
17202 {0, UA_NODEIDTYPE_NUMERIC, {861LU}}, /* .binaryEncodingId */
17203 sizeof(UA_ServerDiagnosticsSummaryDataType), /* .memSize */
17204 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17205 true, /* .pointerFree */
17206 false, /* .overlayable */
17207 12, /* .membersSize */
17208 ServerDiagnosticsSummaryDataType_members /* .members */
17209},
17210/* ServerStatusDataType */
17211{
17212 UA_TYPENAME("ServerStatusDataType") /* .typeName */
17213 {0, UA_NODEIDTYPE_NUMERIC, {862LU}}, /* .typeId */
17214 {0, UA_NODEIDTYPE_NUMERIC, {864LU}}, /* .binaryEncodingId */
17215 sizeof(UA_ServerStatusDataType), /* .memSize */
17216 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17217 false, /* .pointerFree */
17218 false, /* .overlayable */
17219 6, /* .membersSize */
17220 ServerStatusDataType_members /* .members */
17221},
17222/* Range */
17223{
17224 UA_TYPENAME("Range") /* .typeName */
17225 {0, UA_NODEIDTYPE_NUMERIC, {884LU}}, /* .typeId */
17226 {0, UA_NODEIDTYPE_NUMERIC, {886LU}}, /* .binaryEncodingId */
17227 sizeof(UA_Range), /* .memSize */
17228 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17229 true, /* .pointerFree */
17230 false, /* .overlayable */
17231 2, /* .membersSize */
17232 Range_members /* .members */
17233},
17234/* EUInformation */
17235{
17236 UA_TYPENAME("EUInformation") /* .typeName */
17237 {0, UA_NODEIDTYPE_NUMERIC, {887LU}}, /* .typeId */
17238 {0, UA_NODEIDTYPE_NUMERIC, {889LU}}, /* .binaryEncodingId */
17239 sizeof(UA_EUInformation), /* .memSize */
17240 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17241 false, /* .pointerFree */
17242 false, /* .overlayable */
17243 4, /* .membersSize */
17244 EUInformation_members /* .members */
17245},
17246/* AxisScaleEnumeration */
17247{
17248 UA_TYPENAME("AxisScaleEnumeration") /* .typeName */
17249 {0, UA_NODEIDTYPE_NUMERIC, {12077LU}}, /* .typeId */
17250 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17251 sizeof(UA_AxisScaleEnumeration), /* .memSize */
17252 UA_DATATYPEKIND_ENUM, /* .typeKind */
17253 true, /* .pointerFree */
17254 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17255 0, /* .membersSize */
17256 AxisScaleEnumeration_members /* .members */
17257},
17258/* ComplexNumberType */
17259{
17260 UA_TYPENAME("ComplexNumberType") /* .typeName */
17261 {0, UA_NODEIDTYPE_NUMERIC, {12171LU}}, /* .typeId */
17262 {0, UA_NODEIDTYPE_NUMERIC, {12181LU}}, /* .binaryEncodingId */
17263 sizeof(UA_ComplexNumberType), /* .memSize */
17264 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17265 true, /* .pointerFree */
17266 false, /* .overlayable */
17267 2, /* .membersSize */
17268 ComplexNumberType_members /* .members */
17269},
17270/* DoubleComplexNumberType */
17271{
17272 UA_TYPENAME("DoubleComplexNumberType") /* .typeName */
17273 {0, UA_NODEIDTYPE_NUMERIC, {12172LU}}, /* .typeId */
17274 {0, UA_NODEIDTYPE_NUMERIC, {12182LU}}, /* .binaryEncodingId */
17275 sizeof(UA_DoubleComplexNumberType), /* .memSize */
17276 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17277 true, /* .pointerFree */
17278 false, /* .overlayable */
17279 2, /* .membersSize */
17280 DoubleComplexNumberType_members /* .members */
17281},
17282/* AxisInformation */
17283{
17284 UA_TYPENAME("AxisInformation") /* .typeName */
17285 {0, UA_NODEIDTYPE_NUMERIC, {12079LU}}, /* .typeId */
17286 {0, UA_NODEIDTYPE_NUMERIC, {12089LU}}, /* .binaryEncodingId */
17287 sizeof(UA_AxisInformation), /* .memSize */
17288 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17289 false, /* .pointerFree */
17290 false, /* .overlayable */
17291 5, /* .membersSize */
17292 AxisInformation_members /* .members */
17293},
17294/* XVType */
17295{
17296 UA_TYPENAME("XVType") /* .typeName */
17297 {0, UA_NODEIDTYPE_NUMERIC, {12080LU}}, /* .typeId */
17298 {0, UA_NODEIDTYPE_NUMERIC, {12090LU}}, /* .binaryEncodingId */
17299 sizeof(UA_XVType), /* .memSize */
17300 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17301 true, /* .pointerFree */
17302 false, /* .overlayable */
17303 2, /* .membersSize */
17304 XVType_members /* .members */
17305},
17306/* EnumDefinition */
17307{
17308 UA_TYPENAME("EnumDefinition") /* .typeName */
17309 {0, UA_NODEIDTYPE_NUMERIC, {100LU}}, /* .typeId */
17310 {0, UA_NODEIDTYPE_NUMERIC, {123LU}}, /* .binaryEncodingId */
17311 sizeof(UA_EnumDefinition), /* .memSize */
17312 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17313 false, /* .pointerFree */
17314 false, /* .overlayable */
17315 1, /* .membersSize */
17316 EnumDefinition_members /* .members */
17317},
17318/* ReadEventDetails */
17319{
17320 UA_TYPENAME("ReadEventDetails") /* .typeName */
17321 {0, UA_NODEIDTYPE_NUMERIC, {644LU}}, /* .typeId */
17322 {0, UA_NODEIDTYPE_NUMERIC, {646LU}}, /* .binaryEncodingId */
17323 sizeof(UA_ReadEventDetails), /* .memSize */
17324 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17325 false, /* .pointerFree */
17326 false, /* .overlayable */
17327 4, /* .membersSize */
17328 ReadEventDetails_members /* .members */
17329},
17330/* ReadProcessedDetails */
17331{
17332 UA_TYPENAME("ReadProcessedDetails") /* .typeName */
17333 {0, UA_NODEIDTYPE_NUMERIC, {650LU}}, /* .typeId */
17334 {0, UA_NODEIDTYPE_NUMERIC, {652LU}}, /* .binaryEncodingId */
17335 sizeof(UA_ReadProcessedDetails), /* .memSize */
17336 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17337 false, /* .pointerFree */
17338 false, /* .overlayable */
17339 5, /* .membersSize */
17340 ReadProcessedDetails_members /* .members */
17341},
17342/* ModificationInfo */
17343{
17344 UA_TYPENAME("ModificationInfo") /* .typeName */
17345 {0, UA_NODEIDTYPE_NUMERIC, {11216LU}}, /* .typeId */
17346 {0, UA_NODEIDTYPE_NUMERIC, {11226LU}}, /* .binaryEncodingId */
17347 sizeof(UA_ModificationInfo), /* .memSize */
17348 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17349 false, /* .pointerFree */
17350 false, /* .overlayable */
17351 3, /* .membersSize */
17352 ModificationInfo_members /* .members */
17353},
17354/* HistoryModifiedData */
17355{
17356 UA_TYPENAME("HistoryModifiedData") /* .typeName */
17357 {0, UA_NODEIDTYPE_NUMERIC, {11217LU}}, /* .typeId */
17358 {0, UA_NODEIDTYPE_NUMERIC, {11227LU}}, /* .binaryEncodingId */
17359 sizeof(UA_HistoryModifiedData), /* .memSize */
17360 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17361 false, /* .pointerFree */
17362 false, /* .overlayable */
17363 2, /* .membersSize */
17364 HistoryModifiedData_members /* .members */
17365},
17366/* HistoryEvent */
17367{
17368 UA_TYPENAME("HistoryEvent") /* .typeName */
17369 {0, UA_NODEIDTYPE_NUMERIC, {659LU}}, /* .typeId */
17370 {0, UA_NODEIDTYPE_NUMERIC, {661LU}}, /* .binaryEncodingId */
17371 sizeof(UA_HistoryEvent), /* .memSize */
17372 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17373 false, /* .pointerFree */
17374 false, /* .overlayable */
17375 1, /* .membersSize */
17376 HistoryEvent_members /* .members */
17377},
17378/* DataChangeNotification */
17379{
17380 UA_TYPENAME("DataChangeNotification") /* .typeName */
17381 {0, UA_NODEIDTYPE_NUMERIC, {809LU}}, /* .typeId */
17382 {0, UA_NODEIDTYPE_NUMERIC, {811LU}}, /* .binaryEncodingId */
17383 sizeof(UA_DataChangeNotification), /* .memSize */
17384 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17385 false, /* .pointerFree */
17386 false, /* .overlayable */
17387 2, /* .membersSize */
17388 DataChangeNotification_members /* .members */
17389},
17390/* EventNotificationList */
17391{
17392 UA_TYPENAME("EventNotificationList") /* .typeName */
17393 {0, UA_NODEIDTYPE_NUMERIC, {914LU}}, /* .typeId */
17394 {0, UA_NODEIDTYPE_NUMERIC, {916LU}}, /* .binaryEncodingId */
17395 sizeof(UA_EventNotificationList), /* .memSize */
17396 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17397 false, /* .pointerFree */
17398 false, /* .overlayable */
17399 1, /* .membersSize */
17400 EventNotificationList_members /* .members */
17401},
17402};
17403
17404
17405/**** amalgamated original file "/build/src_generated/open62541/transport_generated.c" ****/
17406
17407/**********************************
17408 * Autogenerated -- do not modify *
17409 **********************************/
17410
17411
17412/* MessageType */
17413#define MessageType_members NULL
17414
17415/* ChunkType */
17416#define ChunkType_members NULL
17417
17418/* TcpMessageHeader */
17419static UA_DataTypeMember TcpMessageHeader_members[2] = {
17420{
17421 UA_TYPENAME("MessageTypeAndChunkType") /* .memberName */
17422 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17423 0, /* .padding */
17424 false, /* .isArray */
17425 false /* .isOptional */
17426},
17427{
17428 UA_TYPENAME("MessageSize") /* .memberName */
17429 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17430 offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32), /* .padding */
17431 false, /* .isArray */
17432 false /* .isOptional */
17433},};
17434
17435/* TcpHelloMessage */
17436static UA_DataTypeMember TcpHelloMessage_members[6] = {
17437{
17438 UA_TYPENAME("ProtocolVersion") /* .memberName */
17439 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17440 0, /* .padding */
17441 false, /* .isArray */
17442 false /* .isOptional */
17443},
17444{
17445 UA_TYPENAME("ReceiveBufferSize") /* .memberName */
17446 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17447 offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
17448 false, /* .isArray */
17449 false /* .isOptional */
17450},
17451{
17452 UA_TYPENAME("SendBufferSize") /* .memberName */
17453 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17454 offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
17455 false, /* .isArray */
17456 false /* .isOptional */
17457},
17458{
17459 UA_TYPENAME("MaxMessageSize") /* .memberName */
17460 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17461 offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
17462 false, /* .isArray */
17463 false /* .isOptional */
17464},
17465{
17466 UA_TYPENAME("MaxChunkCount") /* .memberName */
17467 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17468 offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
17469 false, /* .isArray */
17470 false /* .isOptional */
17471},
17472{
17473 UA_TYPENAME("EndpointUrl") /* .memberName */
17474 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
17475 offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32), /* .padding */
17476 false, /* .isArray */
17477 false /* .isOptional */
17478},};
17479
17480/* TcpAcknowledgeMessage */
17481static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = {
17482{
17483 UA_TYPENAME("ProtocolVersion") /* .memberName */
17484 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17485 0, /* .padding */
17486 false, /* .isArray */
17487 false /* .isOptional */
17488},
17489{
17490 UA_TYPENAME("ReceiveBufferSize") /* .memberName */
17491 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17492 offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */
17493 false, /* .isArray */
17494 false /* .isOptional */
17495},
17496{
17497 UA_TYPENAME("SendBufferSize") /* .memberName */
17498 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17499 offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */
17500 false, /* .isArray */
17501 false /* .isOptional */
17502},
17503{
17504 UA_TYPENAME("MaxMessageSize") /* .memberName */
17505 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17506 offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */
17507 false, /* .isArray */
17508 false /* .isOptional */
17509},
17510{
17511 UA_TYPENAME("MaxChunkCount") /* .memberName */
17512 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17513 offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */
17514 false, /* .isArray */
17515 false /* .isOptional */
17516},};
17517
17518/* TcpErrorMessage */
17519static UA_DataTypeMember TcpErrorMessage_members[2] = {
17520{
17521 UA_TYPENAME("Error") /* .memberName */
17522 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17523 0, /* .padding */
17524 false, /* .isArray */
17525 false /* .isOptional */
17526},
17527{
17528 UA_TYPENAME("Reason") /* .memberName */
17529 &UA_TYPES[UA_TYPES_STRING], /* .memberType */
17530 offsetof(UA_TcpErrorMessage, reason) - offsetof(UA_TcpErrorMessage, error) - sizeof(UA_UInt32), /* .padding */
17531 false, /* .isArray */
17532 false /* .isOptional */
17533},};
17534
17535/* AsymmetricAlgorithmSecurityHeader */
17536static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = {
17537{
17538 UA_TYPENAME("SecurityPolicyUri") /* .memberName */
17539 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17540 0, /* .padding */
17541 false, /* .isArray */
17542 false /* .isOptional */
17543},
17544{
17545 UA_TYPENAME("SenderCertificate") /* .memberName */
17546 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17547 offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString), /* .padding */
17548 false, /* .isArray */
17549 false /* .isOptional */
17550},
17551{
17552 UA_TYPENAME("ReceiverCertificateThumbprint") /* .memberName */
17553 &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */
17554 offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString), /* .padding */
17555 false, /* .isArray */
17556 false /* .isOptional */
17557},};
17558
17559/* SequenceHeader */
17560static UA_DataTypeMember SequenceHeader_members[2] = {
17561{
17562 UA_TYPENAME("SequenceNumber") /* .memberName */
17563 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17564 0, /* .padding */
17565 false, /* .isArray */
17566 false /* .isOptional */
17567},
17568{
17569 UA_TYPENAME("RequestId") /* .memberName */
17570 &UA_TYPES[UA_TYPES_UINT32], /* .memberType */
17571 offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32), /* .padding */
17572 false, /* .isArray */
17573 false /* .isOptional */
17574},};
17575const UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = {
17576/* MessageType */
17577{
17578 UA_TYPENAME("MessageType") /* .typeName */
17579 {.namespaceIndex: 0, .identifierType: UA_NODEIDTYPE_NUMERIC, .identifier: {0}}, /* .typeId */
17580 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17581 sizeof(UA_MessageType), /* .memSize */
17582 UA_DATATYPEKIND_ENUM, /* .typeKind */
17583 true, /* .pointerFree */
17584 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17585 .typeId: 0, /* .membersSize */
17586 MessageType_members /* .members */
17587},
17588/* ChunkType */
17589{
17590 UA_TYPENAME("ChunkType") /* .typeName */
17591 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17592 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17593 sizeof(UA_ChunkType), /* .memSize */
17594 UA_DATATYPEKIND_ENUM, /* .typeKind */
17595 true, /* .pointerFree */
17596 UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */
17597 0, /* .membersSize */
17598 ChunkType_members /* .members */
17599},
17600/* TcpMessageHeader */
17601{
17602 UA_TYPENAME("TcpMessageHeader") /* .typeName */
17603 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17604 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17605 sizeof(UA_TcpMessageHeader), /* .memSize */
17606 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17607 true, /* .pointerFree */
17608 false, /* .overlayable */
17609 2, /* .membersSize */
17610 TcpMessageHeader_members /* .members */
17611},
17612/* TcpHelloMessage */
17613{
17614 UA_TYPENAME("TcpHelloMessage") /* .typeName */
17615 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17616 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17617 sizeof(UA_TcpHelloMessage), /* .memSize */
17618 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17619 false, /* .pointerFree */
17620 false, /* .overlayable */
17621 6, /* .membersSize */
17622 TcpHelloMessage_members /* .members */
17623},
17624/* TcpAcknowledgeMessage */
17625{
17626 UA_TYPENAME("TcpAcknowledgeMessage") /* .typeName */
17627 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17628 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17629 sizeof(UA_TcpAcknowledgeMessage), /* .memSize */
17630 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17631 true, /* .pointerFree */
17632 false, /* .overlayable */
17633 5, /* .membersSize */
17634 TcpAcknowledgeMessage_members /* .members */
17635},
17636/* TcpErrorMessage */
17637{
17638 UA_TYPENAME("TcpErrorMessage") /* .typeName */
17639 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17640 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17641 sizeof(UA_TcpErrorMessage), /* .memSize */
17642 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17643 false, /* .pointerFree */
17644 false, /* .overlayable */
17645 2, /* .membersSize */
17646 TcpErrorMessage_members /* .members */
17647},
17648/* AsymmetricAlgorithmSecurityHeader */
17649{
17650 UA_TYPENAME("AsymmetricAlgorithmSecurityHeader") /* .typeName */
17651 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17652 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17653 sizeof(UA_AsymmetricAlgorithmSecurityHeader), /* .memSize */
17654 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17655 false, /* .pointerFree */
17656 false, /* .overlayable */
17657 3, /* .membersSize */
17658 AsymmetricAlgorithmSecurityHeader_members /* .members */
17659},
17660/* SequenceHeader */
17661{
17662 UA_TYPENAME("SequenceHeader") /* .typeName */
17663 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */
17664 {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */
17665 sizeof(UA_SequenceHeader), /* .memSize */
17666 UA_DATATYPEKIND_STRUCTURE, /* .typeKind */
17667 true, /* .pointerFree */
17668 false, /* .overlayable */
17669 2, /* .membersSize */
17670 SequenceHeader_members /* .members */
17671},
17672};
17673
17674
17675/**** amalgamated original file "/build/src_generated/open62541/statuscodes.c" ****/
17676
17677/**********************************
17678 * Autogenerated -- do not modify *
17679 **********************************/
17680
17681
17682typedef struct {
17683 UA_StatusCode code;
17684 const char *name;
17685} UA_StatusCodeName;
17686
17687#ifndef UA_ENABLE_STATUSCODE_DESCRIPTIONS
17688static const char * emptyStatusCodeName = "";
17689const char * UA_StatusCode_name(UA_StatusCode code) {
17690 return emptyStatusCodeName;
17691}
17692#else
17693static const size_t statusCodeDescriptionsSize = 252;
17694static const UA_StatusCodeName statusCodeDescriptions[252] = {
17695 {UA_STATUSCODE_GOOD, "Good"},
17696 {UA_STATUSCODE_GOOD, "Good"},
17697 {UA_STATUSCODE_UNCERTAIN, "Uncertain"},
17698 {UA_STATUSCODE_BAD, "Bad"},
17699 {UA_STATUSCODE_BADUNEXPECTEDERROR, "BadUnexpectedError"},
17700 {UA_STATUSCODE_BADINTERNALERROR, "BadInternalError"},
17701 {UA_STATUSCODE_BADOUTOFMEMORY, "BadOutOfMemory"},
17702 {UA_STATUSCODE_BADRESOURCEUNAVAILABLE, "BadResourceUnavailable"},
17703 {UA_STATUSCODE_BADCOMMUNICATIONERROR, "BadCommunicationError"},
17704 {UA_STATUSCODE_BADENCODINGERROR, "BadEncodingError"},
17705 {UA_STATUSCODE_BADDECODINGERROR, "BadDecodingError"},
17706 {UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, "BadEncodingLimitsExceeded"},
17707 {UA_STATUSCODE_BADREQUESTTOOLARGE, "BadRequestTooLarge"},
17708 {UA_STATUSCODE_BADRESPONSETOOLARGE, "BadResponseTooLarge"},
17709 {UA_STATUSCODE_BADUNKNOWNRESPONSE, "BadUnknownResponse"},
17710 {UA_STATUSCODE_BADTIMEOUT, "BadTimeout"},
17711 {UA_STATUSCODE_BADSERVICEUNSUPPORTED, "BadServiceUnsupported"},
17712 {UA_STATUSCODE_BADSHUTDOWN, "BadShutdown"},
17713 {UA_STATUSCODE_BADSERVERNOTCONNECTED, "BadServerNotConnected"},
17714 {UA_STATUSCODE_BADSERVERHALTED, "BadServerHalted"},
17715 {UA_STATUSCODE_BADNOTHINGTODO, "BadNothingToDo"},
17716 {UA_STATUSCODE_BADTOOMANYOPERATIONS, "BadTooManyOperations"},
17717 {UA_STATUSCODE_BADTOOMANYMONITOREDITEMS, "BadTooManyMonitoredItems"},
17718 {UA_STATUSCODE_BADDATATYPEIDUNKNOWN, "BadDataTypeIdUnknown"},
17719 {UA_STATUSCODE_BADCERTIFICATEINVALID, "BadCertificateInvalid"},
17720 {UA_STATUSCODE_BADSECURITYCHECKSFAILED, "BadSecurityChecksFailed"},
17721 {UA_STATUSCODE_BADCERTIFICATEPOLICYCHECKFAILED, "BadCertificatePolicyCheckFailed"},
17722 {UA_STATUSCODE_BADCERTIFICATETIMEINVALID, "BadCertificateTimeInvalid"},
17723 {UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID, "BadCertificateIssuerTimeInvalid"},
17724 {UA_STATUSCODE_BADCERTIFICATEHOSTNAMEINVALID, "BadCertificateHostNameInvalid"},
17725 {UA_STATUSCODE_BADCERTIFICATEURIINVALID, "BadCertificateUriInvalid"},
17726 {UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED, "BadCertificateUseNotAllowed"},
17727 {UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED, "BadCertificateIssuerUseNotAllowed"},
17728 {UA_STATUSCODE_BADCERTIFICATEUNTRUSTED, "BadCertificateUntrusted"},
17729 {UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN, "BadCertificateRevocationUnknown"},
17730 {UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN, "BadCertificateIssuerRevocationUnknown"},
17731 {UA_STATUSCODE_BADCERTIFICATEREVOKED, "BadCertificateRevoked"},
17732 {UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED, "BadCertificateIssuerRevoked"},
17733 {UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE, "BadCertificateChainIncomplete"},
17734 {UA_STATUSCODE_BADUSERACCESSDENIED, "BadUserAccessDenied"},
17735 {UA_STATUSCODE_BADIDENTITYTOKENINVALID, "BadIdentityTokenInvalid"},
17736 {UA_STATUSCODE_BADIDENTITYTOKENREJECTED, "BadIdentityTokenRejected"},
17737 {UA_STATUSCODE_BADSECURECHANNELIDINVALID, "BadSecureChannelIdInvalid"},
17738 {UA_STATUSCODE_BADINVALIDTIMESTAMP, "BadInvalidTimestamp"},
17739 {UA_STATUSCODE_BADNONCEINVALID, "BadNonceInvalid"},
17740 {UA_STATUSCODE_BADSESSIONIDINVALID, "BadSessionIdInvalid"},
17741 {UA_STATUSCODE_BADSESSIONCLOSED, "BadSessionClosed"},
17742 {UA_STATUSCODE_BADSESSIONNOTACTIVATED, "BadSessionNotActivated"},
17743 {UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID, "BadSubscriptionIdInvalid"},
17744 {UA_STATUSCODE_BADREQUESTHEADERINVALID, "BadRequestHeaderInvalid"},
17745 {UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID, "BadTimestampsToReturnInvalid"},
17746 {UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT, "BadRequestCancelledByClient"},
17747 {UA_STATUSCODE_BADTOOMANYARGUMENTS, "BadTooManyArguments"},
17748 {UA_STATUSCODE_BADLICENSEEXPIRED, "BadLicenseExpired"},
17749 {UA_STATUSCODE_BADLICENSELIMITSEXCEEDED, "BadLicenseLimitsExceeded"},
17750 {UA_STATUSCODE_BADLICENSENOTAVAILABLE, "BadLicenseNotAvailable"},
17751 {UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED, "GoodSubscriptionTransferred"},
17752 {UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY, "GoodCompletesAsynchronously"},
17753 {UA_STATUSCODE_GOODOVERLOAD, "GoodOverload"},
17754 {UA_STATUSCODE_GOODCLAMPED, "GoodClamped"},
17755 {UA_STATUSCODE_BADNOCOMMUNICATION, "BadNoCommunication"},
17756 {UA_STATUSCODE_BADWAITINGFORINITIALDATA, "BadWaitingForInitialData"},
17757 {UA_STATUSCODE_BADNODEIDINVALID, "BadNodeIdInvalid"},
17758 {UA_STATUSCODE_BADNODEIDUNKNOWN, "BadNodeIdUnknown"},
17759 {UA_STATUSCODE_BADATTRIBUTEIDINVALID, "BadAttributeIdInvalid"},
17760 {UA_STATUSCODE_BADINDEXRANGEINVALID, "BadIndexRangeInvalid"},
17761 {UA_STATUSCODE_BADINDEXRANGENODATA, "BadIndexRangeNoData"},
17762 {UA_STATUSCODE_BADDATAENCODINGINVALID, "BadDataEncodingInvalid"},
17763 {UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED, "BadDataEncodingUnsupported"},
17764 {UA_STATUSCODE_BADNOTREADABLE, "BadNotReadable"},
17765 {UA_STATUSCODE_BADNOTWRITABLE, "BadNotWritable"},
17766 {UA_STATUSCODE_BADOUTOFRANGE, "BadOutOfRange"},
17767 {UA_STATUSCODE_BADNOTSUPPORTED, "BadNotSupported"},
17768 {UA_STATUSCODE_BADNOTFOUND, "BadNotFound"},
17769 {UA_STATUSCODE_BADOBJECTDELETED, "BadObjectDeleted"},
17770 {UA_STATUSCODE_BADNOTIMPLEMENTED, "BadNotImplemented"},
17771 {UA_STATUSCODE_BADMONITORINGMODEINVALID, "BadMonitoringModeInvalid"},
17772 {UA_STATUSCODE_BADMONITOREDITEMIDINVALID, "BadMonitoredItemIdInvalid"},
17773 {UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID, "BadMonitoredItemFilterInvalid"},
17774 {UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED, "BadMonitoredItemFilterUnsupported"},
17775 {UA_STATUSCODE_BADFILTERNOTALLOWED, "BadFilterNotAllowed"},
17776 {UA_STATUSCODE_BADSTRUCTUREMISSING, "BadStructureMissing"},
17777 {UA_STATUSCODE_BADEVENTFILTERINVALID, "BadEventFilterInvalid"},
17778 {UA_STATUSCODE_BADCONTENTFILTERINVALID, "BadContentFilterInvalid"},
17779 {UA_STATUSCODE_BADFILTEROPERATORINVALID, "BadFilterOperatorInvalid"},
17780 {UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED, "BadFilterOperatorUnsupported"},
17781 {UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH, "BadFilterOperandCountMismatch"},
17782 {UA_STATUSCODE_BADFILTEROPERANDINVALID, "BadFilterOperandInvalid"},
17783 {UA_STATUSCODE_BADFILTERELEMENTINVALID, "BadFilterElementInvalid"},
17784 {UA_STATUSCODE_BADFILTERLITERALINVALID, "BadFilterLiteralInvalid"},
17785 {UA_STATUSCODE_BADCONTINUATIONPOINTINVALID, "BadContinuationPointInvalid"},
17786 {UA_STATUSCODE_BADNOCONTINUATIONPOINTS, "BadNoContinuationPoints"},
17787 {UA_STATUSCODE_BADREFERENCETYPEIDINVALID, "BadReferenceTypeIdInvalid"},
17788 {UA_STATUSCODE_BADBROWSEDIRECTIONINVALID, "BadBrowseDirectionInvalid"},
17789 {UA_STATUSCODE_BADNODENOTINVIEW, "BadNodeNotInView"},
17790 {UA_STATUSCODE_BADNUMERICOVERFLOW, "BadNumericOverflow"},
17791 {UA_STATUSCODE_BADSERVERURIINVALID, "BadServerUriInvalid"},
17792 {UA_STATUSCODE_BADSERVERNAMEMISSING, "BadServerNameMissing"},
17793 {UA_STATUSCODE_BADDISCOVERYURLMISSING, "BadDiscoveryUrlMissing"},
17794 {UA_STATUSCODE_BADSEMPAHOREFILEMISSING, "BadSempahoreFileMissing"},
17795 {UA_STATUSCODE_BADREQUESTTYPEINVALID, "BadRequestTypeInvalid"},
17796 {UA_STATUSCODE_BADSECURITYMODEREJECTED, "BadSecurityModeRejected"},
17797 {UA_STATUSCODE_BADSECURITYPOLICYREJECTED, "BadSecurityPolicyRejected"},
17798 {UA_STATUSCODE_BADTOOMANYSESSIONS, "BadTooManySessions"},
17799 {UA_STATUSCODE_BADUSERSIGNATUREINVALID, "BadUserSignatureInvalid"},
17800 {UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID, "BadApplicationSignatureInvalid"},
17801 {UA_STATUSCODE_BADNOVALIDCERTIFICATES, "BadNoValidCertificates"},
17802 {UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED, "BadIdentityChangeNotSupported"},
17803 {UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST, "BadRequestCancelledByRequest"},
17804 {UA_STATUSCODE_BADPARENTNODEIDINVALID, "BadParentNodeIdInvalid"},
17805 {UA_STATUSCODE_BADREFERENCENOTALLOWED, "BadReferenceNotAllowed"},
17806 {UA_STATUSCODE_BADNODEIDREJECTED, "BadNodeIdRejected"},
17807 {UA_STATUSCODE_BADNODEIDEXISTS, "BadNodeIdExists"},
17808 {UA_STATUSCODE_BADNODECLASSINVALID, "BadNodeClassInvalid"},
17809 {UA_STATUSCODE_BADBROWSENAMEINVALID, "BadBrowseNameInvalid"},
17810 {UA_STATUSCODE_BADBROWSENAMEDUPLICATED, "BadBrowseNameDuplicated"},
17811 {UA_STATUSCODE_BADNODEATTRIBUTESINVALID, "BadNodeAttributesInvalid"},
17812 {UA_STATUSCODE_BADTYPEDEFINITIONINVALID, "BadTypeDefinitionInvalid"},
17813 {UA_STATUSCODE_BADSOURCENODEIDINVALID, "BadSourceNodeIdInvalid"},
17814 {UA_STATUSCODE_BADTARGETNODEIDINVALID, "BadTargetNodeIdInvalid"},
17815 {UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED, "BadDuplicateReferenceNotAllowed"},
17816 {UA_STATUSCODE_BADINVALIDSELFREFERENCE, "BadInvalidSelfReference"},
17817 {UA_STATUSCODE_BADREFERENCELOCALONLY, "BadReferenceLocalOnly"},
17818 {UA_STATUSCODE_BADNODELETERIGHTS, "BadNoDeleteRights"},
17819 {UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED, "UncertainReferenceNotDeleted"},
17820 {UA_STATUSCODE_BADSERVERINDEXINVALID, "BadServerIndexInvalid"},
17821 {UA_STATUSCODE_BADVIEWIDUNKNOWN, "BadViewIdUnknown"},
17822 {UA_STATUSCODE_BADVIEWTIMESTAMPINVALID, "BadViewTimestampInvalid"},
17823 {UA_STATUSCODE_BADVIEWPARAMETERMISMATCH, "BadViewParameterMismatch"},
17824 {UA_STATUSCODE_BADVIEWVERSIONINVALID, "BadViewVersionInvalid"},
17825 {UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE, "UncertainNotAllNodesAvailable"},
17826 {UA_STATUSCODE_GOODRESULTSMAYBEINCOMPLETE, "GoodResultsMayBeIncomplete"},
17827 {UA_STATUSCODE_BADNOTTYPEDEFINITION, "BadNotTypeDefinition"},
17828 {UA_STATUSCODE_UNCERTAINREFERENCEOUTOFSERVER, "UncertainReferenceOutOfServer"},
17829 {UA_STATUSCODE_BADTOOMANYMATCHES, "BadTooManyMatches"},
17830 {UA_STATUSCODE_BADQUERYTOOCOMPLEX, "BadQueryTooComplex"},
17831 {UA_STATUSCODE_BADNOMATCH, "BadNoMatch"},
17832 {UA_STATUSCODE_BADMAXAGEINVALID, "BadMaxAgeInvalid"},
17833 {UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT, "BadSecurityModeInsufficient"},
17834 {UA_STATUSCODE_BADHISTORYOPERATIONINVALID, "BadHistoryOperationInvalid"},
17835 {UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED, "BadHistoryOperationUnsupported"},
17836 {UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT, "BadInvalidTimestampArgument"},
17837 {UA_STATUSCODE_BADWRITENOTSUPPORTED, "BadWriteNotSupported"},
17838 {UA_STATUSCODE_BADTYPEMISMATCH, "BadTypeMismatch"},
17839 {UA_STATUSCODE_BADMETHODINVALID, "BadMethodInvalid"},
17840 {UA_STATUSCODE_BADARGUMENTSMISSING, "BadArgumentsMissing"},
17841 {UA_STATUSCODE_BADNOTEXECUTABLE, "BadNotExecutable"},
17842 {UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS, "BadTooManySubscriptions"},
17843 {UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS, "BadTooManyPublishRequests"},
17844 {UA_STATUSCODE_BADNOSUBSCRIPTION, "BadNoSubscription"},
17845 {UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN, "BadSequenceNumberUnknown"},
17846 {UA_STATUSCODE_GOODRETRANSMISSIONQUEUENOTSUPPORTED, "GoodRetransmissionQueueNotSupported"},
17847 {UA_STATUSCODE_BADMESSAGENOTAVAILABLE, "BadMessageNotAvailable"},
17848 {UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE, "BadInsufficientClientProfile"},
17849 {UA_STATUSCODE_BADSTATENOTACTIVE, "BadStateNotActive"},
17850 {UA_STATUSCODE_BADALREADYEXISTS, "BadAlreadyExists"},
17851 {UA_STATUSCODE_BADTCPSERVERTOOBUSY, "BadTcpServerTooBusy"},
17852 {UA_STATUSCODE_BADTCPMESSAGETYPEINVALID, "BadTcpMessageTypeInvalid"},
17853 {UA_STATUSCODE_BADTCPSECURECHANNELUNKNOWN, "BadTcpSecureChannelUnknown"},
17854 {UA_STATUSCODE_BADTCPMESSAGETOOLARGE, "BadTcpMessageTooLarge"},
17855 {UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES, "BadTcpNotEnoughResources"},
17856 {UA_STATUSCODE_BADTCPINTERNALERROR, "BadTcpInternalError"},
17857 {UA_STATUSCODE_BADTCPENDPOINTURLINVALID, "BadTcpEndpointUrlInvalid"},
17858 {UA_STATUSCODE_BADREQUESTINTERRUPTED, "BadRequestInterrupted"},
17859 {UA_STATUSCODE_BADREQUESTTIMEOUT, "BadRequestTimeout"},
17860 {UA_STATUSCODE_BADSECURECHANNELCLOSED, "BadSecureChannelClosed"},
17861 {UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN, "BadSecureChannelTokenUnknown"},
17862 {UA_STATUSCODE_BADSEQUENCENUMBERINVALID, "BadSequenceNumberInvalid"},
17863 {UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED, "BadProtocolVersionUnsupported"},
17864 {UA_STATUSCODE_BADCONFIGURATIONERROR, "BadConfigurationError"},
17865 {UA_STATUSCODE_BADNOTCONNECTED, "BadNotConnected"},
17866 {UA_STATUSCODE_BADDEVICEFAILURE, "BadDeviceFailure"},
17867 {UA_STATUSCODE_BADSENSORFAILURE, "BadSensorFailure"},
17868 {UA_STATUSCODE_BADOUTOFSERVICE, "BadOutOfService"},
17869 {UA_STATUSCODE_BADDEADBANDFILTERINVALID, "BadDeadbandFilterInvalid"},
17870 {UA_STATUSCODE_UNCERTAINNOCOMMUNICATIONLASTUSABLEVALUE, "UncertainNoCommunicationLastUsableValue"},
17871 {UA_STATUSCODE_UNCERTAINLASTUSABLEVALUE, "UncertainLastUsableValue"},
17872 {UA_STATUSCODE_UNCERTAINSUBSTITUTEVALUE, "UncertainSubstituteValue"},
17873 {UA_STATUSCODE_UNCERTAININITIALVALUE, "UncertainInitialValue"},
17874 {UA_STATUSCODE_UNCERTAINSENSORNOTACCURATE, "UncertainSensorNotAccurate"},
17875 {UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED, "UncertainEngineeringUnitsExceeded"},
17876 {UA_STATUSCODE_UNCERTAINSUBNORMAL, "UncertainSubNormal"},
17877 {UA_STATUSCODE_GOODLOCALOVERRIDE, "GoodLocalOverride"},
17878 {UA_STATUSCODE_BADREFRESHINPROGRESS, "BadRefreshInProgress"},
17879 {UA_STATUSCODE_BADCONDITIONALREADYDISABLED, "BadConditionAlreadyDisabled"},
17880 {UA_STATUSCODE_BADCONDITIONALREADYENABLED, "BadConditionAlreadyEnabled"},
17881 {UA_STATUSCODE_BADCONDITIONDISABLED, "BadConditionDisabled"},
17882 {UA_STATUSCODE_BADEVENTIDUNKNOWN, "BadEventIdUnknown"},
17883 {UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE, "BadEventNotAcknowledgeable"},
17884 {UA_STATUSCODE_BADDIALOGNOTACTIVE, "BadDialogNotActive"},
17885 {UA_STATUSCODE_BADDIALOGRESPONSEINVALID, "BadDialogResponseInvalid"},
17886 {UA_STATUSCODE_BADCONDITIONBRANCHALREADYACKED, "BadConditionBranchAlreadyAcked"},
17887 {UA_STATUSCODE_BADCONDITIONBRANCHALREADYCONFIRMED, "BadConditionBranchAlreadyConfirmed"},
17888 {UA_STATUSCODE_BADCONDITIONALREADYSHELVED, "BadConditionAlreadyShelved"},
17889 {UA_STATUSCODE_BADCONDITIONNOTSHELVED, "BadConditionNotShelved"},
17890 {UA_STATUSCODE_BADSHELVINGTIMEOUTOFRANGE, "BadShelvingTimeOutOfRange"},
17891 {UA_STATUSCODE_BADNODATA, "BadNoData"},
17892 {UA_STATUSCODE_BADBOUNDNOTFOUND, "BadBoundNotFound"},
17893 {UA_STATUSCODE_BADBOUNDNOTSUPPORTED, "BadBoundNotSupported"},
17894 {UA_STATUSCODE_BADDATALOST, "BadDataLost"},
17895 {UA_STATUSCODE_BADDATAUNAVAILABLE, "BadDataUnavailable"},
17896 {UA_STATUSCODE_BADENTRYEXISTS, "BadEntryExists"},
17897 {UA_STATUSCODE_BADNOENTRYEXISTS, "BadNoEntryExists"},
17898 {UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED, "BadTimestampNotSupported"},
17899 {UA_STATUSCODE_GOODENTRYINSERTED, "GoodEntryInserted"},
17900 {UA_STATUSCODE_GOODENTRYREPLACED, "GoodEntryReplaced"},
17901 {UA_STATUSCODE_UNCERTAINDATASUBNORMAL, "UncertainDataSubNormal"},
17902 {UA_STATUSCODE_GOODNODATA, "GoodNoData"},
17903 {UA_STATUSCODE_GOODMOREDATA, "GoodMoreData"},
17904 {UA_STATUSCODE_BADAGGREGATELISTMISMATCH, "BadAggregateListMismatch"},
17905 {UA_STATUSCODE_BADAGGREGATENOTSUPPORTED, "BadAggregateNotSupported"},
17906 {UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS, "BadAggregateInvalidInputs"},
17907 {UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED, "BadAggregateConfigurationRejected"},
17908 {UA_STATUSCODE_GOODDATAIGNORED, "GoodDataIgnored"},
17909 {UA_STATUSCODE_BADREQUESTNOTALLOWED, "BadRequestNotAllowed"},
17910 {UA_STATUSCODE_BADREQUESTNOTCOMPLETE, "BadRequestNotComplete"},
17911 {UA_STATUSCODE_BADTICKETREQUIRED, "BadTicketRequired"},
17912 {UA_STATUSCODE_BADTICKETINVALID, "BadTicketInvalid"},
17913 {UA_STATUSCODE_GOODEDITED, "GoodEdited"},
17914 {UA_STATUSCODE_GOODPOSTACTIONFAILED, "GoodPostActionFailed"},
17915 {UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED, "UncertainDominantValueChanged"},
17916 {UA_STATUSCODE_GOODDEPENDENTVALUECHANGED, "GoodDependentValueChanged"},
17917 {UA_STATUSCODE_BADDOMINANTVALUECHANGED, "BadDominantValueChanged"},
17918 {UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED, "UncertainDependentValueChanged"},
17919 {UA_STATUSCODE_BADDEPENDENTVALUECHANGED, "BadDependentValueChanged"},
17920 {UA_STATUSCODE_GOODEDITED_DEPENDENTVALUECHANGED, "GoodEdited_DependentValueChanged"},
17921 {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED, "GoodEdited_DominantValueChanged"},
17922 {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "GoodEdited_DominantValueChanged_DependentValueChanged"},
17923 {UA_STATUSCODE_BADEDITED_OUTOFRANGE, "BadEdited_OutOfRange"},
17924 {UA_STATUSCODE_BADINITIALVALUE_OUTOFRANGE, "BadInitialValue_OutOfRange"},
17925 {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED, "BadOutOfRange_DominantValueChanged"},
17926 {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged"},
17927 {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadOutOfRange_DominantValueChanged_DependentValueChanged"},
17928 {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged"},
17929 {UA_STATUSCODE_GOODCOMMUNICATIONEVENT, "GoodCommunicationEvent"},
17930 {UA_STATUSCODE_GOODSHUTDOWNEVENT, "GoodShutdownEvent"},
17931 {UA_STATUSCODE_GOODCALLAGAIN, "GoodCallAgain"},
17932 {UA_STATUSCODE_GOODNONCRITICALTIMEOUT, "GoodNonCriticalTimeout"},
17933 {UA_STATUSCODE_BADINVALIDARGUMENT, "BadInvalidArgument"},
17934 {UA_STATUSCODE_BADCONNECTIONREJECTED, "BadConnectionRejected"},
17935 {UA_STATUSCODE_BADDISCONNECT, "BadDisconnect"},
17936 {UA_STATUSCODE_BADCONNECTIONCLOSED, "BadConnectionClosed"},
17937 {UA_STATUSCODE_BADINVALIDSTATE, "BadInvalidState"},
17938 {UA_STATUSCODE_BADENDOFSTREAM, "BadEndOfStream"},
17939 {UA_STATUSCODE_BADNODATAAVAILABLE, "BadNoDataAvailable"},
17940 {UA_STATUSCODE_BADWAITINGFORRESPONSE, "BadWaitingForResponse"},
17941 {UA_STATUSCODE_BADOPERATIONABANDONED, "BadOperationAbandoned"},
17942 {UA_STATUSCODE_BADEXPECTEDSTREAMTOBLOCK, "BadExpectedStreamToBlock"},
17943 {UA_STATUSCODE_BADWOULDBLOCK, "BadWouldBlock"},
17944 {UA_STATUSCODE_BADSYNTAXERROR, "BadSyntaxError"},
17945 {UA_STATUSCODE_BADMAXCONNECTIONSREACHED, "BadMaxConnectionsReached"},
17946 {0xffffffff, "Unknown StatusCode"}
17947};
17948
17949const char * UA_StatusCode_name(UA_StatusCode code) {
17950 for (size_t i = 0; i < statusCodeDescriptionsSize; ++i) {
17951 if (UA_StatusCode_isEqualTop(s1: statusCodeDescriptions[i].code,s2: code))
17952 return statusCodeDescriptions[i].name;
17953 }
17954 return statusCodeDescriptions[statusCodeDescriptionsSize-1].name;
17955}
17956
17957#endif
17958
17959/**** amalgamated original file "/src/ua_util.c" ****/
17960
17961/* This Source Code Form is subject to the terms of the Mozilla Public
17962 * License, v. 2.0. If a copy of the MPL was not distributed with this
17963 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
17964 *
17965 * Copyright 2014, 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
17966 * Copyright 2014 (c) Florian Palm
17967 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
17968 */
17969
17970
17971
17972size_t
17973UA_readNumberWithBase(const UA_Byte *buf, size_t buflen, UA_UInt32 *number, UA_Byte base) {
17974 UA_assert(buf);
17975 UA_assert(number);
17976 u32 n = 0;
17977 size_t progress = 0;
17978 /* read numbers until the end or a non-number character appears */
17979 while(progress < buflen) {
17980 u8 c = buf[progress];
17981 if(c >= '0' && c <= '9' && c <= '0' + (base-1))
17982 n = (n * base) + c - '0';
17983 else if(base > 9 && c >= 'a' && c <= 'z' && c <= 'a' + (base-11))
17984 n = (n * base) + c-'a' + 10;
17985 else if(base > 9 && c >= 'A' && c <= 'Z' && c <= 'A' + (base-11))
17986 n = (n * base) + c-'A' + 10;
17987 else
17988 break;
17989 ++progress;
17990 }
17991 *number = n;
17992 return progress;
17993}
17994
17995size_t
17996UA_readNumber(const UA_Byte *buf, size_t buflen, UA_UInt32 *number) {
17997 return UA_readNumberWithBase(buf, buflen, number, base: 10);
17998}
17999
18000UA_StatusCode
18001UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
18002 u16 *outPort, UA_String *outPath) {
18003 UA_Boolean ipv6 = false;
18004
18005 /* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */
18006 if(endpointUrl->length < 11) {
18007 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18008 }
18009 if (strncmp(s1: (char*)endpointUrl->data, s2: "opc.tcp://", n: 10) != 0) {
18010#ifdef UA_ENABLE_PUBSUB
18011 if (strncmp((char*)endpointUrl->data, "opc.udp://", 10) != 0 &&
18012 strncmp((char*)endpointUrl->data, "opc.mqtt://", 11) != 0) {
18013 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18014 }
18015#else
18016 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18017#endif
18018 }
18019
18020 /* Where does the hostname end? */
18021 size_t curr = 10;
18022 if(endpointUrl->data[curr] == '[') {
18023 /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */
18024 for(; curr < endpointUrl->length; ++curr) {
18025 if(endpointUrl->data[curr] == ']')
18026 break;
18027 }
18028 if(curr == endpointUrl->length)
18029 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18030 curr++;
18031 ipv6 = true;
18032 } else {
18033 /* IPv4 or hostname: opc.tcp://something.something:1234/path */
18034 for(; curr < endpointUrl->length; ++curr) {
18035 if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/')
18036 break;
18037 }
18038 }
18039
18040 /* Set the hostname */
18041 if(ipv6) {
18042 /* Skip the ipv6 '[]' container for getaddrinfo() later */
18043 outHostname->data = &endpointUrl->data[11];
18044 outHostname->length = curr - 12;
18045 } else {
18046 outHostname->data = &endpointUrl->data[10];
18047 outHostname->length = curr - 10;
18048 }
18049
18050 /* Empty string? */
18051 if(outHostname->length == 0)
18052 outHostname->data = NULL;
18053
18054 if(curr == endpointUrl->length)
18055 return UA_STATUSCODE_GOOD;
18056
18057 /* Set the port */
18058 if(endpointUrl->data[curr] == ':') {
18059 if(++curr == endpointUrl->length)
18060 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18061 u32 largeNum;
18062 size_t progress = UA_readNumber(buf: &endpointUrl->data[curr],
18063 buflen: endpointUrl->length - curr, number: &largeNum);
18064 if(progress == 0 || largeNum > 65535)
18065 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18066 /* Test if the end of a valid port was reached */
18067 curr += progress;
18068 if(curr == endpointUrl->length || endpointUrl->data[curr] == '/')
18069 *outPort = (u16)largeNum;
18070 if(curr == endpointUrl->length)
18071 return UA_STATUSCODE_GOOD;
18072 }
18073
18074 /* Set the path */
18075 UA_assert(curr < endpointUrl->length);
18076 if(endpointUrl->data[curr] != '/')
18077 return UA_STATUSCODE_BADTCPENDPOINTURLINVALID;
18078 if(++curr == endpointUrl->length)
18079 return UA_STATUSCODE_GOOD;
18080 outPath->data = &endpointUrl->data[curr];
18081 outPath->length = endpointUrl->length - curr;
18082
18083 /* Remove trailing slash from the path */
18084 if(endpointUrl->data[endpointUrl->length - 1] == '/')
18085 outPath->length--;
18086
18087 /* Empty string? */
18088 if(outPath->length == 0)
18089 outPath->data = NULL;
18090
18091 return UA_STATUSCODE_GOOD;
18092}
18093
18094UA_StatusCode
18095UA_parseEndpointUrlEthernet(const UA_String *endpointUrl, UA_String *target,
18096 UA_UInt16 *vid, UA_Byte *pcp) {
18097 /* Url must begin with "opc.eth://" */
18098 if(endpointUrl->length < 11) {
18099 return UA_STATUSCODE_BADINTERNALERROR;
18100 }
18101 if(strncmp(s1: (char*) endpointUrl->data, s2: "opc.eth://", n: 10) != 0) {
18102 return UA_STATUSCODE_BADINTERNALERROR;
18103 }
18104
18105 /* Where does the host address end? */
18106 size_t curr = 10;
18107 for(; curr < endpointUrl->length; ++curr) {
18108 if(endpointUrl->data[curr] == ':') {
18109 break;
18110 }
18111 }
18112
18113 /* set host address */
18114 target->data = &endpointUrl->data[10];
18115 target->length = curr - 10;
18116 if(curr == endpointUrl->length) {
18117 return UA_STATUSCODE_GOOD;
18118 }
18119
18120 /* Set VLAN */
18121 u32 value = 0;
18122 curr++; /* skip ':' */
18123 size_t progress = UA_readNumber(buf: &endpointUrl->data[curr],
18124 buflen: endpointUrl->length - curr, number: &value);
18125 if(progress == 0 || value > 4096) {
18126 return UA_STATUSCODE_BADINTERNALERROR;
18127 }
18128 curr += progress;
18129 if(curr == endpointUrl->length || endpointUrl->data[curr] == '.') {
18130 *vid = (UA_UInt16) value;
18131 }
18132 if(curr == endpointUrl->length) {
18133 return UA_STATUSCODE_GOOD;
18134 }
18135
18136 /* Set priority */
18137 if(endpointUrl->data[curr] != '.') {
18138 return UA_STATUSCODE_BADINTERNALERROR;
18139 }
18140 curr++; /* skip '.' */
18141 progress = UA_readNumber(buf: &endpointUrl->data[curr],
18142 buflen: endpointUrl->length - curr, number: &value);
18143 if(progress == 0 || value > 7) {
18144 return UA_STATUSCODE_BADINTERNALERROR;
18145 }
18146 curr += progress;
18147 if(curr != endpointUrl->length) {
18148 return UA_STATUSCODE_BADINTERNALERROR;
18149 }
18150 *pcp = (UA_Byte) value;
18151
18152 return UA_STATUSCODE_GOOD;
18153}
18154
18155UA_StatusCode
18156UA_ByteString_toBase64(const UA_ByteString *byteString,
18157 UA_String *str) {
18158 UA_String_init(p: str);
18159 if(!byteString || !byteString->data)
18160 return UA_STATUSCODE_GOOD;
18161
18162 str->data = (UA_Byte*)
18163 UA_base64(src: byteString->data, len: byteString->length, out_len: &str->length);
18164 if(!str->data)
18165 return UA_STATUSCODE_BADOUTOFMEMORY;
18166
18167 return UA_STATUSCODE_GOOD;
18168}
18169
18170UA_StatusCode UA_EXPORT
18171UA_ByteString_fromBase64(UA_ByteString *bs,
18172 const UA_String *input) {
18173 UA_ByteString_init(p: bs);
18174 if(input->length == 0)
18175 return UA_STATUSCODE_GOOD;
18176 bs->data = UA_unbase64(src: (const unsigned char*)input->data,
18177 len: input->length, out_len: &bs->length);
18178 /* TODO: Differentiate between encoding and memory errors */
18179 if(!bs->data)
18180 return UA_STATUSCODE_BADINTERNALERROR;
18181 return UA_STATUSCODE_GOOD;
18182}
18183
18184/* Key Value Map */
18185
18186UA_StatusCode
18187UA_KeyValueMap_setQualified(UA_KeyValuePair **map, size_t *mapSize,
18188 const UA_QualifiedName *key,
18189 const UA_Variant *value) {
18190 /* Parameter exists already */
18191 const UA_Variant *v = UA_KeyValueMap_getQualified(map: *map, mapSize: *mapSize, key);
18192 if(v) {
18193 UA_Variant copyV;
18194 UA_StatusCode res = UA_Variant_copy(src: v, dst: &copyV);
18195 if(res != UA_STATUSCODE_GOOD)
18196 return res;
18197 UA_Variant *target = (UA_Variant*)(uintptr_t)v;
18198 UA_Variant_clear(p: target);
18199 *target = copyV;
18200 return UA_STATUSCODE_GOOD;
18201 }
18202
18203 /* Append to the array */
18204 UA_KeyValuePair pair;
18205 pair.key = *key;
18206 pair.value = *value;
18207 return UA_Array_appendCopy(p: (void**)map, size: mapSize, newElem: &pair,
18208 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
18209}
18210
18211UA_StatusCode
18212UA_KeyValueMap_set(UA_KeyValuePair **map, size_t *mapSize,
18213 const char *key, const UA_Variant *value) {
18214 UA_QualifiedName qnKey;
18215 qnKey.namespaceIndex = 0;
18216 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18217 return UA_KeyValueMap_setQualified(map, mapSize, key: &qnKey, value);
18218}
18219
18220const UA_Variant *
18221UA_KeyValueMap_getQualified(UA_KeyValuePair *map, size_t mapSize,
18222 const UA_QualifiedName *key) {
18223 for(size_t i = 0; i < mapSize; i++) {
18224 if(map[i].key.namespaceIndex == key->namespaceIndex &&
18225 UA_String_equal(s1: &map[i].key.name, s2: &key->name))
18226 return &map[i].value;
18227
18228 }
18229 return NULL;
18230}
18231
18232const UA_Variant *
18233UA_KeyValueMap_get(UA_KeyValuePair *map, size_t mapSize,
18234 const char *key) {
18235 UA_QualifiedName qnKey;
18236 qnKey.namespaceIndex = 0;
18237 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18238 return UA_KeyValueMap_getQualified(map, mapSize, key: &qnKey);
18239}
18240
18241/* Returns NULL if the parameter is not defined or not of the right datatype */
18242const UA_Variant *
18243UA_KeyValueMap_getScalar(UA_KeyValuePair *map, size_t mapSize,
18244 const char *key, const UA_DataType *type) {
18245 const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
18246 if(!v || !UA_Variant_hasScalarType(v, type))
18247 return NULL;
18248 return v;
18249}
18250
18251const UA_Variant *
18252UA_KeyValueMap_getArray(UA_KeyValuePair *map, size_t mapSize,
18253 const char *key, const UA_DataType *type) {
18254 const UA_Variant *v = UA_KeyValueMap_get(map, mapSize, key);
18255 if(!v || !UA_Variant_hasArrayType(v, type))
18256 return NULL;
18257 return v;
18258}
18259
18260void
18261UA_KeyValueMap_deleteQualified(UA_KeyValuePair **map, size_t *mapSize,
18262 const UA_QualifiedName *key) {
18263 UA_KeyValuePair *m = *map;
18264 size_t s = *mapSize;
18265 for(size_t i = 0; i < s; i++) {
18266 if(m[i].key.namespaceIndex != key->namespaceIndex ||
18267 !UA_String_equal(s1: &m[i].key.name, s2: &key->name))
18268 continue;
18269
18270 /* Clean the pair */
18271 UA_KeyValuePair_clear(p: &m[i]);
18272
18273 /* Move the last pair to fill the empty slot */
18274 if(s > 1 && i < s - 1) {
18275 m[i] = m[s-1];
18276 UA_KeyValuePair_init(p: &m[s-1]);
18277 }
18278
18279 UA_StatusCode res = UA_Array_resize(p: (void**)map, size: mapSize, newSize: *mapSize-1,
18280 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
18281 (void)res;
18282 *mapSize = s - 1; /* In case resize fails, keep the longer original
18283 * array around. Resize never fails when reducing
18284 * the size to zero. Reduce the size integer in
18285 * any case. */
18286 return;
18287 }
18288}
18289
18290void
18291UA_KeyValueMap_delete(UA_KeyValuePair **map, size_t *mapSize,
18292 const char *key) {
18293 UA_QualifiedName qnKey;
18294 qnKey.namespaceIndex = 0;
18295 qnKey.name = UA_STRING(chars: (char*)(uintptr_t)key);
18296 UA_KeyValueMap_deleteQualified(map, mapSize, key: &qnKey);
18297}
18298
18299/**** amalgamated original file "/src/ua_timer.c" ****/
18300
18301/* This Source Code Form is subject to the terms of the Mozilla Public
18302 * License, v. 2.0. If a copy of the MPL was not distributed with this
18303 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18304 *
18305 * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18306 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
18307 */
18308
18309
18310/* There may be several entries with the same nextTime in the tree. We give them
18311 * an absolute order by considering the memory address to break ties. Because of
18312 * this, the nextTime property cannot be used to lookup specific entries. */
18313static enum aa_cmp
18314cmpDateTime(const UA_DateTime *a, const UA_DateTime *b) {
18315 if(*a < *b)
18316 return AA_CMP_LESS;
18317 if(*a > *b)
18318 return AA_CMP_MORE;
18319 if(a == b)
18320 return AA_CMP_EQ;
18321 if(a < b)
18322 return AA_CMP_LESS;
18323 return AA_CMP_MORE;
18324}
18325
18326/* The identifiers of entries are unique */
18327static enum aa_cmp
18328cmpId(const UA_UInt64 *a, const UA_UInt64 *b) {
18329 if(*a < *b)
18330 return AA_CMP_LESS;
18331 if(*a == *b)
18332 return AA_CMP_EQ;
18333 return AA_CMP_MORE;
18334}
18335
18336static UA_DateTime
18337calculateNextTime(UA_DateTime currentTime, UA_DateTime baseTime,
18338 UA_DateTime interval) {
18339 /* Take the difference between current and base time */
18340 UA_DateTime diffCurrentTimeBaseTime = currentTime - baseTime;
18341
18342 /* Take modulo of the diff time with the interval. This is the duration we
18343 * are already "into" the current interval. Subtract it from (current +
18344 * interval) to get the next execution time. */
18345 UA_DateTime cycleDelay = diffCurrentTimeBaseTime % interval;
18346
18347 /* Handle the special case where the baseTime is in the future */
18348 if(UA_UNLIKELY(cycleDelay < 0))
18349 cycleDelay += interval;
18350
18351 return currentTime + interval - cycleDelay;
18352}
18353
18354void
18355UA_Timer_init(UA_Timer *t) {
18356 memset(s: t, c: 0, n: sizeof(UA_Timer));
18357 aa_init(head: &t->root,
18358 cmp: (enum aa_cmp (*)(const void*, const void*))cmpDateTime,
18359 offsetof(UA_TimerEntry, treeEntry),
18360 offsetof(UA_TimerEntry, nextTime));
18361 aa_init(head: &t->idRoot,
18362 cmp: (enum aa_cmp (*)(const void*, const void*))cmpId,
18363 offsetof(UA_TimerEntry, idTreeEntry),
18364 offsetof(UA_TimerEntry, id));
18365 UA_LOCK_INIT(&t->timerMutex);
18366}
18367
18368void
18369UA_Timer_addTimerEntry(UA_Timer *t, UA_TimerEntry *te, UA_UInt64 *callbackId) {
18370 UA_LOCK(&t->timerMutex);
18371 te->id = ++t->idCounter;
18372 if(callbackId)
18373 *callbackId = te->id;
18374 aa_insert(head: &t->root, elem: te);
18375 aa_insert(head: &t->idRoot, elem: te);
18376 UA_UNLOCK(&t->timerMutex);
18377}
18378
18379static UA_StatusCode
18380addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application,
18381 void *data, UA_DateTime nextTime, UA_UInt64 interval,
18382 UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
18383 /* A callback method needs to be present */
18384 if(!callback)
18385 return UA_STATUSCODE_BADINTERNALERROR;
18386
18387 /* Allocate the repeated callback structure */
18388 UA_TimerEntry *te = (UA_TimerEntry*)UA_malloc(size: sizeof(UA_TimerEntry));
18389 if(!te)
18390 return UA_STATUSCODE_BADOUTOFMEMORY;
18391
18392 /* Set the repeated callback */
18393 te->interval = (UA_UInt64)interval;
18394 te->id = ++t->idCounter;
18395 te->callback = callback;
18396 te->application = application;
18397 te->data = data;
18398 te->nextTime = nextTime;
18399 te->timerPolicy = timerPolicy;
18400
18401 /* Set the output identifier */
18402 if(callbackId)
18403 *callbackId = te->id;
18404
18405 aa_insert(head: &t->root, elem: te);
18406 aa_insert(head: &t->idRoot, elem: te);
18407 return UA_STATUSCODE_GOOD;
18408}
18409
18410UA_StatusCode
18411UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback,
18412 void *application, void *data, UA_DateTime date,
18413 UA_UInt64 *callbackId) {
18414 UA_LOCK(&t->timerMutex);
18415 UA_StatusCode res = addCallback(t, callback, application, data, nextTime: date,
18416 interval: 0, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
18417 callbackId);
18418 UA_UNLOCK(&t->timerMutex);
18419 return res;
18420}
18421
18422/* Adding repeated callbacks: Add an entry with the "nextTime" timestamp in the
18423 * future. This will be picked up in the next iteration and inserted at the
18424 * correct place. So that the next execution takes place ät "nextTime". */
18425UA_StatusCode
18426UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback,
18427 void *application, void *data, UA_Double interval_ms,
18428 UA_DateTime *baseTime, UA_TimerPolicy timerPolicy,
18429 UA_UInt64 *callbackId) {
18430 /* The interval needs to be positive */
18431 if(interval_ms <= 0.0)
18432 return UA_STATUSCODE_BADINTERNALERROR;
18433 UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
18434 if(interval == 0)
18435 return UA_STATUSCODE_BADINTERNALERROR;
18436
18437 /* Compute the first time for execution */
18438 UA_DateTime currentTime = UA_DateTime_nowMonotonic();
18439 UA_DateTime nextTime;
18440 if(baseTime == NULL) {
18441 /* Use "now" as the basetime */
18442 nextTime = currentTime + (UA_DateTime)interval;
18443 } else {
18444 nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval);
18445 }
18446
18447 UA_LOCK(&t->timerMutex);
18448 UA_StatusCode res = addCallback(t, callback, application, data, nextTime,
18449 interval, timerPolicy, callbackId);
18450 UA_UNLOCK(&t->timerMutex);
18451 return res;
18452}
18453
18454UA_StatusCode
18455UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId,
18456 UA_Double interval_ms, UA_DateTime *baseTime,
18457 UA_TimerPolicy timerPolicy) {
18458 /* The interval needs to be positive */
18459 if(interval_ms <= 0.0)
18460 return UA_STATUSCODE_BADINTERNALERROR;
18461 UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC);
18462 if(interval == 0)
18463 return UA_STATUSCODE_BADINTERNALERROR;
18464
18465 UA_LOCK(&t->timerMutex);
18466
18467 /* Remove from the sorted tree */
18468 UA_TimerEntry *te = (UA_TimerEntry*)aa_find(head: &t->idRoot, key: &callbackId);
18469 if(!te) {
18470 UA_UNLOCK(&t->timerMutex);
18471 return UA_STATUSCODE_BADNOTFOUND;
18472 }
18473 aa_remove(head: &t->root, elem: te);
18474
18475 /* Compute the next time for execution. The logic is identical to the
18476 * creation of a new repeated callback. */
18477 UA_DateTime currentTime = UA_DateTime_nowMonotonic();
18478 if(baseTime == NULL) {
18479 /* Use "now" as the basetime */
18480 te->nextTime = currentTime + (UA_DateTime)interval;
18481 } else {
18482 te->nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval);
18483 }
18484
18485 /* Update the remaining parameters and re-insert */
18486 te->interval = interval;
18487 te->timerPolicy = timerPolicy;
18488 aa_insert(head: &t->root, elem: te);
18489
18490 UA_UNLOCK(&t->timerMutex);
18491 return UA_STATUSCODE_GOOD;
18492}
18493
18494void
18495UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId) {
18496 UA_LOCK(&t->timerMutex);
18497 UA_TimerEntry *te = (UA_TimerEntry*)aa_find(head: &t->idRoot, key: &callbackId);
18498 if(UA_LIKELY(te != NULL)) {
18499 aa_remove(head: &t->root, elem: te);
18500 aa_remove(head: &t->idRoot, elem: te);
18501 UA_free(ptr: te);
18502 }
18503 UA_UNLOCK(&t->timerMutex);
18504}
18505
18506UA_DateTime
18507UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic,
18508 UA_TimerExecutionCallback executionCallback,
18509 void *executionApplication) {
18510 UA_LOCK(&t->timerMutex);
18511 UA_TimerEntry *first;
18512 while((first = (UA_TimerEntry*)aa_min(head: &t->root)) &&
18513 first->nextTime <= nowMonotonic) {
18514 aa_remove(head: &t->root, elem: first);
18515
18516 /* Reinsert / remove to their new position first. Because the callback
18517 * can interact with the zip tree and expects the same entries in the
18518 * root and idRoot trees. */
18519
18520 if(first->interval == 0) {
18521 aa_remove(head: &t->idRoot, elem: first);
18522 if(first->callback) {
18523 UA_UNLOCK(&t->timerMutex);
18524 executionCallback(executionApplication, first->callback,
18525 first->application, first->data);
18526 UA_LOCK(&t->timerMutex);
18527 }
18528 UA_free(ptr: first);
18529 continue;
18530 }
18531
18532 /* Set the time for the next execution. Prevent an infinite loop by
18533 * forcing the execution time in the next iteration.
18534 *
18535 * If the timer policy is "CurrentTime", then there is at least the
18536 * interval between executions. This is used for Monitoreditems, for
18537 * which the spec says: The sampling interval indicates the fastest rate
18538 * at which the Server should sample its underlying source for data
18539 * changes. (Part 4, 5.12.1.2) */
18540 first->nextTime += (UA_DateTime)first->interval;
18541 if(first->nextTime < nowMonotonic) {
18542 if(first->timerPolicy == UA_TIMER_HANDLE_CYCLEMISS_WITH_BASETIME)
18543 first->nextTime = calculateNextTime(currentTime: nowMonotonic, baseTime: first->nextTime,
18544 interval: (UA_DateTime)first->interval);
18545 else
18546 first->nextTime = nowMonotonic + (UA_DateTime)first->interval;
18547 }
18548
18549 aa_insert(head: &t->root, elem: first);
18550
18551 if(!first->callback)
18552 continue;
18553
18554 /* Unlock the mutes before dropping into the callback. So that the timer
18555 * itself can be edited within the callback. When we return, only the
18556 * pointer to t must still exist. */
18557 UA_ApplicationCallback cb = first->callback;
18558 void *app = first->application;
18559 void *data = first->data;
18560 UA_UNLOCK(&t->timerMutex);
18561 executionCallback(executionApplication, cb, app, data);
18562 UA_LOCK(&t->timerMutex);
18563 }
18564
18565 /* Return the timestamp of the earliest next callback */
18566 first = (UA_TimerEntry*)aa_min(head: &t->root);
18567 UA_DateTime next = (first) ? first->nextTime : UA_INT64_MAX;
18568 if(next < nowMonotonic)
18569 next = nowMonotonic;
18570 UA_UNLOCK(&t->timerMutex);
18571 return next;
18572}
18573
18574void
18575UA_Timer_clear(UA_Timer *t) {
18576 UA_LOCK(&t->timerMutex);
18577
18578 /* Free all entries */
18579 UA_TimerEntry *top;
18580 while((top = (UA_TimerEntry*)aa_min(head: &t->idRoot))) {
18581 aa_remove(head: &t->idRoot, elem: top);
18582 UA_free(ptr: top);
18583 }
18584
18585 /* Reset the trees to avoid future access */
18586 t->root.root = NULL;
18587 t->idRoot.root = NULL;
18588
18589 UA_UNLOCK(&t->timerMutex);
18590#if UA_MULTITHREADING >= 100
18591 UA_LOCK_DESTROY(&t->timerMutex);
18592#endif
18593}
18594
18595/**** amalgamated original file "/src/ua_connection.c" ****/
18596
18597/* This Source Code Form is subject to the terms of the Mozilla Public
18598 * License, v. 2.0. If a copy of the MPL was not distributed with this
18599 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18600 *
18601 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18602 * Copyright 2014, 2016-2017 (c) Florian Palm
18603 * Copyright 2015-2016 (c) Sten Grüner
18604 * Copyright 2015 (c) Oleksiy Vasylyev
18605 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
18606 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
18607 * Copyright 2019 (c) Kalycito Infotech Private Limited
18608 */
18609
18610
18611
18612/* Hides some errors before sending them to a client according to the
18613 * standard. */
18614static void
18615hideErrors(UA_TcpErrorMessage *const error) {
18616 switch(error->error) {
18617 case UA_STATUSCODE_BADCERTIFICATEUNTRUSTED:
18618 case UA_STATUSCODE_BADCERTIFICATEREVOKED:
18619 error->error = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
18620 error->reason = UA_STRING_NULL;
18621 break;
18622 // TODO: Check if these are all cases that need to be covered.
18623 default:
18624 break;
18625 }
18626}
18627
18628void
18629UA_Connection_sendError(UA_Connection *connection, UA_TcpErrorMessage *error) {
18630 hideErrors(error);
18631
18632 UA_TcpMessageHeader header;
18633 header.messageTypeAndChunkType = UA_MESSAGETYPE_ERR + UA_CHUNKTYPE_FINAL;
18634 // Header + ErrorMessage (error + reasonLength_field + length)
18635 header.messageSize = 8 + (4 + 4 + (UA_UInt32)error->reason.length);
18636
18637 /* Get the send buffer from the network layer */
18638 UA_ByteString msg = UA_BYTESTRING_NULL;
18639 UA_StatusCode retval = connection->getSendBuffer(connection, header.messageSize, &msg);
18640 if(retval != UA_STATUSCODE_GOOD)
18641 return;
18642
18643 /* Encode and send the response */
18644 UA_Byte *bufPos = msg.data;
18645 const UA_Byte *bufEnd = &msg.data[msg.length];
18646 retval |= UA_encodeBinaryInternal(src: &header,
18647 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
18648 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
18649 retval |= UA_encodeBinaryInternal(src: error,
18650 type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE],
18651 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
18652 (void)retval; /* Encoding of these cannot fail */
18653 msg.length = header.messageSize;
18654 connection->send(connection, &msg);
18655}
18656
18657void UA_Connection_detachSecureChannel(UA_Connection *connection) {
18658 UA_SecureChannel *channel = connection->channel;
18659 if(channel)
18660 /* only replace when the channel points to this connection */
18661 UA_atomic_cmpxchg(addr: (void**)&channel->connection, expected: connection, NULL);
18662 UA_atomic_xchg(addr: (void**)&connection->channel, NULL);
18663}
18664
18665// TODO: Return an error code
18666void
18667UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
18668 if(UA_atomic_cmpxchg(addr: (void**)&channel->connection, NULL, newptr: connection) == NULL)
18669 UA_atomic_xchg(addr: (void**)&connection->channel, newptr: (void*)channel);
18670}
18671
18672/**** amalgamated original file "/src/ua_securechannel.c" ****/
18673
18674/* This Source Code Form is subject to the terms of the Mozilla Public
18675 * License, v. 2.0. If a copy of the MPL was not distributed with this
18676 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
18677 *
18678 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
18679 * Copyright 2014, 2016-2017 (c) Florian Palm
18680 * Copyright 2015-2016 (c) Sten Grüner
18681 * Copyright 2015 (c) Oleksiy Vasylyev
18682 * Copyright 2016 (c) TorbenD
18683 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
18684 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
18685 * Copyright 2018-2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
18686 */
18687
18688
18689
18690#define UA_BITMASK_MESSAGETYPE 0x00ffffffu
18691#define UA_BITMASK_CHUNKTYPE 0xff000000u
18692
18693const UA_String UA_SECURITY_POLICY_NONE_URI =
18694 {47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"};
18695
18696#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
18697UA_StatusCode decrypt_verifySignatureFailure;
18698UA_StatusCode sendAsym_sendFailure;
18699UA_StatusCode processSym_seqNumberFailure;
18700#endif
18701
18702void UA_SecureChannel_init(UA_SecureChannel *channel,
18703 const UA_ConnectionConfig *config) {
18704 /* Linked lists are also initialized by zeroing out */
18705 memset(s: channel, c: 0, n: sizeof(UA_SecureChannel));
18706 channel->state = UA_SECURECHANNELSTATE_FRESH;
18707 SIMPLEQ_INIT(&channel->completeChunks);
18708 SIMPLEQ_INIT(&channel->decryptedChunks);
18709 SLIST_INIT(&channel->sessions);
18710 channel->config = *config;
18711}
18712
18713UA_StatusCode
18714UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel,
18715 const UA_SecurityPolicy *securityPolicy,
18716 const UA_ByteString *remoteCertificate) {
18717 /* Is a policy already configured? */
18718 UA_CHECK_ERROR(!channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
18719 securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
18720 "Security policy already configured");
18721
18722 /* Create the context */
18723 UA_StatusCode res = securityPolicy->channelModule.
18724 newContext(securityPolicy, remoteCertificate, &channel->channelContext);
18725 res |= UA_ByteString_copy(src: remoteCertificate, dst: &channel->remoteCertificate);
18726 UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
18727 UA_LOGCATEGORY_SECURITYPOLICY,
18728 "Could not set up the SecureChannel context");
18729
18730 /* Compute the certificate thumbprint */
18731 UA_ByteString remoteCertificateThumbprint =
18732 {20, channel->remoteCertificateThumbprint};
18733 res = securityPolicy->asymmetricModule.
18734 makeCertificateThumbprint(securityPolicy, &channel->remoteCertificate,
18735 &remoteCertificateThumbprint);
18736 UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger,
18737 UA_LOGCATEGORY_SECURITYPOLICY,
18738 "Could not create the certificate thumbprint");
18739
18740 /* Set the policy */
18741 channel->securityPolicy = securityPolicy;
18742 return UA_STATUSCODE_GOOD;
18743}
18744
18745static void
18746UA_Chunk_delete(UA_Chunk *chunk) {
18747 if(chunk->copied)
18748 UA_ByteString_clear(p: &chunk->bytes);
18749 UA_free(ptr: chunk);
18750}
18751
18752static void
18753deleteChunks(UA_ChunkQueue *queue) {
18754 UA_Chunk *chunk;
18755 while((chunk = SIMPLEQ_FIRST(queue))) {
18756 SIMPLEQ_REMOVE_HEAD(queue, pointers);
18757 UA_Chunk_delete(chunk);
18758 }
18759}
18760
18761void
18762UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel) {
18763 deleteChunks(queue: &channel->completeChunks);
18764 deleteChunks(queue: &channel->decryptedChunks);
18765 UA_ByteString_clear(p: &channel->incompleteChunk);
18766}
18767
18768void
18769UA_SecureChannel_close(UA_SecureChannel *channel) {
18770 /* Set the status to closed */
18771 channel->state = UA_SECURECHANNELSTATE_CLOSED;
18772 channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
18773
18774 /* Reset the SecurityMode and config */
18775 channel->securityMode = UA_MESSAGESECURITYMODE_INVALID;
18776 memset(s: &channel->config, c: 0, n: sizeof(UA_ConnectionConfig));
18777
18778 /* Clean up the SecurityToken */
18779 UA_ChannelSecurityToken_clear(p: &channel->securityToken);
18780 UA_ChannelSecurityToken_clear(p: &channel->altSecurityToken);
18781
18782 /* Delete the channel context for the security policy */
18783 if(channel->securityPolicy) {
18784 channel->securityPolicy->channelModule.deleteContext(channel->channelContext);
18785 channel->securityPolicy = NULL;
18786 channel->channelContext = NULL;
18787 }
18788
18789 /* Detach from the connection and close the connection */
18790 if(channel->connection) {
18791 if(channel->connection->state != UA_CONNECTIONSTATE_CLOSED)
18792 channel->connection->close(channel->connection);
18793 UA_Connection_detachSecureChannel(connection: channel->connection);
18794 }
18795
18796 /* Clean up certificate and nonces */
18797 UA_ByteString_clear(p: &channel->remoteCertificate);
18798 UA_ByteString_clear(p: &channel->localNonce);
18799 UA_ByteString_clear(p: &channel->remoteNonce);
18800
18801 /* Reset the sequence numbers */
18802 channel->receiveSequenceNumber = 0;
18803 channel->sendSequenceNumber = 0;
18804
18805 /* Detach Sessions from the SecureChannel. This also removes outstanding
18806 * Publish requests whose RequestId is valid only for the SecureChannel. */
18807 UA_SessionHeader *sh;
18808 while((sh = SLIST_FIRST(&channel->sessions))) {
18809 if(sh->serverSession) {
18810 UA_Session_detachFromSecureChannel(session: (UA_Session *)sh);
18811 } else {
18812 sh->channel = NULL;
18813 SLIST_REMOVE_HEAD(&channel->sessions, next);
18814 }
18815 }
18816
18817 /* Delete remaining chunks */
18818 UA_SecureChannel_deleteBuffered(channel);
18819}
18820
18821UA_StatusCode
18822UA_SecureChannel_processHELACK(UA_SecureChannel *channel,
18823 const UA_TcpAcknowledgeMessage *remoteConfig) {
18824 /* The lowest common version is used by both sides */
18825 if(channel->config.protocolVersion > remoteConfig->protocolVersion)
18826 channel->config.protocolVersion = remoteConfig->protocolVersion;
18827
18828 /* Can we receive the max send size? */
18829 if(channel->config.sendBufferSize > remoteConfig->receiveBufferSize)
18830 channel->config.sendBufferSize = remoteConfig->receiveBufferSize;
18831
18832 /* Can we send the max receive size? */
18833 if(channel->config.recvBufferSize > remoteConfig->sendBufferSize)
18834 channel->config.recvBufferSize = remoteConfig->sendBufferSize;
18835
18836 channel->config.remoteMaxMessageSize = remoteConfig->maxMessageSize;
18837 channel->config.remoteMaxChunkCount = remoteConfig->maxChunkCount;
18838
18839 /* Chunks of at least 8192 bytes must be permissible.
18840 * See Part 6, Clause 6.7.1 */
18841 if(channel->config.recvBufferSize < 8192 ||
18842 channel->config.sendBufferSize < 8192 ||
18843 (channel->config.remoteMaxMessageSize != 0 &&
18844 channel->config.remoteMaxMessageSize < 8192))
18845 return UA_STATUSCODE_BADINTERNALERROR;
18846
18847 channel->connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
18848 return UA_STATUSCODE_GOOD;
18849}
18850
18851/* Sends an OPN message using asymmetric encryption if defined */
18852UA_StatusCode
18853UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel,
18854 UA_UInt32 requestId, const void *content,
18855 const UA_DataType *contentType) {
18856 UA_CHECK(channel->securityMode != UA_MESSAGESECURITYMODE_INVALID,
18857 return UA_STATUSCODE_BADSECURITYMODEREJECTED);
18858
18859 const UA_SecurityPolicy *sp = channel->securityPolicy;
18860 UA_Connection *conn = channel->connection;
18861 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
18862 UA_CHECK_MEM(conn, return UA_STATUSCODE_BADINTERNALERROR);
18863
18864 /* Allocate the message buffer */
18865 UA_ByteString buf = UA_BYTESTRING_NULL;
18866 UA_StatusCode res = conn->getSendBuffer(conn, channel->config.sendBufferSize, &buf);
18867 UA_CHECK_STATUS(res, return res);
18868
18869 /* Restrict buffer to the available space for the payload */
18870 UA_Byte *buf_pos = buf.data;
18871 const UA_Byte *buf_end = &buf.data[buf.length];
18872 hideBytesAsym(channel, buf_start: &buf_pos, buf_end: &buf_end);
18873
18874 /* Encode the message type and content */
18875 res |= UA_NodeId_encodeBinary(src: &contentType->binaryEncodingId, bufPos: &buf_pos, bufEnd: buf_end);
18876 res |= UA_encodeBinaryInternal(src: content, type: contentType,
18877 bufPos: &buf_pos, bufEnd: &buf_end, NULL, NULL);
18878 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18879
18880 const size_t securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel);
18881
18882#ifdef UA_ENABLE_ENCRYPTION
18883 /* Add padding to the chunk. Also pad if the securityMode is SIGN_ONLY,
18884 * since we are using asymmetric communication to exchange keys and thus
18885 * need to encrypt. */
18886 if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE)
18887 padChunk(channel, cm: &channel->securityPolicy->asymmetricModule.cryptoModule,
18888 start: &buf.data[UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength],
18889 pos: &buf_pos);
18890#endif
18891
18892 /* The total message length */
18893 size_t pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data;
18894 size_t total_length = pre_sig_length;
18895 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
18896 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
18897 total_length += sp->asymmetricModule.cryptoModule.signatureAlgorithm.
18898 getLocalSignatureSize(channel->channelContext);
18899
18900 /* The total message length is known here which is why we encode the headers
18901 * at this step and not earlier. */
18902 size_t encryptedLength = 0;
18903 res = prependHeadersAsym(channel, header_pos: buf.data, buf_end, totalLength: total_length,
18904 securityHeaderLength, requestId, finalLength: &encryptedLength);
18905 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18906
18907#ifdef UA_ENABLE_ENCRYPTION
18908 res = signAndEncryptAsym(channel, preSignLength: pre_sig_length, buf: &buf,
18909 securityHeaderLength, totalLength: total_length);
18910 UA_CHECK_STATUS(res, conn->releaseSendBuffer(conn, &buf); return res);
18911#endif
18912
18913 /* Send the message, the buffer is freed in the network layer */
18914 buf.length = encryptedLength;
18915 res = conn->send(conn, &buf);
18916#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
18917 res |= sendAsym_sendFailure;
18918#endif
18919 return res;
18920}
18921
18922/* Will this chunk surpass the capacity of the SecureChannel for the message? */
18923static UA_StatusCode
18924adjustCheckMessageLimitsSym(UA_MessageContext *mc, size_t bodyLength) {
18925 mc->messageSizeSoFar += bodyLength;
18926 mc->chunksSoFar++;
18927
18928 UA_SecureChannel *channel = mc->channel;
18929 if(mc->messageSizeSoFar > channel->config.localMaxMessageSize &&
18930 channel->config.localMaxMessageSize != 0)
18931 return UA_STATUSCODE_BADRESPONSETOOLARGE;
18932
18933 if(mc->chunksSoFar > channel->config.localMaxChunkCount &&
18934 channel->config.localMaxChunkCount != 0)
18935 return UA_STATUSCODE_BADRESPONSETOOLARGE;
18936
18937 return UA_STATUSCODE_GOOD;
18938}
18939
18940static UA_StatusCode
18941encodeHeadersSym(UA_MessageContext *mc, size_t totalLength) {
18942 UA_SecureChannel *channel = mc->channel;
18943 UA_Byte *header_pos = mc->messageBuffer.data;
18944
18945 UA_TcpMessageHeader header;
18946 header.messageTypeAndChunkType = mc->messageType;
18947 header.messageSize = (UA_UInt32)totalLength;
18948 if(mc->final)
18949 header.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL;
18950 else
18951 header.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE;
18952
18953 UA_SequenceHeader seqHeader;
18954 seqHeader.requestId = mc->requestId;
18955 seqHeader.sequenceNumber = UA_atomic_addUInt32(addr: &channel->sendSequenceNumber, increase: 1);
18956
18957 UA_StatusCode res = UA_STATUSCODE_GOOD;
18958 res |= UA_encodeBinaryInternal(src: &header, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
18959 bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL);
18960 res |= UA_UInt32_encodeBinary(src: &channel->securityToken.channelId,
18961 bufPos: &header_pos, bufEnd: mc->buf_end);
18962 res |= UA_UInt32_encodeBinary(src: &channel->securityToken.tokenId,
18963 bufPos: &header_pos, bufEnd: mc->buf_end);
18964 res |= UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
18965 bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL);
18966 return res;
18967}
18968
18969static UA_StatusCode
18970sendSymmetricChunk(UA_MessageContext *mc) {
18971 UA_SecureChannel *channel = mc->channel;
18972 const UA_SecurityPolicy *sp = channel->securityPolicy;
18973 UA_Connection *connection = channel->connection;
18974 UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
18975
18976 /* The size of the message payload */
18977 size_t bodyLength = (uintptr_t)mc->buf_pos -
18978 (uintptr_t)&mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
18979
18980 /* Early-declare variables so we can use a goto in the error case */
18981 size_t total_length = 0;
18982 size_t pre_sig_length = 0;
18983
18984 /* Check if chunk exceeds the limits for the overall message */
18985 UA_StatusCode res = adjustCheckMessageLimitsSym(mc, bodyLength);
18986 UA_CHECK_STATUS(res, goto error);
18987
18988 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
18989 "Send from a symmetric message buffer of length %lu "
18990 "a message of header+payload length of %lu",
18991 (long unsigned int)mc->messageBuffer.length,
18992 (long unsigned int)
18993 ((uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data));
18994
18995#ifdef UA_ENABLE_ENCRYPTION
18996 /* Add padding if the message is encrypted */
18997 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
18998 padChunk(channel, cm: &sp->symmetricModule.cryptoModule,
18999 start: &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH],
19000 pos: &mc->buf_pos);
19001#endif
19002
19003 /* Compute the total message length */
19004 pre_sig_length = (uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data;
19005 total_length = pre_sig_length;
19006 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
19007 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
19008 total_length += sp->symmetricModule.cryptoModule.signatureAlgorithm.
19009 getLocalSignatureSize(channel->channelContext);
19010
19011 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
19012 "Send from a symmetric message buffer of length %lu "
19013 "a message of length %lu",
19014 (long unsigned int)mc->messageBuffer.length,
19015 (long unsigned int)total_length);
19016
19017 /* Space for the padding and the signature have been reserved in setBufPos() */
19018 UA_assert(total_length <= channel->config.sendBufferSize);
19019
19020 /* Adjust the buffer size of the network layer */
19021 mc->messageBuffer.length = total_length;
19022
19023 /* Generate and encode the header for symmetric messages */
19024 res = encodeHeadersSym(mc, totalLength: total_length);
19025 UA_CHECK_STATUS(res, goto error);
19026
19027#ifdef UA_ENABLE_ENCRYPTION
19028 /* Sign and encrypt the messge */
19029 res = signAndEncryptSym(messageContext: mc, preSigLength: pre_sig_length, totalLength: total_length);
19030 UA_CHECK_STATUS(res, goto error);
19031#endif
19032
19033 /* Send the chunk, the buffer is freed in the network layer */
19034 return connection->send(channel->connection, &mc->messageBuffer);
19035
19036 error:
19037 /* Free the unused message buffer */
19038 connection->releaseSendBuffer(channel->connection, &mc->messageBuffer);
19039 return res;
19040}
19041
19042/* Callback from the encoding layer. Send the chunk and replace the buffer. */
19043static UA_StatusCode
19044sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos,
19045 const UA_Byte **buf_end) {
19046 /* Set buf values from encoding in the messagecontext */
19047 UA_MessageContext *mc = (UA_MessageContext *)data;
19048 mc->buf_pos = *buf_pos;
19049 mc->buf_end = *buf_end;
19050
19051 /* Send out */
19052 UA_StatusCode res = sendSymmetricChunk(mc);
19053 UA_CHECK_STATUS(res, return res);
19054
19055 /* Set a new buffer for the next chunk */
19056 UA_Connection *c = mc->channel->connection;
19057 UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
19058
19059 res = c->getSendBuffer(c, mc->channel->config.sendBufferSize,
19060 &mc->messageBuffer);
19061 UA_CHECK_STATUS(res, return res);
19062
19063 /* Hide bytes for header, padding and signature */
19064 setBufPos(mc);
19065 *buf_pos = mc->buf_pos;
19066 *buf_end = mc->buf_end;
19067 return UA_STATUSCODE_GOOD;
19068}
19069
19070UA_StatusCode
19071UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel,
19072 UA_UInt32 requestId, UA_MessageType messageType) {
19073 UA_CHECK(messageType == UA_MESSAGETYPE_MSG || messageType == UA_MESSAGETYPE_CLO,
19074 return UA_STATUSCODE_BADINTERNALERROR);
19075
19076 UA_Connection *c = channel->connection;
19077 UA_CHECK_MEM(c, return UA_STATUSCODE_BADINTERNALERROR);
19078
19079 /* Create the chunking info structure */
19080 mc->channel = channel;
19081 mc->requestId = requestId;
19082 mc->chunksSoFar = 0;
19083 mc->messageSizeSoFar = 0;
19084 mc->final = false;
19085 mc->messageBuffer = UA_BYTESTRING_NULL;
19086 mc->messageType = messageType;
19087
19088 /* Allocate the message buffer */
19089 UA_StatusCode res = c->getSendBuffer(c, channel->config.sendBufferSize,
19090 &mc->messageBuffer);
19091 UA_CHECK_STATUS(res, return res);
19092
19093 /* Hide bytes for header, padding and signature */
19094 setBufPos(mc);
19095 return UA_STATUSCODE_GOOD;
19096}
19097
19098UA_StatusCode
19099UA_MessageContext_encode(UA_MessageContext *mc, const void *content,
19100 const UA_DataType *contentType) {
19101 UA_StatusCode res =
19102 UA_encodeBinaryInternal(src: content, type: contentType, bufPos: &mc->buf_pos, bufEnd: &mc->buf_end,
19103 exchangeCallback: sendSymmetricEncodingCallback, exchangeHandle: mc);
19104 if(res != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0)
19105 UA_MessageContext_abort(mc);
19106 return res;
19107}
19108
19109UA_StatusCode
19110UA_MessageContext_finish(UA_MessageContext *mc) {
19111 mc->final = true;
19112 return sendSymmetricChunk(mc);
19113}
19114
19115void
19116UA_MessageContext_abort(UA_MessageContext *mc) {
19117 UA_Connection *connection = mc->channel->connection;
19118 connection->releaseSendBuffer(connection, &mc->messageBuffer);
19119}
19120
19121UA_StatusCode
19122UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId,
19123 UA_MessageType messageType, void *payload,
19124 const UA_DataType *payloadType) {
19125 if(!channel || !channel->connection || !payload || !payloadType)
19126 return UA_STATUSCODE_BADINTERNALERROR;
19127
19128 if(channel->state != UA_SECURECHANNELSTATE_OPEN)
19129 return UA_STATUSCODE_BADCONNECTIONCLOSED;
19130
19131 if(channel->connection->state != UA_CONNECTIONSTATE_ESTABLISHED)
19132 return UA_STATUSCODE_BADCONNECTIONCLOSED;
19133
19134 UA_MessageContext mc;
19135 UA_StatusCode res = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType);
19136 UA_CHECK_STATUS(res, return res);
19137
19138 /* Assert's required for clang-analyzer */
19139 UA_assert(mc.buf_pos ==
19140 &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
19141 UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
19142
19143 res = UA_MessageContext_encode(mc: &mc, content: &payloadType->binaryEncodingId,
19144 contentType: &UA_TYPES[UA_TYPES_NODEID]);
19145 UA_CHECK_STATUS(res, return res);
19146
19147 res = UA_MessageContext_encode(mc: &mc, content: payload, contentType: payloadType);
19148 UA_CHECK_STATUS(res, return res);
19149
19150 return UA_MessageContext_finish(mc: &mc);
19151}
19152
19153/********************************/
19154/* Receive and Process Messages */
19155/********************************/
19156
19157/* Does the sequence number match? Otherwise try to rollover. See Part 6,
19158 * Section 6.7.2.4 of the standard. */
19159#define UA_SEQUENCENUMBER_ROLLOVER 4294966271
19160
19161#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
19162static UA_StatusCode
19163processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) {
19164#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
19165 /* Failure mode hook for unit tests */
19166 if(processSym_seqNumberFailure != UA_STATUSCODE_GOOD)
19167 return processSym_seqNumberFailure;
19168#endif
19169
19170 if(sequenceNumber != channel->receiveSequenceNumber + 1) {
19171 if(channel->receiveSequenceNumber + 1 <= UA_SEQUENCENUMBER_ROLLOVER ||
19172 sequenceNumber >= 1024)
19173 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
19174 channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */
19175 }
19176 ++channel->receiveSequenceNumber;
19177 return UA_STATUSCODE_GOOD;
19178}
19179#endif
19180
19181static UA_StatusCode
19182unpackPayloadOPN(UA_SecureChannel *channel, UA_Chunk *chunk, void *application) {
19183 UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19184 size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
19185 UA_UInt32 secureChannelId;
19186 UA_StatusCode res = UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId);
19187 UA_assert(res == UA_STATUSCODE_GOOD);
19188
19189 UA_AsymmetricAlgorithmSecurityHeader asymHeader;
19190 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &asymHeader,
19191 type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL);
19192 UA_CHECK_STATUS(res, return res);
19193
19194 if(asymHeader.senderCertificate.length > 0) {
19195 if(channel->certificateVerification)
19196 res = channel->certificateVerification->
19197 verifyCertificate(channel->certificateVerification->context,
19198 &asymHeader.senderCertificate);
19199 else
19200 res = UA_STATUSCODE_BADINTERNALERROR;
19201 UA_CHECK_STATUS(res, goto error);
19202 }
19203
19204 /* New channel, create a security policy context and attach */
19205 if(!channel->securityPolicy) {
19206 if(channel->processOPNHeader)
19207 res = channel->processOPNHeader(application, channel, &asymHeader);
19208 if(!channel->securityPolicy)
19209 res = UA_STATUSCODE_BADINTERNALERROR;
19210 UA_CHECK_STATUS(res, goto error);
19211 }
19212
19213 /* On the client side, take the SecureChannelId from the first response */
19214 if(secureChannelId != 0 && channel->securityToken.channelId == 0)
19215 channel->securityToken.channelId = secureChannelId;
19216
19217#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
19218 /* Check the ChannelId. Non-opened channels have the id zero. */
19219 if(secureChannelId != channel->securityToken.channelId) {
19220 res = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
19221 goto error;
19222 }
19223#endif
19224
19225 /* Check the header */
19226 res = checkAsymHeader(channel, asymHeader: &asymHeader);
19227 UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader);
19228 UA_CHECK_STATUS(res, return res);
19229
19230 /* Decrypt the chunk payload */
19231 res = decryptAndVerifyChunk(channel,
19232 cryptoModule: &channel->securityPolicy->asymmetricModule.cryptoModule,
19233 messageType: chunk->messageType, chunk: &chunk->bytes, offset);
19234 UA_CHECK_STATUS(res, return res);
19235
19236 /* Decode the SequenceHeader */
19237 UA_SequenceHeader sequenceHeader;
19238 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader,
19239 type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
19240 UA_CHECK_STATUS(res, return res);
19241
19242 /* Set the sequence number for the channel from which to count up */
19243 channel->receiveSequenceNumber = sequenceHeader.sequenceNumber;
19244 chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
19245
19246 /* Use only the payload */
19247 chunk->bytes.data += offset;
19248 chunk->bytes.length -= offset;
19249 return UA_STATUSCODE_GOOD;
19250
19251error:
19252 UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader);
19253 return res;
19254}
19255
19256static UA_StatusCode
19257unpackPayloadMSG(UA_SecureChannel *channel, UA_Chunk *chunk) {
19258 UA_CHECK_MEM(channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR);
19259
19260 UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19261 size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */
19262 UA_UInt32 secureChannelId;
19263 UA_UInt32 tokenId; /* SymmetricAlgorithmSecurityHeader */
19264 UA_StatusCode res = UA_STATUSCODE_GOOD;
19265 res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId);
19266 res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &tokenId);
19267 UA_assert(offset == UA_SECURECHANNEL_MESSAGE_MIN_LENGTH);
19268 UA_assert(res == UA_STATUSCODE_GOOD);
19269
19270#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
19271 /* Check the ChannelId. Non-opened channels have the id zero. */
19272 UA_CHECK(secureChannelId == channel->securityToken.channelId,
19273 return UA_STATUSCODE_BADSECURECHANNELIDINVALID);
19274#endif
19275
19276 /* Check (and revolve) the SecurityToken */
19277 res = checkSymHeader(channel, tokenId);
19278 UA_CHECK_STATUS(res, return res);
19279
19280 /* Decrypt the chunk payload */
19281 res = decryptAndVerifyChunk(channel,
19282 cryptoModule: &channel->securityPolicy->symmetricModule.cryptoModule,
19283 messageType: chunk->messageType, chunk: &chunk->bytes, offset);
19284 UA_CHECK_STATUS(res, return res);
19285
19286 /* Check the sequence number. Skip sequence number checking for fuzzer to
19287 * improve coverage */
19288 UA_SequenceHeader sequenceHeader;
19289 res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader,
19290 type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL);
19291#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
19292 res |= processSequenceNumberSym(channel, sequenceNumber: sequenceHeader.sequenceNumber);
19293#endif
19294 UA_CHECK_STATUS(res, return res);
19295
19296 chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */
19297
19298 /* Use only the payload */
19299 chunk->bytes.data += offset;
19300 chunk->bytes.length -= offset;
19301 return UA_STATUSCODE_GOOD;
19302}
19303
19304static UA_StatusCode
19305assembleProcessMessage(UA_SecureChannel *channel, void *application,
19306 UA_ProcessMessageCallback callback) {
19307 UA_Chunk *chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
19308 UA_assert(chunk != NULL);
19309
19310 UA_StatusCode res = UA_STATUSCODE_GOOD;
19311 if(chunk->chunkType == UA_CHUNKTYPE_FINAL) {
19312 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19313 UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
19314 res = callback(application, channel, chunk->messageType,
19315 chunk->requestId, &chunk->bytes);
19316 UA_Chunk_delete(chunk);
19317 return res;
19318 }
19319
19320 UA_UInt32 requestId = chunk->requestId;
19321 UA_MessageType messageType = chunk->messageType;
19322 UA_ChunkType chunkType = chunk->chunkType;
19323 UA_assert(chunkType == UA_CHUNKTYPE_INTERMEDIATE);
19324
19325 size_t messageSize = 0;
19326 SIMPLEQ_FOREACH(chunk, &channel->decryptedChunks, pointers) {
19327 /* Consistency check */
19328 if(requestId != chunk->requestId)
19329 return UA_STATUSCODE_BADINTERNALERROR;
19330 if(chunkType != chunk->chunkType && chunk->chunkType != UA_CHUNKTYPE_FINAL)
19331 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19332 if(chunk->messageType != messageType)
19333 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19334
19335 /* Sum up the lengths */
19336 messageSize += chunk->bytes.length;
19337 if(chunk->chunkType == UA_CHUNKTYPE_FINAL)
19338 break;
19339 }
19340
19341 /* Allocate memory for the full message */
19342 UA_ByteString payload;
19343 res = UA_ByteString_allocBuffer(bs: &payload, length: messageSize);
19344 UA_CHECK_STATUS(res, return res);
19345
19346 /* Assemble the full message */
19347 size_t offset = 0;
19348 while(true) {
19349 chunk = SIMPLEQ_FIRST(&channel->decryptedChunks);
19350 memcpy(dest: &payload.data[offset], src: chunk->bytes.data, n: chunk->bytes.length);
19351 offset += chunk->bytes.length;
19352 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19353 UA_ChunkType ct = chunk->chunkType;
19354 UA_Chunk_delete(chunk);
19355 if(ct == UA_CHUNKTYPE_FINAL)
19356 break;
19357 }
19358
19359 /* Process the assembled message */
19360 res = callback(application, channel, messageType, requestId, &payload);
19361 UA_ByteString_clear(p: &payload);
19362 return res;
19363}
19364
19365static UA_StatusCode
19366persistCompleteChunks(UA_ChunkQueue *queue) {
19367 UA_Chunk *chunk;
19368 SIMPLEQ_FOREACH(chunk, queue, pointers) {
19369 if(chunk->copied)
19370 continue;
19371 UA_ByteString copy;
19372 UA_StatusCode res = UA_ByteString_copy(src: &chunk->bytes, dst: &copy);
19373 UA_CHECK_STATUS(res, return res);
19374 chunk->bytes = copy;
19375 chunk->copied = true;
19376 }
19377 return UA_STATUSCODE_GOOD;
19378}
19379
19380static UA_StatusCode
19381persistIncompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
19382 size_t offset) {
19383 UA_assert(channel->incompleteChunk.length == 0);
19384 UA_assert(offset < buffer->length);
19385 size_t length = buffer->length - offset;
19386 UA_StatusCode res = UA_ByteString_allocBuffer(bs: &channel->incompleteChunk, length);
19387 UA_CHECK_STATUS(res, return res);
19388 memcpy(dest: channel->incompleteChunk.data, src: &buffer->data[offset], n: length);
19389 return UA_STATUSCODE_GOOD;
19390}
19391
19392/* Processes chunks and puts them into the payloads queue. Once a final chunk is
19393 * put into the queue, the message is assembled and the callback is called. The
19394 * queue will be cleared for the next message. */
19395static UA_StatusCode
19396processChunks(UA_SecureChannel *channel, void *application,
19397 UA_ProcessMessageCallback callback) {
19398 UA_Chunk *chunk;
19399 UA_StatusCode res = UA_STATUSCODE_GOOD;
19400 while((chunk = SIMPLEQ_FIRST(&channel->completeChunks))) {
19401 /* Remove from the complete-chunk queue */
19402 SIMPLEQ_REMOVE_HEAD(&channel->completeChunks, pointers);
19403
19404 /* Check, decrypt and unpack the payload */
19405 if(chunk->messageType == UA_MESSAGETYPE_OPN) {
19406 if(channel->state != UA_SECURECHANNELSTATE_OPEN &&
19407 channel->state != UA_SECURECHANNELSTATE_OPN_SENT &&
19408 channel->state != UA_SECURECHANNELSTATE_ACK_SENT)
19409 res = UA_STATUSCODE_BADINVALIDSTATE;
19410 else
19411 res = unpackPayloadOPN(channel, chunk, application);
19412 } else if(chunk->messageType == UA_MESSAGETYPE_MSG ||
19413 chunk->messageType == UA_MESSAGETYPE_CLO) {
19414 if(channel->state == UA_SECURECHANNELSTATE_CLOSED)
19415 res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
19416 else
19417 res = unpackPayloadMSG(channel, chunk);
19418 } else {
19419 chunk->bytes.data += UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
19420 chunk->bytes.length -= UA_SECURECHANNEL_MESSAGEHEADER_LENGTH;
19421 }
19422
19423 if(res != UA_STATUSCODE_GOOD) {
19424 UA_Chunk_delete(chunk);
19425 return res;
19426 }
19427
19428 /* Add to the decrypted-chunk queue */
19429 SIMPLEQ_INSERT_TAIL(&channel->decryptedChunks, chunk, pointers);
19430
19431 /* Check the resource limits */
19432 channel->decryptedChunksCount++;
19433 channel->decryptedChunksLength += chunk->bytes.length;
19434 if((channel->config.localMaxChunkCount != 0 &&
19435 channel->decryptedChunksCount > channel->config.localMaxChunkCount) ||
19436 (channel->config.localMaxMessageSize != 0 &&
19437 channel->decryptedChunksLength > channel->config.localMaxMessageSize)) {
19438 return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
19439 }
19440
19441 /* Waiting for additional chunks */
19442 if(chunk->chunkType == UA_CHUNKTYPE_INTERMEDIATE)
19443 continue;
19444
19445 /* Final chunk or abort. Reset the counters. */
19446 channel->decryptedChunksCount = 0;
19447 channel->decryptedChunksLength = 0;
19448
19449 /* Abort the message, remove all decrypted chunks
19450 * TODO: Log a warning with the error code */
19451 if(chunk->chunkType == UA_CHUNKTYPE_ABORT) {
19452 while((chunk = SIMPLEQ_FIRST(&channel->decryptedChunks))) {
19453 SIMPLEQ_REMOVE_HEAD(&channel->decryptedChunks, pointers);
19454 UA_Chunk_delete(chunk);
19455 }
19456 continue;
19457 }
19458
19459 /* The decrypted queue contains a full message. Process it. */
19460 UA_assert(chunk->chunkType == UA_CHUNKTYPE_FINAL);
19461 res = assembleProcessMessage(channel, application, callback);
19462 UA_CHECK_STATUS(res, return res);
19463 }
19464
19465 return UA_STATUSCODE_GOOD;
19466}
19467
19468static UA_StatusCode
19469extractCompleteChunk(UA_SecureChannel *channel, const UA_ByteString *buffer,
19470 size_t *offset, UA_Boolean *done) {
19471 /* At least 8 byte needed for the header. Wait for the next chunk. */
19472 size_t initial_offset = *offset;
19473 size_t remaining = buffer->length - initial_offset;
19474 if(remaining < UA_SECURECHANNEL_MESSAGEHEADER_LENGTH) {
19475 *done = true;
19476 return UA_STATUSCODE_GOOD;
19477 }
19478
19479 /* Decoding cannot fail */
19480 UA_TcpMessageHeader hdr;
19481 UA_StatusCode res =
19482 UA_decodeBinaryInternal(src: buffer, offset: &initial_offset, dst: &hdr,
19483 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL);
19484 UA_assert(res == UA_STATUSCODE_GOOD);
19485 (void)res; /* pacify compilers if assert is ignored */
19486 UA_MessageType msgType = (UA_MessageType)
19487 (hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE);
19488 UA_ChunkType chunkType = (UA_ChunkType)
19489 (hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE);
19490
19491 /* The message size is not allowed */
19492 if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH)
19493 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19494 if(hdr.messageSize > channel->config.recvBufferSize)
19495 return UA_STATUSCODE_BADTCPMESSAGETOOLARGE;
19496
19497 /* Incomplete chunk */
19498 if(hdr.messageSize > remaining) {
19499 *done = true;
19500 return UA_STATUSCODE_GOOD;
19501 }
19502
19503 /* ByteString with only this chunk. */
19504 UA_ByteString chunkPayload;
19505 chunkPayload.data = &buffer->data[*offset];
19506 chunkPayload.length = hdr.messageSize;
19507
19508 if(msgType == UA_MESSAGETYPE_HEL || msgType == UA_MESSAGETYPE_ACK ||
19509 msgType == UA_MESSAGETYPE_ERR || msgType == UA_MESSAGETYPE_OPN) {
19510 if(chunkType != UA_CHUNKTYPE_FINAL)
19511 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19512 } else {
19513 /* Only messages on SecureChannel-level with symmetric encryption afterwards */
19514 if(msgType != UA_MESSAGETYPE_MSG &&
19515 msgType != UA_MESSAGETYPE_CLO)
19516 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19517
19518 /* Check the chunk type before decrypting */
19519 if(chunkType != UA_CHUNKTYPE_FINAL &&
19520 chunkType != UA_CHUNKTYPE_INTERMEDIATE &&
19521 chunkType != UA_CHUNKTYPE_ABORT)
19522 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
19523 }
19524
19525 /* Add the chunk; forward the offset */
19526 *offset += hdr.messageSize;
19527 UA_Chunk *chunk = (UA_Chunk*)UA_malloc(size: sizeof(UA_Chunk));
19528 UA_CHECK_MEM(chunk, return UA_STATUSCODE_BADOUTOFMEMORY);
19529
19530 chunk->bytes = chunkPayload;
19531 chunk->messageType = msgType;
19532 chunk->chunkType = chunkType;
19533 chunk->requestId = 0;
19534 chunk->copied = false;
19535
19536 SIMPLEQ_INSERT_TAIL(&channel->completeChunks, chunk, pointers);
19537 return UA_STATUSCODE_GOOD;
19538}
19539
19540UA_StatusCode
19541UA_SecureChannel_processBuffer(UA_SecureChannel *channel, void *application,
19542 UA_ProcessMessageCallback callback,
19543 const UA_ByteString *buffer) {
19544 /* Prepend the incomplete last chunk. This is usually done in the
19545 * networklayer. But we test for a buffered incomplete chunk here again to
19546 * work around "lazy" network layers. */
19547 UA_ByteString appended = channel->incompleteChunk;
19548 if(appended.length > 0) {
19549 channel->incompleteChunk = UA_BYTESTRING_NULL;
19550 UA_Byte *t = (UA_Byte*)UA_realloc(ptr: appended.data, size: appended.length + buffer->length);
19551 UA_CHECK_MEM(t, UA_ByteString_clear(&appended);
19552 return UA_STATUSCODE_BADOUTOFMEMORY);
19553 memcpy(dest: &t[appended.length], src: buffer->data, n: buffer->length);
19554 appended.data = t;
19555 appended.length += buffer->length;
19556 buffer = &appended;
19557 }
19558
19559 /* Loop over the received chunks */
19560 size_t offset = 0;
19561 UA_Boolean done = false;
19562 UA_StatusCode res;
19563 while(!done) {
19564 res = extractCompleteChunk(channel, buffer, offset: &offset, done: &done);
19565 UA_CHECK_STATUS(res, goto cleanup);
19566 }
19567
19568 /* Buffer half-received chunk. Before processing the messages so that
19569 * processing is reentrant. */
19570 if(offset < buffer->length) {
19571 res = persistIncompleteChunk(channel, buffer, offset);
19572 UA_CHECK_STATUS(res, goto cleanup);
19573 }
19574
19575 /* Process whatever we can. Chunks of completed and processed messages are
19576 * removed. */
19577 res = processChunks(channel, application, callback);
19578 UA_CHECK_STATUS(res, goto cleanup);
19579
19580 /* Persist full chunks that still point to the buffer. Can only return
19581 * UA_STATUSCODE_BADOUTOFMEMORY as an error code. So merging res works. */
19582 res |= persistCompleteChunks(queue: &channel->completeChunks);
19583 res |= persistCompleteChunks(queue: &channel->decryptedChunks);
19584
19585 cleanup:
19586 UA_ByteString_clear(p: &appended);
19587 return res;
19588}
19589
19590UA_StatusCode
19591UA_SecureChannel_receive(UA_SecureChannel *channel, void *application,
19592 UA_ProcessMessageCallback callback, UA_UInt32 timeout) {
19593 UA_Connection *connection = channel->connection;
19594 UA_CHECK_MEM(connection, return UA_STATUSCODE_BADINTERNALERROR);
19595
19596 /* Listen for messages to arrive */
19597 UA_ByteString buffer = UA_BYTESTRING_NULL;
19598 UA_StatusCode res = connection->recv(connection, &buffer, timeout);
19599 UA_CHECK_STATUS(res, return res);
19600
19601 /* Try to process one complete chunk */
19602 res = UA_SecureChannel_processBuffer(channel, application, callback, buffer: &buffer);
19603 connection->releaseRecvBuffer(connection, &buffer);
19604 return res;
19605}
19606
19607/**** amalgamated original file "/src/ua_securechannel_crypto.c" ****/
19608
19609/* This Source Code Form is subject to the terms of the Mozilla Public
19610 * License, v. 2.0. If a copy of the MPL was not distributed with this
19611 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
19612 *
19613 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
19614 * Copyright 2014, 2016-2017 (c) Florian Palm
19615 * Copyright 2015-2016 (c) Sten Grüner
19616 * Copyright 2015 (c) Oleksiy Vasylyev
19617 * Copyright 2016 (c) TorbenD
19618 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
19619 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
19620 */
19621
19622
19623
19624UA_StatusCode
19625UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) {
19626 const UA_SecurityPolicy *sp = channel->securityPolicy;
19627 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19628 UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local nonce");
19629
19630 /* Is the length of the previous nonce correct? */
19631 size_t nonceLength = sp->symmetricModule.secureChannelNonceLength;
19632 if(channel->localNonce.length != nonceLength) {
19633 UA_ByteString_clear(p: &channel->localNonce);
19634 UA_StatusCode res = UA_ByteString_allocBuffer(bs: &channel->localNonce, length: nonceLength);
19635 UA_CHECK_STATUS(res, return res);
19636 }
19637
19638 /* Generate the nonce */
19639 return sp->symmetricModule.generateNonce(sp->policyContext, &channel->localNonce);
19640}
19641
19642UA_StatusCode
19643UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) {
19644 const UA_SecurityPolicy *sp = channel->securityPolicy;
19645 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19646 UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new local keys");
19647
19648 void *cc = channel->channelContext;
19649 const UA_SecurityPolicyChannelModule *cm = &sp->channelModule;
19650 const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule;
19651 const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule;
19652
19653 /* Generate symmetric key buffer of the required length. The block size is
19654 * identical for local/remote. */
19655 UA_ByteString buf;
19656 size_t encrKL = crm->encryptionAlgorithm.getLocalKeyLength(cc);
19657 size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
19658 size_t signKL = crm->signatureAlgorithm.getLocalKeyLength(cc);
19659 if(encrBS + signKL + encrKL == 0)
19660 return UA_STATUSCODE_GOOD; /* No keys to generate */
19661
19662 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL);
19663 UA_CHECK_STATUS(retval, return retval);
19664 UA_ByteString localSigningKey = {signKL, buf.data};
19665 UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]};
19666 UA_ByteString localIv = {encrBS, &buf.data[signKL + encrKL]};
19667
19668 /* Generate key */
19669 retval = sm->generateKey(sp->policyContext, &channel->remoteNonce,
19670 &channel->localNonce, &buf);
19671 UA_CHECK_STATUS(retval, goto error);
19672
19673 /* Set the channel context */
19674 retval |= cm->setLocalSymSigningKey(cc, &localSigningKey);
19675 retval |= cm->setLocalSymEncryptingKey(cc, &localEncryptingKey);
19676 retval |= cm->setLocalSymIv(cc, &localIv);
19677
19678 error:
19679 UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
19680 "Could not generate local keys (statuscode: %s)",
19681 UA_StatusCode_name(retval)));
19682 UA_ByteString_clear(p: &buf);
19683 return retval;
19684}
19685
19686UA_StatusCode
19687generateRemoteKeys(const UA_SecureChannel *channel) {
19688 const UA_SecurityPolicy *sp = channel->securityPolicy;
19689 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19690 UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new remote keys");
19691
19692 void *cc = channel->channelContext;
19693 const UA_SecurityPolicyChannelModule *cm = &sp->channelModule;
19694 const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule;
19695 const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule;
19696
19697 /* Generate symmetric key buffer of the required length */
19698 UA_ByteString buf;
19699 size_t encrKL = crm->encryptionAlgorithm.getRemoteKeyLength(cc);
19700 size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc);
19701 size_t signKL = crm->signatureAlgorithm.getRemoteKeyLength(cc);
19702 if(encrBS + signKL + encrKL == 0)
19703 return UA_STATUSCODE_GOOD; /* No keys to generate */
19704
19705 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL);
19706 UA_CHECK_STATUS(retval, return retval);
19707 UA_ByteString remoteSigningKey = {signKL, buf.data};
19708 UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]};
19709 UA_ByteString remoteIv = {encrBS, &buf.data[signKL + encrKL]};
19710
19711 /* Generate key */
19712 retval = sm->generateKey(sp->policyContext, &channel->localNonce,
19713 &channel->remoteNonce, &buf);
19714 UA_CHECK_STATUS(retval, goto error);
19715
19716 /* Set the channel context */
19717 retval |= cm->setRemoteSymSigningKey(cc, &remoteSigningKey);
19718 retval |= cm->setRemoteSymEncryptingKey(cc, &remoteEncryptingKey);
19719 retval |= cm->setRemoteSymIv(cc, &remoteIv);
19720
19721 error:
19722 UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel,
19723 "Could not generate remote keys (statuscode: %s)",
19724 UA_StatusCode_name(retval)));
19725 UA_ByteString_clear(p: &buf);
19726 return retval;
19727}
19728
19729/***************************/
19730/* Send Asymmetric Message */
19731/***************************/
19732
19733/* The length of the static header content */
19734#define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12
19735
19736size_t
19737calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) {
19738 const UA_SecurityPolicy *sp = channel->securityPolicy;
19739 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19740
19741 size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH +
19742 sp->policyUri.length;
19743 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19744 return asymHeaderLength;
19745
19746 /* OPN is always encrypted even if the mode is sign only */
19747 asymHeaderLength += 20; /* Thumbprints are always 20 byte long */
19748 asymHeaderLength += sp->localCertificate.length;
19749 return asymHeaderLength;
19750}
19751
19752UA_StatusCode
19753prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos,
19754 const UA_Byte *buf_end, size_t totalLength,
19755 size_t securityHeaderLength, UA_UInt32 requestId,
19756 size_t *const encryptedLength) {
19757 const UA_SecurityPolicy *sp = channel->securityPolicy;
19758 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
19759
19760 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) {
19761 *encryptedLength = totalLength;
19762 } else {
19763 size_t dataToEncryptLength = totalLength -
19764 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength);
19765 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
19766 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19767 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
19768 encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
19769
19770 /* Padding always fills up the last block */
19771 UA_assert(dataToEncryptLength % plainTextBlockSize == 0);
19772 size_t blocks = dataToEncryptLength / plainTextBlockSize;
19773 *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize);
19774 }
19775
19776 UA_TcpMessageHeader messageHeader;
19777 messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL;
19778 messageHeader.messageSize = (UA_UInt32)*encryptedLength;
19779 UA_UInt32 secureChannelId = channel->securityToken.channelId;
19780 UA_StatusCode retval = UA_STATUSCODE_GOOD;
19781 retval |= UA_encodeBinaryInternal(src: &messageHeader,
19782 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
19783 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19784 retval |= UA_UInt32_encodeBinary(src: &secureChannelId, bufPos: &header_pos, bufEnd: buf_end);
19785 UA_CHECK_STATUS(retval, return retval);
19786
19787 UA_AsymmetricAlgorithmSecurityHeader asymHeader;
19788 UA_AsymmetricAlgorithmSecurityHeader_init(p: &asymHeader);
19789 asymHeader.securityPolicyUri = sp->policyUri;
19790 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
19791 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
19792 asymHeader.senderCertificate = sp->localCertificate;
19793 asymHeader.receiverCertificateThumbprint.length = 20;
19794 asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint;
19795 }
19796 retval = UA_encodeBinaryInternal(src: &asymHeader,
19797 type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER],
19798 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19799 UA_CHECK_STATUS(retval, return retval);
19800
19801 UA_SequenceHeader seqHeader;
19802 seqHeader.requestId = requestId;
19803 seqHeader.sequenceNumber = UA_atomic_addUInt32(addr: &channel->sendSequenceNumber, increase: 1);
19804 retval = UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER],
19805 bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL);
19806 return retval;
19807}
19808
19809void
19810hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start,
19811 const UA_Byte **buf_end) {
19812 /* Set buf_start to the beginning of the payload body */
19813 *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH;
19814 *buf_start += calculateAsymAlgSecurityHeaderLength(channel);
19815 *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
19816
19817#ifdef UA_ENABLE_ENCRYPTION
19818 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19819 return;
19820
19821 /* Make space for the certificate */
19822 const UA_SecurityPolicy *sp = channel->securityPolicy;
19823 *buf_end -= sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19824 getLocalSignatureSize(channel->channelContext);
19825
19826 /* Block sizes depend on the remote key (certificate) */
19827 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
19828 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19829 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
19830 encryptionAlgorithm.getRemoteBlockSize(channel->channelContext);
19831 UA_Boolean extraPadding = (sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
19832 getRemoteKeyLength(channel->channelContext) > 2048);
19833
19834 /* Compute the maximum number of encrypted blocks that can fit entirely
19835 * before the signature. From that compute the maximum usable plaintext
19836 * size. */
19837 size_t maxEncrypted = (size_t)(*buf_end - *buf_start) +
19838 UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH;
19839 size_t max_blocks = maxEncrypted / encryptedBlockSize;
19840 size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
19841 *buf_end = *buf_start + (max_blocks * plainTextBlockSize) -
19842 UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH - paddingBytes;
19843#endif
19844}
19845
19846#ifdef UA_ENABLE_ENCRYPTION
19847
19848/* Assumes that pos can be advanced to the end of the current block */
19849void
19850padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm,
19851 const UA_Byte *start, UA_Byte **pos) {
19852 const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start;
19853 size_t signatureSize = cm->signatureAlgorithm.
19854 getLocalSignatureSize(channel->channelContext);
19855 size_t plainTextBlockSize = cm->encryptionAlgorithm.
19856 getRemotePlainTextBlockSize(channel->channelContext);
19857 UA_Boolean extraPadding = (cm->encryptionAlgorithm.
19858 getRemoteKeyLength(channel->channelContext) > 2048);
19859 size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u;
19860
19861 size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize);
19862 size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0;
19863
19864 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
19865 "Add %lu bytes of padding plus %lu padding size bytes",
19866 (long unsigned int)paddingLength,
19867 (long unsigned int)paddingBytes);
19868
19869 /* Write the padding. This is <= because the paddingSize byte also has to be
19870 * written */
19871 UA_Byte paddingByte = (UA_Byte)paddingLength;
19872 for(UA_UInt16 i = 0; i <= paddingLength; ++i) {
19873 **pos = paddingByte;
19874 ++*pos;
19875 }
19876
19877 /* Write the extra padding byte if required */
19878 if(extraPadding) {
19879 **pos = (UA_Byte)(paddingLength >> 8u);
19880 ++*pos;
19881 }
19882}
19883
19884UA_StatusCode
19885signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength,
19886 UA_ByteString *buf, size_t securityHeaderLength,
19887 size_t totalLength) {
19888 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
19889 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
19890 return UA_STATUSCODE_GOOD;
19891
19892 /* Sign message */
19893 const UA_SecurityPolicy *sp = channel->securityPolicy;
19894 const UA_ByteString dataToSign = {preSignLength, buf->data};
19895 size_t sigsize = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19896 getLocalSignatureSize(channel->channelContext);
19897 UA_ByteString signature = {sigsize, buf->data + preSignLength};
19898 UA_StatusCode retval = sp->asymmetricModule.cryptoModule.signatureAlgorithm.
19899 sign(channel->channelContext, &dataToSign, &signature);
19900 UA_CHECK_STATUS(retval, return retval);
19901
19902 /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are
19903 * signed and encrypted if the SecurityMode is not None (even if the
19904 * SecurityMode is SignOnly). */
19905 size_t unencrypted_length =
19906 UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength;
19907 UA_ByteString dataToEncrypt = {totalLength - unencrypted_length,
19908 &buf->data[unencrypted_length]};
19909 return sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
19910 encrypt(channel->channelContext, &dataToEncrypt);
19911}
19912
19913/**************************/
19914/* Send Symmetric Message */
19915/**************************/
19916
19917UA_StatusCode
19918signAndEncryptSym(UA_MessageContext *messageContext,
19919 size_t preSigLength, size_t totalLength) {
19920 const UA_SecureChannel *channel = messageContext->channel;
19921 if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19922 return UA_STATUSCODE_GOOD;
19923
19924 /* Sign */
19925 const UA_SecurityPolicy *sp = channel->securityPolicy;
19926 UA_ByteString dataToSign = messageContext->messageBuffer;
19927 dataToSign.length = preSigLength;
19928 UA_ByteString signature;
19929 signature.length = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19930 getLocalSignatureSize(channel->channelContext);
19931 signature.data = messageContext->buf_pos;
19932 UA_StatusCode res = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19933 sign(channel->channelContext, &dataToSign, &signature);
19934 UA_CHECK_STATUS(res, return res);
19935
19936 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
19937 return UA_STATUSCODE_GOOD;
19938
19939 /* Encrypt */
19940 UA_ByteString dataToEncrypt;
19941 dataToEncrypt.data = messageContext->messageBuffer.data +
19942 UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
19943 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH;
19944 dataToEncrypt.length = totalLength -
19945 (UA_SECURECHANNEL_CHANNELHEADER_LENGTH +
19946 UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH);
19947 return sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19948 encrypt(channel->channelContext, &dataToEncrypt);
19949}
19950
19951#endif /* UA_ENABLE_ENCRYPTION */
19952
19953void
19954setBufPos(UA_MessageContext *mc) {
19955 /* Forward the data pointer so that the payload is encoded after the message
19956 * header. This has to be a symmetric message because OPN (with asymmetric
19957 * encryption) does not support chunking. */
19958 mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH];
19959 mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length];
19960
19961#ifdef UA_ENABLE_ENCRYPTION
19962 if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
19963 return;
19964
19965 const UA_SecureChannel *channel = mc->channel;
19966 const UA_SecurityPolicy *sp = channel->securityPolicy;
19967 size_t sigsize = sp->symmetricModule.cryptoModule.signatureAlgorithm.
19968 getLocalSignatureSize(channel->channelContext);
19969 size_t plainBlockSize = sp->symmetricModule.cryptoModule.
19970 encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext);
19971
19972 /* Assuming that for symmetric encryption the plainTextBlockSize ==
19973 * cypherTextBlockSize. For symmetric encryption the remote/local block
19974 * sizes are identical. */
19975 UA_assert(sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19976 getRemoteBlockSize(channel->channelContext) == plainBlockSize);
19977
19978 /* Leave enough space for the signature and padding */
19979 mc->buf_end -= sigsize;
19980 mc->buf_end -= mc->messageBuffer.length % plainBlockSize;
19981
19982 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
19983 /* Reserve space for the padding bytes */
19984 UA_Boolean extraPadding =
19985 (sp->symmetricModule.cryptoModule.encryptionAlgorithm.
19986 getRemoteKeyLength(channel->channelContext) > 2048);
19987 mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2;
19988 }
19989
19990 UA_LOG_TRACE_CHANNEL(sp->logger, channel,
19991 "Prepare a symmetric message buffer of length %lu "
19992 "with a usable maximum payload length of %lu",
19993 (long unsigned)mc->messageBuffer.length,
19994 (long unsigned)((uintptr_t)mc->buf_end -
19995 (uintptr_t)mc->messageBuffer.data));
19996#endif
19997}
19998
19999/****************************/
20000/* Process a received Chunk */
20001/****************************/
20002
20003static size_t
20004decodePadding(const UA_SecureChannel *channel,
20005 const UA_SecurityPolicyCryptoModule *cryptoModule,
20006 const UA_ByteString *chunk, size_t sigsize) {
20007 /* Read the byte with the padding size */
20008 size_t paddingSize = chunk->data[chunk->length - sigsize - 1];
20009
20010 /* Extra padding size */
20011 if(cryptoModule->encryptionAlgorithm.
20012 getLocalKeyLength(channel->channelContext) > 2048) {
20013 paddingSize <<= 8u;
20014 paddingSize += chunk->data[chunk->length - sigsize - 2];
20015 paddingSize += 1; /* Extra padding byte itself */
20016 }
20017
20018 /* Add one since the paddingSize byte itself needs to be removed as well */
20019 return paddingSize + 1;
20020}
20021
20022static UA_StatusCode
20023verifySignature(const UA_SecureChannel *channel,
20024 const UA_SecurityPolicyCryptoModule *cryptoModule,
20025 const UA_ByteString *chunk, size_t sigsize) {
20026 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
20027 "Verifying chunk signature");
20028 UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
20029 const UA_ByteString content = {chunk->length - sigsize, chunk->data};
20030 const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize};
20031 UA_StatusCode retval = cryptoModule->signatureAlgorithm.
20032 verify(channel->channelContext, &content, &sig);
20033#ifdef UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
20034 retval |= decrypt_verifySignatureFailure;
20035#endif
20036 return retval;
20037}
20038
20039/* Sets the payload to a pointer inside the chunk buffer. Returns the requestId
20040 * and the sequenceNumber */
20041UA_StatusCode
20042decryptAndVerifyChunk(const UA_SecureChannel *channel,
20043 const UA_SecurityPolicyCryptoModule *cryptoModule,
20044 UA_MessageType messageType, UA_ByteString *chunk,
20045 size_t offset) {
20046 /* Decrypt the chunk */
20047 UA_StatusCode res = UA_STATUSCODE_GOOD;
20048 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
20049 messageType == UA_MESSAGETYPE_OPN) {
20050 UA_ByteString cipher = {chunk->length - offset, chunk->data + offset};
20051 res = cryptoModule->encryptionAlgorithm.decrypt(channel->channelContext, &cipher);
20052 UA_CHECK_STATUS(res, return res);
20053 chunk->length = cipher.length + offset;
20054 }
20055
20056 /* Does the message have a signature? */
20057 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
20058 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT &&
20059 messageType != UA_MESSAGETYPE_OPN)
20060 return UA_STATUSCODE_GOOD;
20061
20062 /* Verify the chunk signature */
20063 size_t sigsize = cryptoModule->signatureAlgorithm.
20064 getRemoteSignatureSize(channel->channelContext);
20065 res = verifySignature(channel, cryptoModule, chunk, sigsize);
20066 UA_CHECK_STATUS(res,
20067 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20068 "Could not verify the signature"); return res);
20069
20070 /* Compute the padding if the payload as encrypted */
20071 size_t padSize = 0;
20072 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT ||
20073 (messageType == UA_MESSAGETYPE_OPN &&
20074 cryptoModule->encryptionAlgorithm.uri.length > 0)) {
20075 padSize = decodePadding(channel, cryptoModule, chunk, sigsize);
20076 UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel,
20077 "Calculated padding size to be %lu",
20078 (long unsigned)padSize);
20079 }
20080
20081 /* Verify the content length. The encrypted payload has to be at least 9
20082 * bytes long: 8 byte for the SequenceHeader and one byte for the actual
20083 * message */
20084 UA_CHECK(offset + padSize + sigsize + 9 < chunk->length,
20085 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20086 "Impossible padding value");
20087 return UA_STATUSCODE_BADSECURITYCHECKSFAILED);
20088
20089 /* Hide the signature and padding */
20090 chunk->length -= (sigsize + padSize);
20091 return UA_STATUSCODE_GOOD;
20092}
20093
20094UA_StatusCode
20095checkAsymHeader(UA_SecureChannel *channel,
20096 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
20097 const UA_SecurityPolicy *sp = channel->securityPolicy;
20098 if(!UA_ByteString_equal(string1: &sp->policyUri, string2: &asymHeader->securityPolicyUri))
20099 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
20100
20101 return sp->asymmetricModule.
20102 compareCertificateThumbprint(sp, &asymHeader->receiverCertificateThumbprint);
20103
20104 /* The certificate in the header is verified via the configured PKI plugin
20105 * as certificateVerification.verifyCertificate(...). We cannot do it here
20106 * because the client/server context is needed. */
20107}
20108
20109UA_StatusCode
20110checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId) {
20111 /* If no match, try to revolve to the next token after a
20112 * RenewSecureChannel */
20113 UA_StatusCode retval = UA_STATUSCODE_GOOD;
20114 UA_ChannelSecurityToken *token = &channel->securityToken;
20115 switch(channel->renewState) {
20116 case UA_SECURECHANNELRENEWSTATE_NORMAL:
20117 case UA_SECURECHANNELRENEWSTATE_SENT:
20118 default:
20119 break;
20120
20121 case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER:
20122 /* Old token still in use */
20123 if(tokenId == channel->securityToken.tokenId)
20124 break;
20125
20126 /* Not the new token */
20127 UA_CHECK(tokenId == channel->altSecurityToken.tokenId,
20128 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20129 "Unknown SecurityToken");
20130 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
20131
20132 /* Roll over to the new token, generate new local and remote keys */
20133 channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
20134 channel->securityToken = channel->altSecurityToken;
20135 UA_ChannelSecurityToken_init(p: &channel->altSecurityToken);
20136 retval |= UA_SecureChannel_generateLocalKeys(channel);
20137 retval |= generateRemoteKeys(channel);
20138 UA_CHECK_STATUS(retval, return retval);
20139 break;
20140
20141 case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT:
20142 /* The server is still using the old token. That's okay. */
20143 if(tokenId == channel->altSecurityToken.tokenId) {
20144 token = &channel->altSecurityToken;
20145 break;
20146 }
20147
20148 /* Not the new token */
20149 UA_CHECK(tokenId == channel->securityToken.tokenId,
20150 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20151 "Unknown SecurityToken");
20152 return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN);
20153
20154 /* The remote server uses the new token for the first time. Delete the
20155 * old token and roll the remote key over. The local key already uses
20156 * the nonce pair from the last OPN exchange. */
20157 channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
20158 UA_ChannelSecurityToken_init(p: &channel->altSecurityToken);
20159 retval = generateRemoteKeys(channel);
20160 UA_CHECK_STATUS(retval, return retval);
20161 }
20162
20163 UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC);
20164 if(channel->state == UA_SECURECHANNELSTATE_OPEN &&
20165 timeout < UA_DateTime_nowMonotonic()) {
20166 UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel,
20167 "SecurityToken timed out");
20168 UA_SecureChannel_close(channel);
20169 return UA_STATUSCODE_BADSECURECHANNELCLOSED;
20170 }
20171
20172 return UA_STATUSCODE_GOOD;
20173}
20174
20175/**** amalgamated original file "/src/server/ua_session.c" ****/
20176
20177/* This Source Code Form is subject to the terms of the Mozilla Public
20178 * License, v. 2.0. If a copy of the MPL was not distributed with this
20179 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
20180 *
20181 * Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
20182 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
20183 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
20184 */
20185
20186#ifdef UA_ENABLE_SUBSCRIPTIONS
20187#endif
20188
20189#define UA_SESSION_NONCELENTH 32
20190
20191void UA_Session_init(UA_Session *session) {
20192 memset(s: session, c: 0, n: sizeof(UA_Session));
20193 session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
20194#ifdef UA_ENABLE_SUBSCRIPTIONS
20195 SIMPLEQ_INIT(&session->responseQueue);
20196 TAILQ_INIT(&session->subscriptions);
20197#endif
20198}
20199
20200void UA_Session_clear(UA_Session *session, UA_Server* server) {
20201 UA_LOCK_ASSERT(&server->serviceMutex, 1);
20202
20203 /* Remove all Subscriptions. This may send out remaining publish
20204 * responses. */
20205#ifdef UA_ENABLE_SUBSCRIPTIONS
20206 UA_Subscription *sub, *tempsub;
20207 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
20208 UA_Subscription_delete(server, sub);
20209 }
20210#endif
20211
20212#ifdef UA_ENABLE_DIAGNOSTICS
20213 deleteNode(server, session->sessionId, true);
20214#endif
20215
20216 UA_Session_detachFromSecureChannel(session);
20217 UA_ApplicationDescription_clear(p: &session->clientDescription);
20218 UA_NodeId_clear(p: &session->header.authenticationToken);
20219 UA_NodeId_clear(p: &session->sessionId);
20220 UA_String_clear(p: &session->sessionName);
20221 UA_ByteString_clear(p: &session->serverNonce);
20222 struct ContinuationPoint *cp, *next = session->continuationPoints;
20223 while((cp = next)) {
20224 next = ContinuationPoint_clear(cp);
20225 UA_free(ptr: cp);
20226 }
20227 session->continuationPoints = NULL;
20228 session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS;
20229
20230 UA_Array_delete(p: session->params, size: session->paramsSize,
20231 type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
20232 session->params = NULL;
20233 session->paramsSize = 0;
20234
20235 UA_Array_delete(p: session->localeIds, size: session->localeIdsSize,
20236 type: &UA_TYPES[UA_TYPES_STRING]);
20237 session->localeIds = NULL;
20238 session->localeIdsSize = 0;
20239
20240#ifdef UA_ENABLE_DIAGNOSTICS
20241 UA_SessionDiagnosticsDataType_clear(&session->diagnostics);
20242 UA_SessionSecurityDiagnosticsDataType_clear(&session->securityDiagnostics);
20243#endif
20244}
20245
20246void
20247UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) {
20248 UA_Session_detachFromSecureChannel(session);
20249 session->header.channel = channel;
20250 session->header.serverSession = true;
20251 SLIST_INSERT_HEAD(&channel->sessions, &session->header, next);
20252}
20253
20254void
20255UA_Session_detachFromSecureChannel(UA_Session *session) {
20256 UA_SecureChannel *channel = session->header.channel;
20257 if(!channel)
20258 return;
20259 session->header.channel = NULL;
20260 UA_SessionHeader *sh;
20261 SLIST_FOREACH(sh, &channel->sessions, next) {
20262 if((UA_Session*)sh != session)
20263 continue;
20264 SLIST_REMOVE(&channel->sessions, sh, UA_SessionHeader, next);
20265 break;
20266 }
20267
20268 /* Clean up the response queue. Their RequestId is bound to the
20269 * SecureChannel so they cannot be reused. */
20270#ifdef UA_ENABLE_SUBSCRIPTIONS
20271 UA_PublishResponseEntry *pre;
20272 while((pre = UA_Session_dequeuePublishReq(session))) {
20273 UA_PublishResponse_clear(p: &pre->response);
20274 UA_free(ptr: pre);
20275 }
20276#endif
20277}
20278
20279UA_StatusCode
20280UA_Session_generateNonce(UA_Session *session) {
20281 UA_SecureChannel *channel = session->header.channel;
20282 if(!channel || !channel->securityPolicy)
20283 return UA_STATUSCODE_BADINTERNALERROR;
20284
20285 /* Is the length of the previous nonce correct? */
20286 if(session->serverNonce.length != UA_SESSION_NONCELENTH) {
20287 UA_ByteString_clear(p: &session->serverNonce);
20288 UA_StatusCode retval =
20289 UA_ByteString_allocBuffer(bs: &session->serverNonce, UA_SESSION_NONCELENTH);
20290 if(retval != UA_STATUSCODE_GOOD)
20291 return retval;
20292 }
20293
20294 return channel->securityPolicy->symmetricModule.
20295 generateNonce(channel->securityPolicy->policyContext, &session->serverNonce);
20296}
20297
20298void UA_Session_updateLifetime(UA_Session *session) {
20299 session->validTill = UA_DateTime_nowMonotonic() +
20300 (UA_DateTime)(session->timeout * UA_DATETIME_MSEC);
20301#ifdef UA_ENABLE_DIAGNOSTICS
20302 session->diagnostics.clientLastContactTime = UA_DateTime_now();
20303#endif
20304}
20305
20306#ifdef UA_ENABLE_SUBSCRIPTIONS
20307
20308void
20309UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub) {
20310 /* Attach to the session */
20311 sub->session = session;
20312
20313 /* Increase the count */
20314 session->subscriptionsSize++;
20315
20316 /* Increase the number of outstanding retransmissions */
20317 session->totalRetransmissionQueueSize += sub->retransmissionQueueSize;
20318
20319 /* Insert at the end of the subscriptions of the same priority / just before
20320 * the subscriptions with the next lower priority. */
20321 UA_Subscription *after = NULL;
20322 TAILQ_FOREACH(after, &session->subscriptions, sessionListEntry) {
20323 if(after->priority < sub->priority) {
20324 TAILQ_INSERT_BEFORE(after, sub, sessionListEntry);
20325 return;
20326 }
20327 }
20328 TAILQ_INSERT_TAIL(&session->subscriptions, sub, sessionListEntry);
20329}
20330
20331void
20332UA_Session_detachSubscription(UA_Server *server, UA_Session *session,
20333 UA_Subscription *sub, UA_Boolean releasePublishResponses) {
20334 /* Detach from the session */
20335 sub->session = NULL;
20336 TAILQ_REMOVE(&session->subscriptions, sub, sessionListEntry);
20337
20338 /* Reduce the count */
20339 UA_assert(session->subscriptionsSize > 0);
20340 session->subscriptionsSize--;
20341
20342 /* Reduce the number of outstanding retransmissions */
20343 session->totalRetransmissionQueueSize -= sub->retransmissionQueueSize;
20344
20345 /* Send remaining publish responses if the last subscription was removed */
20346 if(!releasePublishResponses || !TAILQ_EMPTY(&session->subscriptions))
20347 return;
20348 UA_PublishResponseEntry *pre;
20349 while((pre = UA_Session_dequeuePublishReq(session))) {
20350 UA_PublishResponse *response = &pre->response;
20351 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
20352 response->responseHeader.timestamp = UA_DateTime_now();
20353 sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId,
20354 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
20355 UA_PublishResponse_clear(p: response);
20356 UA_free(ptr: pre);
20357 }
20358}
20359
20360UA_Subscription *
20361UA_Session_getSubscriptionById(UA_Session *session, UA_UInt32 subscriptionId) {
20362 UA_Subscription *sub;
20363 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
20364 /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
20365 if(sub->statusChange != UA_STATUSCODE_GOOD)
20366 continue;
20367 if(sub->subscriptionId == subscriptionId)
20368 break;
20369 }
20370 return sub;
20371}
20372
20373UA_Subscription *
20374UA_Server_getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId) {
20375 UA_Subscription *sub;
20376 LIST_FOREACH(sub, &server->subscriptions, serverListEntry) {
20377 /* Prevent lookup of subscriptions that are to be deleted with a statuschange */
20378 if(sub->statusChange != UA_STATUSCODE_GOOD)
20379 continue;
20380 if(sub->subscriptionId == subscriptionId)
20381 break;
20382 }
20383 return sub;
20384}
20385
20386UA_PublishResponseEntry*
20387UA_Session_dequeuePublishReq(UA_Session *session) {
20388 UA_PublishResponseEntry* entry = SIMPLEQ_FIRST(&session->responseQueue);
20389 if(entry) {
20390 SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
20391 session->responseQueueSize--;
20392 }
20393 return entry;
20394}
20395
20396void
20397UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry,
20398 UA_Boolean head) {
20399 if(!head)
20400 SIMPLEQ_INSERT_TAIL(&session->responseQueue, entry, listEntry);
20401 else
20402 SIMPLEQ_INSERT_HEAD(&session->responseQueue, entry, listEntry);
20403 session->responseQueueSize++;
20404}
20405
20406#endif
20407
20408/* Session Handling */
20409
20410UA_StatusCode
20411UA_Server_closeSession(UA_Server *server, const UA_NodeId *sessionId) {
20412 UA_LOCK(&server->serviceMutex);
20413 session_list_entry *entry;
20414 UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
20415 LIST_FOREACH(entry, &server->sessions, pointers) {
20416 if(UA_NodeId_equal(n1: &entry->session.sessionId, n2: sessionId)) {
20417 UA_Server_removeSession(server, sentry: entry, event: UA_DIAGNOSTICEVENT_CLOSE);
20418 res = UA_STATUSCODE_GOOD;
20419 break;
20420 }
20421 }
20422 UA_UNLOCK(&server->serviceMutex);
20423 return res;
20424}
20425
20426UA_StatusCode
20427UA_Server_setSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20428 const char *name, const UA_Variant *parameter) {
20429 UA_LOCK(&server->serviceMutex);
20430 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20431 UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID;
20432 if(session)
20433 res = UA_KeyValueMap_set(map: &session->params, mapSize: &session->paramsSize,
20434 key: name, value: parameter);
20435 UA_UNLOCK(&server->serviceMutex);
20436 return res;
20437}
20438
20439void
20440UA_Server_deleteSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20441 const char *name) {
20442 UA_LOCK(&server->serviceMutex);
20443 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20444 if(session)
20445 UA_KeyValueMap_delete(map: &session->params, mapSize: &session->paramsSize, key: name);
20446 UA_UNLOCK(&server->serviceMutex);
20447}
20448
20449UA_StatusCode
20450UA_Server_getSessionParameter(UA_Server *server, const UA_NodeId *sessionId,
20451 const char *name, UA_Variant *outParameter) {
20452 UA_LOCK(&server->serviceMutex);
20453 if(!outParameter) {
20454 UA_UNLOCK(&server->serviceMutex);
20455 return UA_STATUSCODE_BADINTERNALERROR;
20456 }
20457
20458 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20459 if(!session) {
20460 UA_UNLOCK(&server->serviceMutex);
20461 return UA_STATUSCODE_BADSESSIONIDINVALID;
20462 }
20463
20464 const UA_Variant *param =
20465 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20466 if(!param) {
20467 UA_UNLOCK(&server->serviceMutex);
20468 return UA_STATUSCODE_BADNOTFOUND;
20469 }
20470
20471 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20472 UA_UNLOCK(&server->serviceMutex);
20473 return res;
20474}
20475
20476UA_StatusCode
20477UA_Server_getSessionScalarParameter(UA_Server *server, const UA_NodeId *sessionId,
20478 const char *name, const UA_DataType *type,
20479 UA_Variant *outParameter) {
20480 UA_LOCK(&server->serviceMutex);
20481 if(!outParameter) {
20482 UA_UNLOCK(&server->serviceMutex);
20483 return UA_STATUSCODE_BADINTERNALERROR;
20484 }
20485
20486 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20487 if(!session) {
20488 UA_UNLOCK(&server->serviceMutex);
20489 return UA_STATUSCODE_BADSESSIONIDINVALID;
20490 }
20491
20492 const UA_Variant *param =
20493 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20494 if(!param || !UA_Variant_hasScalarType(v: param, type)) {
20495 UA_UNLOCK(&server->serviceMutex);
20496 return UA_STATUSCODE_BADNOTFOUND;
20497 }
20498
20499 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20500 UA_UNLOCK(&server->serviceMutex);
20501 return res;
20502}
20503
20504UA_StatusCode
20505UA_Server_getSessionArrayParameter(UA_Server *server, const UA_NodeId *sessionId,
20506 const char *name, const UA_DataType *type,
20507 UA_Variant *outParameter) {
20508 UA_LOCK(&server->serviceMutex);
20509 if(!outParameter) {
20510 UA_UNLOCK(&server->serviceMutex);
20511 return UA_STATUSCODE_BADINTERNALERROR;
20512 }
20513
20514 UA_Session *session = UA_Server_getSessionById(server, sessionId);
20515 if(!session) {
20516 UA_UNLOCK(&server->serviceMutex);
20517 return UA_STATUSCODE_BADSESSIONIDINVALID;
20518 }
20519
20520 const UA_Variant *param =
20521 UA_KeyValueMap_get(map: session->params, mapSize: session->paramsSize, key: name);
20522 if(!param || !UA_Variant_hasArrayType(v: param, type)) {
20523 UA_UNLOCK(&server->serviceMutex);
20524 return UA_STATUSCODE_BADNOTFOUND;
20525 }
20526
20527 UA_StatusCode res = UA_Variant_copy(src: param, dst: outParameter);
20528 UA_UNLOCK(&server->serviceMutex);
20529 return res;
20530}
20531
20532/**** amalgamated original file "/src/server/ua_nodes.c" ****/
20533
20534/* This Source Code Form is subject to the terms of the Mozilla Public
20535 * License, v. 2.0. If a copy of the MPL was not distributed with this
20536 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
20537 *
20538 * Copyright 2015-2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
20539 * Copyright 2015-2016 (c) Sten Grüner
20540 * Copyright 2015 (c) Chris Iatrou
20541 * Copyright 2015, 2017 (c) Florian Palm
20542 * Copyright 2015 (c) Oleksiy Vasylyev
20543 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
20544 * Copyright 2017 (c) Julian Grothoff
20545 */
20546
20547
20548/*****************/
20549/* Node Pointers */
20550/*****************/
20551
20552#define UA_NODEPOINTER_MASK 0x03
20553#define UA_NODEPOINTER_TAG_IMMEDIATE 0x00
20554#define UA_NODEPOINTER_TAG_NODEID 0x01
20555#define UA_NODEPOINTER_TAG_EXPANDEDNODEID 0x02
20556#define UA_NODEPOINTER_TAG_NODE 0x03
20557
20558void
20559UA_NodePointer_clear(UA_NodePointer *np) {
20560 switch(np->immediate & UA_NODEPOINTER_MASK) {
20561 case UA_NODEPOINTER_TAG_NODEID:
20562 np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20563 UA_NodeId_delete(p: (UA_NodeId*)(uintptr_t)np->id);
20564 break;
20565 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20566 np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20567 UA_ExpandedNodeId_delete(p: (UA_ExpandedNodeId*)(uintptr_t)
20568 np->expandedId);
20569 break;
20570 default:
20571 break;
20572 }
20573 UA_NodePointer_init(np);
20574}
20575
20576UA_StatusCode
20577UA_NodePointer_copy(UA_NodePointer in, UA_NodePointer *out) {
20578 UA_StatusCode res = UA_STATUSCODE_GOOD;
20579 UA_Byte tag = in.immediate & UA_NODEPOINTER_MASK;
20580 in.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20581 switch(tag) {
20582 case UA_NODEPOINTER_TAG_NODE:
20583 in.id = &in.node->nodeId;
20584 goto nodeid; /* fallthrough */
20585 case UA_NODEPOINTER_TAG_NODEID:
20586 nodeid:
20587 out->id = UA_NodeId_new();
20588 if(!out->id)
20589 return UA_STATUSCODE_BADOUTOFMEMORY;
20590 res = UA_NodeId_copy(src: in.id, dst: (UA_NodeId*)(uintptr_t)out->id);
20591 if(res != UA_STATUSCODE_GOOD) {
20592 UA_free(ptr: (void*)out->immediate);
20593 out->immediate = 0;
20594 break;
20595 }
20596 out->immediate |= UA_NODEPOINTER_TAG_NODEID;
20597 break;
20598 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20599 out->expandedId = UA_ExpandedNodeId_new();
20600 if(!out->expandedId)
20601 return UA_STATUSCODE_BADOUTOFMEMORY;
20602 res = UA_ExpandedNodeId_copy(src: in.expandedId,
20603 dst: (UA_ExpandedNodeId*)(uintptr_t)
20604 out->expandedId);
20605 if(res != UA_STATUSCODE_GOOD) {
20606 UA_free(ptr: (void*)out->immediate);
20607 out->immediate = 0;
20608 break;
20609 }
20610 out->immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
20611 break;
20612 default:
20613 case UA_NODEPOINTER_TAG_IMMEDIATE:
20614 *out = in;
20615 break;
20616 }
20617 return res;
20618}
20619
20620UA_Boolean
20621UA_NodePointer_isLocal(UA_NodePointer np) {
20622 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20623 return (tag != UA_NODEPOINTER_TAG_EXPANDEDNODEID);
20624}
20625
20626UA_Order
20627UA_NodePointer_order(UA_NodePointer p1, UA_NodePointer p2) {
20628 if(p1.immediate == p2.immediate)
20629 return UA_ORDER_EQ;
20630
20631 /* Extract the tag and resolve pointers to nodes */
20632 UA_Byte tag1 = p1.immediate & UA_NODEPOINTER_MASK;
20633 if(tag1 == UA_NODEPOINTER_TAG_NODE) {
20634 p1 = UA_NodePointer_fromNodeId(id: &p1.node->nodeId);
20635 tag1 = p1.immediate & UA_NODEPOINTER_MASK;
20636 }
20637 UA_Byte tag2 = p2.immediate & UA_NODEPOINTER_MASK;
20638 if(tag2 == UA_NODEPOINTER_TAG_NODE) {
20639 p2 = UA_NodePointer_fromNodeId(id: &p2.node->nodeId);
20640 tag2 = p2.immediate & UA_NODEPOINTER_MASK;
20641 }
20642
20643 /* Different tags, cannot be identical */
20644 if(tag1 != tag2)
20645 return (tag1 > tag2) ? UA_ORDER_MORE : UA_ORDER_LESS;
20646
20647 /* Immediate */
20648 if(UA_LIKELY(tag1 == UA_NODEPOINTER_TAG_IMMEDIATE))
20649 return (p1.immediate > p2.immediate) ?
20650 UA_ORDER_MORE : UA_ORDER_LESS;
20651
20652 /* Compare from pointers */
20653 p1.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20654 p2.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20655 if(tag1 == UA_NODEPOINTER_TAG_EXPANDEDNODEID)
20656 return UA_ExpandedNodeId_order(n1: p1.expandedId, n2: p2.expandedId);
20657 return UA_NodeId_order(n1: p1.id, n2: p2.id);
20658}
20659
20660UA_NodePointer
20661UA_NodePointer_fromNodeId(const UA_NodeId *id) {
20662 UA_NodePointer np;
20663 if(id->identifierType != UA_NODEIDTYPE_NUMERIC) {
20664 np.id = id;
20665 np.immediate |= UA_NODEPOINTER_TAG_NODEID;
20666 return np;
20667 }
20668
20669#if SIZE_MAX > UA_UINT32_MAX
20670 /* 64bit: 4 Byte for the numeric identifier + 2 Byte for the namespaceIndex
20671 * + 1 Byte for the tagging bit (zero) */
20672 np.immediate = ((uintptr_t)id->identifier.numeric) << 32;
20673 np.immediate |= ((uintptr_t)id->namespaceIndex) << 8;
20674#else
20675 /* 32bit: 3 Byte for the numeric identifier + 6 Bit for the namespaceIndex
20676 * + 2 Bit for the tagging bit (zero) */
20677 if(id->namespaceIndex < (0x01 << 6) &&
20678 id->identifier.numeric < (0x01 << 24)) {
20679 np.immediate = ((uintptr_t)id->identifier.numeric) << 8;
20680 np.immediate |= ((uintptr_t)id->namespaceIndex) << 2;
20681 } else {
20682 np.id = id;
20683 np.immediate |= UA_NODEPOINTER_TAG_NODEID;
20684 }
20685#endif
20686 return np;
20687}
20688
20689UA_NodeId
20690UA_NodePointer_toNodeId(UA_NodePointer np) {
20691 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20692 np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20693 switch(tag) {
20694 case UA_NODEPOINTER_TAG_NODE:
20695 return np.node->nodeId;
20696 case UA_NODEPOINTER_TAG_NODEID:
20697 return *np.id;
20698 case UA_NODEPOINTER_TAG_EXPANDEDNODEID:
20699 return np.expandedId->nodeId;
20700 default:
20701 case UA_NODEPOINTER_TAG_IMMEDIATE:
20702 break;
20703 }
20704
20705 UA_NodeId id;
20706 id.identifierType = UA_NODEIDTYPE_NUMERIC;
20707#if SIZE_MAX > UA_UINT32_MAX /* 64bit */
20708 id.namespaceIndex = (UA_UInt16)(np.immediate >> 8);
20709 id.identifier.numeric = (UA_UInt32)(np.immediate >> 32);
20710#else /* 32bit */
20711 id.namespaceIndex = ((UA_Byte)np.immediate) >> 2;
20712 id.identifier.numeric = np.immediate >> 8;
20713#endif
20714 return id;
20715}
20716
20717UA_NodePointer
20718UA_NodePointer_fromExpandedNodeId(const UA_ExpandedNodeId *id) {
20719 if(!UA_ExpandedNodeId_isLocal(n: id)) {
20720 UA_NodePointer np;
20721 np.expandedId = id;
20722 np.immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID;
20723 return np;
20724 }
20725 return UA_NodePointer_fromNodeId(id: &id->nodeId);
20726}
20727
20728UA_ExpandedNodeId
20729UA_NodePointer_toExpandedNodeId(UA_NodePointer np) {
20730 /* Resolve node pointer to get the NodeId */
20731 UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK;
20732 if(tag == UA_NODEPOINTER_TAG_NODE) {
20733 np = UA_NodePointer_fromNodeId(id: &np.node->nodeId);
20734 tag = np.immediate & UA_NODEPOINTER_MASK;
20735 }
20736
20737 /* ExpandedNodeId, make a shallow copy */
20738 if(tag == UA_NODEPOINTER_TAG_EXPANDEDNODEID) {
20739 np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK;
20740 return *np.expandedId;
20741 }
20742
20743 /* NodeId, either immediate or via a pointer */
20744 UA_ExpandedNodeId en;
20745 UA_ExpandedNodeId_init(p: &en);
20746 en.nodeId = UA_NodePointer_toNodeId(np);
20747 return en;
20748}
20749
20750/**************/
20751/* References */
20752/**************/
20753
20754static UA_StatusCode
20755addReferenceTarget(UA_NodeReferenceKind *refs, UA_NodePointer target,
20756 UA_UInt32 targetNameHash);
20757
20758static enum aa_cmp
20759cmpRefTargetId(const void *a, const void *b) {
20760 const UA_ReferenceTargetTreeElem *aa = (const UA_ReferenceTargetTreeElem*)a;
20761 const UA_ReferenceTargetTreeElem *bb = (const UA_ReferenceTargetTreeElem*)b;
20762 if(aa->targetIdHash < bb->targetIdHash)
20763 return AA_CMP_LESS;
20764 if(aa->targetIdHash > bb->targetIdHash)
20765 return AA_CMP_MORE;
20766 return (enum aa_cmp)UA_NodePointer_order(p1: aa->target.targetId,
20767 p2: bb->target.targetId);
20768}
20769
20770static enum aa_cmp
20771cmpRefTargetName(const void *a, const void *b) {
20772 const UA_UInt32 *nameHashA = (const UA_UInt32*)a;
20773 const UA_UInt32 *nameHashB = (const UA_UInt32*)b;
20774 if(*nameHashA < *nameHashB)
20775 return AA_CMP_LESS;
20776 if(*nameHashA > *nameHashB)
20777 return AA_CMP_MORE;
20778 return AA_CMP_EQ;
20779}
20780
20781/* Reusable binary search tree "heads". Just switch out the root pointer. */
20782static const struct aa_head refIdTree =
20783 { NULL, cmpRefTargetId, offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20784const struct aa_head refNameTree =
20785 { NULL, cmpRefTargetName, offsetof(UA_ReferenceTargetTreeElem, nameTreeEntry),
20786 offsetof(UA_ReferenceTarget, targetNameHash) };
20787
20788const UA_ReferenceTarget *
20789UA_NodeReferenceKind_iterate(const UA_NodeReferenceKind *rk,
20790 const UA_ReferenceTarget *prev) {
20791 /* Return from the tree */
20792 if(rk->hasRefTree) {
20793 const struct aa_head _refIdTree =
20794 { rk->targets.tree.idTreeRoot, cmpRefTargetId,
20795 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20796 if(prev == NULL)
20797 return (const UA_ReferenceTarget*)aa_min(head: &_refIdTree);
20798 return (const UA_ReferenceTarget*)aa_next(head: &_refIdTree, elem: prev);
20799 }
20800 if(prev == NULL) /* Return start of the array */
20801 return rk->targets.array;
20802 if(prev + 1 >= &rk->targets.array[rk->targetsSize])
20803 return NULL; /* End of the array */
20804 return prev + 1; /* Next element in the array */
20805}
20806
20807/* Also deletes the elements of the tree */
20808static void
20809moveTreeToArray(UA_ReferenceTarget *array, size_t *pos,
20810 struct aa_entry *entry) {
20811 if(!entry)
20812 return;
20813 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
20814 ((uintptr_t)entry - offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
20815 moveTreeToArray(array, pos, entry: elem->idTreeEntry.left);
20816 moveTreeToArray(array, pos, entry: elem->idTreeEntry.right);
20817 array[*pos] = elem->target;
20818 (*pos)++;
20819 UA_free(ptr: elem);
20820}
20821
20822UA_StatusCode
20823UA_NodeReferenceKind_switch(UA_NodeReferenceKind *rk) {
20824 if(rk->hasRefTree) {
20825 /* From tree to array */
20826 UA_ReferenceTarget *array = (UA_ReferenceTarget*)
20827 UA_malloc(size: sizeof(UA_ReferenceTarget) * rk->targetsSize);
20828 if(!array)
20829 return UA_STATUSCODE_BADOUTOFMEMORY;
20830 size_t pos = 0;
20831 moveTreeToArray(array, pos: &pos, entry: rk->targets.tree.idTreeRoot);
20832 rk->targets.array = array;
20833 rk->hasRefTree = false;
20834 return UA_STATUSCODE_GOOD;
20835 }
20836
20837 /* From array to tree */
20838 UA_NodeReferenceKind newRk = *rk;
20839 newRk.hasRefTree = true;
20840 newRk.targets.tree.idTreeRoot = NULL;
20841 newRk.targets.tree.nameTreeRoot = NULL;
20842 for(size_t i = 0; i < rk->targetsSize; i++) {
20843 UA_StatusCode res =
20844 addReferenceTarget(refs: &newRk, target: rk->targets.array[i].targetId,
20845 targetNameHash: rk->targets.array[i].targetNameHash);
20846 if(res != UA_STATUSCODE_GOOD) {
20847 struct aa_head _refIdTree = refIdTree;
20848 _refIdTree.root = newRk.targets.tree.idTreeRoot;
20849 while(_refIdTree.root) {
20850 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
20851 ((uintptr_t)_refIdTree.root -
20852 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
20853 aa_remove(head: &_refIdTree, elem);
20854 UA_NodePointer_clear(np: &elem->target.targetId);
20855 UA_free(ptr: elem);
20856 }
20857 return res;
20858 }
20859 }
20860 for(size_t i = 0; i < rk->targetsSize; i++)
20861 UA_NodePointer_clear(np: &rk->targets.array[i].targetId);
20862 UA_free(ptr: rk->targets.array);
20863 *rk = newRk;
20864 return UA_STATUSCODE_GOOD;
20865}
20866
20867const UA_ReferenceTarget *
20868UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk,
20869 const UA_ExpandedNodeId *targetId) {
20870 UA_NodePointer targetP = UA_NodePointer_fromExpandedNodeId(id: targetId);
20871
20872 /* Return from the tree */
20873 if(rk->hasRefTree) {
20874 UA_ReferenceTargetTreeElem tmpTarget;
20875 tmpTarget.target.targetId = targetP;
20876 tmpTarget.targetIdHash = UA_ExpandedNodeId_hash(n: targetId);
20877 const struct aa_head _refIdTree =
20878 { rk->targets.tree.idTreeRoot, cmpRefTargetId,
20879 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry), 0 };
20880 return (const UA_ReferenceTarget*)aa_find(head: &_refIdTree, key: &tmpTarget);
20881 }
20882
20883 /* Return from the array */
20884 for(size_t i = 0; i < rk->targetsSize; i++) {
20885 if(UA_NodePointer_equal(p1: targetP, p2: rk->targets.array[i].targetId))
20886 return &rk->targets.array[i];
20887 }
20888 return NULL;
20889}
20890
20891const UA_Node *
20892UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target) {
20893 if(!UA_NodePointer_isLocal(np: target))
20894 return NULL;
20895 UA_NodeId id = UA_NodePointer_toNodeId(np: target);
20896 return UA_NODESTORE_GET(server, &id);
20897}
20898
20899/* General node handling methods. There is no UA_Node_new() method here.
20900 * Creating nodes is part of the Nodestore layer */
20901
20902void UA_Node_clear(UA_Node *node) {
20903 /* Delete references */
20904 UA_Node_deleteReferences(node);
20905
20906 /* Delete other head content */
20907 UA_NodeHead *head = &node->head;
20908 UA_NodeId_clear(p: &head->nodeId);
20909 UA_QualifiedName_clear(p: &head->browseName);
20910 UA_LocalizedText_clear(p: &head->displayName);
20911 UA_LocalizedText_clear(p: &head->description);
20912
20913 /* Delete unique content of the nodeclass */
20914 switch(head->nodeClass) {
20915 case UA_NODECLASS_OBJECT:
20916 break;
20917 case UA_NODECLASS_METHOD:
20918 break;
20919 case UA_NODECLASS_OBJECTTYPE:
20920 break;
20921 case UA_NODECLASS_VARIABLE:
20922 case UA_NODECLASS_VARIABLETYPE: {
20923 UA_VariableNode *p = &node->variableNode;
20924 UA_NodeId_clear(p: &p->dataType);
20925 UA_Array_delete(p: p->arrayDimensions, size: p->arrayDimensionsSize,
20926 type: &UA_TYPES[UA_TYPES_INT32]);
20927 p->arrayDimensions = NULL;
20928 p->arrayDimensionsSize = 0;
20929 if(p->valueSource == UA_VALUESOURCE_DATA)
20930 UA_DataValue_clear(p: &p->value.data.value);
20931 break;
20932 }
20933 case UA_NODECLASS_REFERENCETYPE: {
20934 UA_ReferenceTypeNode *p = &node->referenceTypeNode;
20935 UA_LocalizedText_clear(p: &p->inverseName);
20936 break;
20937 }
20938 case UA_NODECLASS_DATATYPE:
20939 break;
20940 case UA_NODECLASS_VIEW:
20941 break;
20942 default:
20943 break;
20944 }
20945}
20946
20947static UA_StatusCode
20948UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) {
20949 dst->eventNotifier = src->eventNotifier;
20950 return UA_STATUSCODE_GOOD;
20951}
20952
20953static UA_StatusCode
20954UA_CommonVariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
20955 UA_StatusCode retval =
20956 UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize,
20957 dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]);
20958 if(retval != UA_STATUSCODE_GOOD)
20959 return retval;
20960 dst->arrayDimensionsSize = src->arrayDimensionsSize;
20961 retval = UA_NodeId_copy(src: &src->dataType, dst: &dst->dataType);
20962 dst->valueRank = src->valueRank;
20963 dst->valueSource = src->valueSource;
20964 if(src->valueSource == UA_VALUESOURCE_DATA) {
20965 retval |= UA_DataValue_copy(src: &src->value.data.value,
20966 dst: &dst->value.data.value);
20967 dst->value.data.callback = src->value.data.callback;
20968 } else
20969 dst->value.dataSource = src->value.dataSource;
20970 return retval;
20971}
20972
20973static UA_StatusCode
20974UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) {
20975 dst->accessLevel = src->accessLevel;
20976 dst->minimumSamplingInterval = src->minimumSamplingInterval;
20977 dst->historizing = src->historizing;
20978 dst->isDynamic = src->isDynamic;
20979 return UA_CommonVariableNode_copy(src, dst);
20980}
20981
20982static UA_StatusCode
20983UA_VariableTypeNode_copy(const UA_VariableTypeNode *src,
20984 UA_VariableTypeNode *dst) {
20985 dst->isAbstract = src->isAbstract;
20986 return UA_CommonVariableNode_copy(src: (const UA_VariableNode*)src, dst: (UA_VariableNode*)dst);
20987}
20988
20989static UA_StatusCode
20990UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) {
20991 dst->executable = src->executable;
20992 dst->method = src->method;
20993#if UA_MULTITHREADING >= 100
20994 dst->async = src->async;
20995#endif
20996 return UA_STATUSCODE_GOOD;
20997}
20998
20999static UA_StatusCode
21000UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) {
21001 dst->isAbstract = src->isAbstract;
21002 dst->lifecycle = src->lifecycle;
21003 return UA_STATUSCODE_GOOD;
21004}
21005
21006static UA_StatusCode
21007UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src,
21008 UA_ReferenceTypeNode *dst) {
21009 dst->isAbstract = src->isAbstract;
21010 dst->symmetric = src->symmetric;
21011 dst->referenceTypeIndex = src->referenceTypeIndex;
21012 dst->subTypes = src->subTypes;
21013 return UA_LocalizedText_copy(src: &src->inverseName, dst: &dst->inverseName);
21014}
21015
21016static UA_StatusCode
21017UA_DataTypeNode_copy(const UA_DataTypeNode *src, UA_DataTypeNode *dst) {
21018 dst->isAbstract = src->isAbstract;
21019 return UA_STATUSCODE_GOOD;
21020}
21021
21022static UA_StatusCode
21023UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) {
21024 dst->containsNoLoops = src->containsNoLoops;
21025 dst->eventNotifier = src->eventNotifier;
21026 return UA_STATUSCODE_GOOD;
21027}
21028
21029UA_StatusCode
21030UA_Node_copy(const UA_Node *src, UA_Node *dst) {
21031 const UA_NodeHead *srchead = &src->head;
21032 UA_NodeHead *dsthead = &dst->head;
21033 if(srchead->nodeClass != dsthead->nodeClass)
21034 return UA_STATUSCODE_BADINTERNALERROR;
21035
21036 /* Copy standard content */
21037 UA_StatusCode retval = UA_NodeId_copy(src: &srchead->nodeId, dst: &dsthead->nodeId);
21038 retval |= UA_QualifiedName_copy(src: &srchead->browseName, dst: &dsthead->browseName);
21039 retval |= UA_LocalizedText_copy(src: &srchead->displayName, dst: &dsthead->displayName);
21040 retval |= UA_LocalizedText_copy(src: &srchead->description, dst: &dsthead->description);
21041 dsthead->writeMask = srchead->writeMask;
21042 dsthead->context = srchead->context;
21043 dsthead->constructed = srchead->constructed;
21044#ifdef UA_ENABLE_SUBSCRIPTIONS
21045 dsthead->monitoredItems = srchead->monitoredItems;
21046#endif
21047 if(retval != UA_STATUSCODE_GOOD) {
21048 UA_Node_clear(node: dst);
21049 return retval;
21050 }
21051
21052 /* Copy the references */
21053 dsthead->references = NULL;
21054 if(srchead->referencesSize > 0) {
21055 dsthead->references = (UA_NodeReferenceKind*)
21056 UA_calloc(nmemb: srchead->referencesSize, size: sizeof(UA_NodeReferenceKind));
21057 if(!dsthead->references) {
21058 UA_Node_clear(node: dst);
21059 return UA_STATUSCODE_BADOUTOFMEMORY;
21060 }
21061 dsthead->referencesSize = srchead->referencesSize;
21062
21063 for(size_t i = 0; i < srchead->referencesSize; ++i) {
21064 UA_NodeReferenceKind *srefs = &srchead->references[i];
21065 UA_NodeReferenceKind *drefs = &dsthead->references[i];
21066 drefs->referenceTypeIndex = srefs->referenceTypeIndex;
21067 drefs->isInverse = srefs->isInverse;
21068 drefs->hasRefTree = srefs->hasRefTree; /* initially empty */
21069
21070 /* Copy all the targets */
21071 const UA_ReferenceTarget *t = NULL;
21072 while((t = UA_NodeReferenceKind_iterate(rk: srefs, prev: t))) {
21073 retval = addReferenceTarget(refs: drefs, target: t->targetId, targetNameHash: t->targetNameHash);
21074 if(retval != UA_STATUSCODE_GOOD) {
21075 UA_Node_clear(node: dst);
21076 return retval;
21077 }
21078 }
21079 }
21080 }
21081
21082 /* Copy unique content of the nodeclass */
21083 switch(src->head.nodeClass) {
21084 case UA_NODECLASS_OBJECT:
21085 retval = UA_ObjectNode_copy(src: &src->objectNode, dst: &dst->objectNode);
21086 break;
21087 case UA_NODECLASS_VARIABLE:
21088 retval = UA_VariableNode_copy(src: &src->variableNode, dst: &dst->variableNode);
21089 break;
21090 case UA_NODECLASS_METHOD:
21091 retval = UA_MethodNode_copy(src: &src->methodNode, dst: &dst->methodNode);
21092 break;
21093 case UA_NODECLASS_OBJECTTYPE:
21094 retval = UA_ObjectTypeNode_copy(src: &src->objectTypeNode, dst: &dst->objectTypeNode);
21095 break;
21096 case UA_NODECLASS_VARIABLETYPE:
21097 retval = UA_VariableTypeNode_copy(src: &src->variableTypeNode, dst: &dst->variableTypeNode);
21098 break;
21099 case UA_NODECLASS_REFERENCETYPE:
21100 retval = UA_ReferenceTypeNode_copy(src: &src->referenceTypeNode, dst: &dst->referenceTypeNode);
21101 break;
21102 case UA_NODECLASS_DATATYPE:
21103 retval = UA_DataTypeNode_copy(src: &src->dataTypeNode, dst: &dst->dataTypeNode);
21104 break;
21105 case UA_NODECLASS_VIEW:
21106 retval = UA_ViewNode_copy(src: &src->viewNode, dst: &dst->viewNode);
21107 break;
21108 default:
21109 break;
21110 }
21111
21112 if(retval != UA_STATUSCODE_GOOD)
21113 UA_Node_clear(node: dst);
21114
21115 return retval;
21116}
21117
21118UA_Node *
21119UA_Node_copy_alloc(const UA_Node *src) {
21120 size_t nodesize = 0;
21121 switch(src->head.nodeClass) {
21122 case UA_NODECLASS_OBJECT:
21123 nodesize = sizeof(UA_ObjectNode);
21124 break;
21125 case UA_NODECLASS_VARIABLE:
21126 nodesize = sizeof(UA_VariableNode);
21127 break;
21128 case UA_NODECLASS_METHOD:
21129 nodesize = sizeof(UA_MethodNode);
21130 break;
21131 case UA_NODECLASS_OBJECTTYPE:
21132 nodesize = sizeof(UA_ObjectTypeNode);
21133 break;
21134 case UA_NODECLASS_VARIABLETYPE:
21135 nodesize = sizeof(UA_VariableTypeNode);
21136 break;
21137 case UA_NODECLASS_REFERENCETYPE:
21138 nodesize = sizeof(UA_ReferenceTypeNode);
21139 break;
21140 case UA_NODECLASS_DATATYPE:
21141 nodesize = sizeof(UA_DataTypeNode);
21142 break;
21143 case UA_NODECLASS_VIEW:
21144 nodesize = sizeof(UA_ViewNode);
21145 break;
21146 default:
21147 return NULL;
21148 }
21149
21150 UA_Node *dst = (UA_Node*)UA_calloc(nmemb: 1, size: nodesize);
21151 if(!dst)
21152 return NULL;
21153
21154 dst->head.nodeClass = src->head.nodeClass;
21155
21156 UA_StatusCode retval = UA_Node_copy(src, dst);
21157 if(retval != UA_STATUSCODE_GOOD) {
21158 UA_free(ptr: dst);
21159 return NULL;
21160 }
21161 return dst;
21162}
21163/******************************/
21164/* Copy Attributes into Nodes */
21165/******************************/
21166
21167static UA_StatusCode
21168copyStandardAttributes(UA_NodeHead *head, const UA_NodeAttributes *attr) {
21169 /* UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); */
21170 /* UA_QualifiedName_copy(&item->browseName, &node->browseName); */
21171
21172 head->writeMask = attr->writeMask;
21173 UA_StatusCode retval = UA_LocalizedText_copy(src: &attr->description, dst: &head->description);
21174 /* The new nodeset format has optional display names:
21175 * https://github.com/open62541/open62541/issues/2627. If the display name
21176 * is NULL, take the name part of the browse name */
21177 if(attr->displayName.text.length == 0)
21178 retval |= UA_String_copy(src: &head->browseName.name, dst: &head->displayName.text);
21179 else
21180 retval |= UA_LocalizedText_copy(src: &attr->displayName, dst: &head->displayName);
21181 return retval;
21182}
21183
21184static UA_StatusCode
21185copyCommonVariableAttributes(UA_VariableNode *node,
21186 const UA_VariableAttributes *attr) {
21187 /* Copy the array dimensions */
21188 UA_StatusCode retval =
21189 UA_Array_copy(src: attr->arrayDimensions, size: attr->arrayDimensionsSize,
21190 dst: (void**)&node->arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
21191 if(retval != UA_STATUSCODE_GOOD)
21192 return retval;
21193 node->arrayDimensionsSize = attr->arrayDimensionsSize;
21194
21195 /* Data type and value rank */
21196 retval = UA_NodeId_copy(src: &attr->dataType, dst: &node->dataType);
21197 if(retval != UA_STATUSCODE_GOOD)
21198 return retval;
21199 node->valueRank = attr->valueRank;
21200
21201 /* Copy the value */
21202 retval = UA_Variant_copy(src: &attr->value, dst: &node->value.data.value.value);
21203 node->valueSource = UA_VALUESOURCE_DATA;
21204 node->value.data.value.hasValue = (node->value.data.value.value.type != NULL);
21205
21206 return retval;
21207}
21208
21209static UA_StatusCode
21210copyVariableNodeAttributes(UA_VariableNode *vnode,
21211 const UA_VariableAttributes *attr) {
21212 vnode->accessLevel = attr->accessLevel;
21213 vnode->historizing = attr->historizing;
21214 vnode->minimumSamplingInterval = attr->minimumSamplingInterval;
21215 return copyCommonVariableAttributes(node: vnode, attr);
21216}
21217
21218static UA_StatusCode
21219copyVariableTypeNodeAttributes(UA_VariableTypeNode *vtnode,
21220 const UA_VariableTypeAttributes *attr) {
21221 vtnode->isAbstract = attr->isAbstract;
21222 return copyCommonVariableAttributes(node: (UA_VariableNode*)vtnode,
21223 attr: (const UA_VariableAttributes*)attr);
21224}
21225
21226static UA_StatusCode
21227copyObjectNodeAttributes(UA_ObjectNode *onode, const UA_ObjectAttributes *attr) {
21228 onode->eventNotifier = attr->eventNotifier;
21229 return UA_STATUSCODE_GOOD;
21230}
21231
21232static UA_StatusCode
21233copyReferenceTypeNodeAttributes(UA_ReferenceTypeNode *rtnode,
21234 const UA_ReferenceTypeAttributes *attr) {
21235 rtnode->isAbstract = attr->isAbstract;
21236 rtnode->symmetric = attr->symmetric;
21237 return UA_LocalizedText_copy(src: &attr->inverseName, dst: &rtnode->inverseName);
21238}
21239
21240static UA_StatusCode
21241copyObjectTypeNodeAttributes(UA_ObjectTypeNode *otnode,
21242 const UA_ObjectTypeAttributes *attr) {
21243 otnode->isAbstract = attr->isAbstract;
21244 return UA_STATUSCODE_GOOD;
21245}
21246
21247static UA_StatusCode
21248copyViewNodeAttributes(UA_ViewNode *vnode, const UA_ViewAttributes *attr) {
21249 vnode->containsNoLoops = attr->containsNoLoops;
21250 vnode->eventNotifier = attr->eventNotifier;
21251 return UA_STATUSCODE_GOOD;
21252}
21253
21254static UA_StatusCode
21255copyDataTypeNodeAttributes(UA_DataTypeNode *dtnode,
21256 const UA_DataTypeAttributes *attr) {
21257 dtnode->isAbstract = attr->isAbstract;
21258 return UA_STATUSCODE_GOOD;
21259}
21260
21261static UA_StatusCode
21262copyMethodNodeAttributes(UA_MethodNode *mnode,
21263 const UA_MethodAttributes *attr) {
21264 mnode->executable = attr->executable;
21265 return UA_STATUSCODE_GOOD;
21266}
21267
21268#define CHECK_ATTRIBUTES(TYPE) \
21269 if(attributeType != &UA_TYPES[UA_TYPES_##TYPE]) { \
21270 retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID; \
21271 break; \
21272 }
21273
21274UA_StatusCode
21275UA_Node_setAttributes(UA_Node *node, const void *attributes, const UA_DataType *attributeType) {
21276 /* Copy the attributes into the node */
21277 UA_StatusCode retval = UA_STATUSCODE_GOOD;
21278 switch(node->head.nodeClass) {
21279 case UA_NODECLASS_OBJECT:
21280 CHECK_ATTRIBUTES(OBJECTATTRIBUTES);
21281 retval = copyObjectNodeAttributes(onode: &node->objectNode,
21282 attr: (const UA_ObjectAttributes*)attributes);
21283 break;
21284 case UA_NODECLASS_VARIABLE:
21285 CHECK_ATTRIBUTES(VARIABLEATTRIBUTES);
21286 retval = copyVariableNodeAttributes(vnode: &node->variableNode,
21287 attr: (const UA_VariableAttributes*)attributes);
21288 break;
21289 case UA_NODECLASS_OBJECTTYPE:
21290 CHECK_ATTRIBUTES(OBJECTTYPEATTRIBUTES);
21291 retval = copyObjectTypeNodeAttributes(otnode: &node->objectTypeNode,
21292 attr: (const UA_ObjectTypeAttributes*)attributes);
21293 break;
21294 case UA_NODECLASS_VARIABLETYPE:
21295 CHECK_ATTRIBUTES(VARIABLETYPEATTRIBUTES);
21296 retval = copyVariableTypeNodeAttributes(vtnode: &node->variableTypeNode,
21297 attr: (const UA_VariableTypeAttributes*)attributes);
21298 break;
21299 case UA_NODECLASS_REFERENCETYPE:
21300 CHECK_ATTRIBUTES(REFERENCETYPEATTRIBUTES);
21301 retval = copyReferenceTypeNodeAttributes(rtnode: &node->referenceTypeNode,
21302 attr: (const UA_ReferenceTypeAttributes*)attributes);
21303 break;
21304 case UA_NODECLASS_DATATYPE:
21305 CHECK_ATTRIBUTES(DATATYPEATTRIBUTES);
21306 retval = copyDataTypeNodeAttributes(dtnode: &node->dataTypeNode,
21307 attr: (const UA_DataTypeAttributes*)attributes);
21308 break;
21309 case UA_NODECLASS_VIEW:
21310 CHECK_ATTRIBUTES(VIEWATTRIBUTES);
21311 retval = copyViewNodeAttributes(vnode: &node->viewNode, attr: (const UA_ViewAttributes*)attributes);
21312 break;
21313 case UA_NODECLASS_METHOD:
21314 CHECK_ATTRIBUTES(METHODATTRIBUTES);
21315 retval = copyMethodNodeAttributes(mnode: &node->methodNode, attr: (const UA_MethodAttributes*)attributes);
21316 break;
21317 case UA_NODECLASS_UNSPECIFIED:
21318 default:
21319 retval = UA_STATUSCODE_BADNODECLASSINVALID;
21320 }
21321
21322 if(retval == UA_STATUSCODE_GOOD)
21323 retval = copyStandardAttributes(head: &node->head, attr: (const UA_NodeAttributes*)attributes);
21324 if(retval != UA_STATUSCODE_GOOD)
21325 UA_Node_clear(node);
21326 return retval;
21327}
21328
21329/*********************/
21330/* Manage References */
21331/*********************/
21332
21333static UA_StatusCode
21334addReferenceTarget(UA_NodeReferenceKind *rk, UA_NodePointer targetId,
21335 UA_UInt32 targetNameHash) {
21336 /* Insert into array */
21337 if(!rk->hasRefTree) {
21338 UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
21339 UA_realloc(ptr: rk->targets.array,
21340 size: sizeof(UA_ReferenceTarget) * (rk->targetsSize + 1));
21341 if(!newRefs)
21342 return UA_STATUSCODE_BADOUTOFMEMORY;
21343 rk->targets.array = newRefs;
21344
21345 UA_StatusCode retval =
21346 UA_NodePointer_copy(in: targetId,
21347 out: &rk->targets.array[rk->targetsSize].targetId);
21348 rk->targets.array[rk->targetsSize].targetNameHash = targetNameHash;
21349 if(retval != UA_STATUSCODE_GOOD) {
21350 if(rk->targetsSize == 0) {
21351 UA_free(ptr: rk->targets.array);
21352 rk->targets.array = NULL;
21353 }
21354 return retval;
21355 }
21356 rk->targetsSize++;
21357 return UA_STATUSCODE_GOOD;
21358 }
21359
21360 /* Insert into tree */
21361 UA_ReferenceTargetTreeElem *entry = (UA_ReferenceTargetTreeElem*)
21362 UA_malloc(size: sizeof(UA_ReferenceTargetTreeElem));
21363 if(!entry)
21364 return UA_STATUSCODE_BADOUTOFMEMORY;
21365
21366 UA_StatusCode retval =
21367 UA_NodePointer_copy(in: targetId, out: &entry->target.targetId);
21368 if(retval != UA_STATUSCODE_GOOD) {
21369 UA_free(ptr: entry);
21370 return retval;
21371 }
21372
21373 /* <-- The point of no return --> */
21374
21375 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: targetId);
21376 entry->targetIdHash = UA_ExpandedNodeId_hash(n: &en);
21377 entry->target.targetNameHash = targetNameHash;
21378
21379 /* Insert to the id lookup binary search tree. Only the root is kept in refs
21380 * to save space. */
21381 struct aa_head _refIdTree = refIdTree;
21382 _refIdTree.root = rk->targets.tree.idTreeRoot;
21383 aa_insert(head: &_refIdTree, elem: entry);
21384 rk->targets.tree.idTreeRoot = _refIdTree.root;
21385
21386 /* Insert to the name lookup binary search tree */
21387 struct aa_head _refNameTree = refNameTree;
21388 _refNameTree.root = rk->targets.tree.nameTreeRoot;
21389 aa_insert(head: &_refNameTree, elem: entry);
21390 rk->targets.tree.nameTreeRoot = _refNameTree.root;
21391
21392 rk->targetsSize++;
21393
21394 return UA_STATUSCODE_GOOD;
21395}
21396
21397static UA_StatusCode
21398addReferenceKind(UA_NodeHead *head, UA_Byte refTypeIndex, UA_Boolean isForward,
21399 const UA_NodePointer target, UA_UInt32 targetBrowseNameHash) {
21400 UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
21401 UA_realloc(ptr: head->references,
21402 size: sizeof(UA_NodeReferenceKind) * (head->referencesSize+1));
21403 if(!refs)
21404 return UA_STATUSCODE_BADOUTOFMEMORY;
21405 head->references = refs;
21406
21407 UA_NodeReferenceKind *newRef = &refs[head->referencesSize];
21408 memset(s: newRef, c: 0, n: sizeof(UA_NodeReferenceKind));
21409 newRef->referenceTypeIndex = refTypeIndex;
21410 newRef->isInverse = !isForward;
21411 UA_StatusCode retval =
21412 addReferenceTarget(rk: newRef, targetId: target, targetNameHash: targetBrowseNameHash);
21413 if(retval != UA_STATUSCODE_GOOD) {
21414 if(head->referencesSize == 0) {
21415 UA_free(ptr: head->references);
21416 head->references = NULL;
21417 }
21418 return retval;
21419 }
21420
21421 head->referencesSize++;
21422 return UA_STATUSCODE_GOOD;
21423}
21424
21425UA_StatusCode
21426UA_Node_addReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
21427 const UA_ExpandedNodeId *targetNodeId,
21428 UA_UInt32 targetBrowseNameHash) {
21429 /* Find the matching reference kind */
21430 for(size_t i = 0; i < node->head.referencesSize; ++i) {
21431 UA_NodeReferenceKind *refs = &node->head.references[i];
21432
21433 /* Reference direction does not match */
21434 if(refs->isInverse == isForward)
21435 continue;
21436
21437 /* Reference type does not match */
21438 if(refs->referenceTypeIndex != refTypeIndex)
21439 continue;
21440
21441 /* Does an identical reference already exist? */
21442 const UA_ReferenceTarget *found =
21443 UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId);
21444 if(found)
21445 return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
21446
21447 /* Add to existing ReferenceKind */
21448 return addReferenceTarget(rk: refs, targetId: UA_NodePointer_fromExpandedNodeId(id: targetNodeId),
21449 targetNameHash: targetBrowseNameHash);
21450 }
21451
21452 /* Add new ReferenceKind for the target */
21453 return addReferenceKind(head: &node->head, refTypeIndex, isForward,
21454 target: UA_NodePointer_fromExpandedNodeId(id: targetNodeId),
21455 targetBrowseNameHash);
21456
21457}
21458
21459UA_StatusCode
21460UA_Node_deleteReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward,
21461 const UA_ExpandedNodeId *targetNodeId) {
21462 struct aa_head _refIdTree = refIdTree;
21463 struct aa_head _refNameTree = refNameTree;
21464
21465 UA_NodeHead *head = &node->head;
21466 for(size_t i = 0; i < head->referencesSize; i++) {
21467 UA_NodeReferenceKind *refs = &head->references[i];
21468 if(isForward == refs->isInverse)
21469 continue;
21470 if(refTypeIndex != refs->referenceTypeIndex)
21471 continue;
21472
21473 /* Cast out the const qualifier (hack!) */
21474 UA_ReferenceTarget *target = (UA_ReferenceTarget*)(uintptr_t)
21475 UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId);
21476 if(!target)
21477 continue;
21478
21479 /* Ok, delete the reference. Cannot fail */
21480 refs->targetsSize--;
21481
21482 if(!refs->hasRefTree) {
21483 /* Remove from array */
21484 UA_NodePointer_clear(np: &target->targetId);
21485
21486 /* Elements remaining. Realloc. */
21487 if(refs->targetsSize > 0) {
21488 if(target != &refs->targets.array[refs->targetsSize])
21489 *target = refs->targets.array[refs->targetsSize];
21490 UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*)
21491 UA_realloc(ptr: refs->targets.array,
21492 size: sizeof(UA_ReferenceTarget) * refs->targetsSize);
21493 if(newRefs)
21494 refs->targets.array = newRefs;
21495 return UA_STATUSCODE_GOOD; /* Realloc allowed to fail */
21496 }
21497
21498 /* Remove the last target. Remove the ReferenceKind below */
21499 UA_free(ptr: refs->targets.array);
21500 } else {
21501 /* Remove from the tree */
21502 _refIdTree.root = refs->targets.tree.idTreeRoot;
21503 aa_remove(head: &_refIdTree, elem: target);
21504 refs->targets.tree.idTreeRoot = _refIdTree.root;
21505
21506 _refNameTree.root = refs->targets.tree.nameTreeRoot;
21507 aa_remove(head: &_refNameTree, elem: target);
21508 refs->targets.tree.nameTreeRoot = _refNameTree.root;
21509
21510 UA_NodePointer_clear(np: &target->targetId);
21511 UA_free(ptr: target);
21512 if(refs->targets.tree.idTreeRoot)
21513 return UA_STATUSCODE_GOOD; /* At least one target remains */
21514 }
21515
21516 /* No targets remaining. Remove the ReferenceKind. */
21517 head->referencesSize--;
21518 if(head->referencesSize > 0) {
21519 /* No target for the ReferenceType remaining. Remove and shrink down
21520 * allocated buffer. Ignore errors in case memory buffer could not
21521 * be shrinked down. */
21522 if(i != head->referencesSize)
21523 head->references[i] = head->references[node->head.referencesSize];
21524 UA_NodeReferenceKind *newRefs = (UA_NodeReferenceKind*)
21525 UA_realloc(ptr: head->references,
21526 size: sizeof(UA_NodeReferenceKind) * head->referencesSize);
21527 if(newRefs)
21528 head->references = newRefs;
21529 } else {
21530 /* No remaining references of any ReferenceType */
21531 UA_free(ptr: head->references);
21532 head->references = NULL;
21533 }
21534 return UA_STATUSCODE_GOOD;
21535 }
21536 return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED;
21537}
21538
21539void
21540UA_Node_deleteReferencesSubset(UA_Node *node, const UA_ReferenceTypeSet *keepSet) {
21541 UA_NodeHead *head = &node->head;
21542 struct aa_head _refIdTree = refIdTree;
21543 for(size_t i = 0; i < head->referencesSize; i++) {
21544 /* Keep the references of this type? */
21545 UA_NodeReferenceKind *refs = &head->references[i];
21546 if(UA_ReferenceTypeSet_contains(set: keepSet, index: refs->referenceTypeIndex))
21547 continue;
21548
21549 /* Remove all target entries. Don't remove entries from browseName tree.
21550 * The entire ReferenceKind will be removed anyway. */
21551 if(!refs->hasRefTree) {
21552 for(size_t j = 0; j < refs->targetsSize; j++)
21553 UA_NodePointer_clear(np: &refs->targets.array[j].targetId);
21554 UA_free(ptr: refs->targets.array);
21555 } else {
21556 _refIdTree.root = refs->targets.tree.idTreeRoot;
21557 while(_refIdTree.root) {
21558 UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)
21559 ((uintptr_t)_refIdTree.root -
21560 offsetof(UA_ReferenceTargetTreeElem, idTreeEntry));
21561 aa_remove(head: &_refIdTree, elem);
21562 UA_NodePointer_clear(np: &elem->target.targetId);
21563 UA_free(ptr: elem);
21564 }
21565 }
21566
21567 /* Move last references-kind entry to this position. Don't memcpy over
21568 * the same position. Decrease i to repeat at this location. */
21569 head->referencesSize--;
21570 if(i != head->referencesSize) {
21571 head->references[i] = head->references[head->referencesSize];
21572 i--;
21573 }
21574 }
21575
21576 if(head->referencesSize > 0) {
21577 /* Realloc to save memory. Ignore if realloc fails. */
21578 UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*)
21579 UA_realloc(ptr: head->references,
21580 size: sizeof(UA_NodeReferenceKind) * head->referencesSize);
21581 if(refs)
21582 head->references = refs;
21583 } else {
21584 /* The array is empty. Remove. */
21585 UA_free(ptr: head->references);
21586 head->references = NULL;
21587 }
21588}
21589
21590void UA_Node_deleteReferences(UA_Node *node) {
21591 UA_ReferenceTypeSet noRefs;
21592 UA_ReferenceTypeSet_init(set: &noRefs);
21593 UA_Node_deleteReferencesSubset(node, keepSet: &noRefs);
21594}
21595
21596/**** amalgamated original file "/src/server/ua_server.c" ****/
21597
21598/* This Source Code Form is subject to the terms of the Mozilla Public
21599 * License, v. 2.0. If a copy of the MPL was not distributed with this
21600 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
21601 *
21602 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
21603 * Copyright 2014-2017 (c) Florian Palm
21604 * Copyright 2015-2016 (c) Sten Grüner
21605 * Copyright 2015-2016 (c) Chris Iatrou
21606 * Copyright 2015 (c) LEvertz
21607 * Copyright 2015-2016 (c) Oleksiy Vasylyev
21608 * Copyright 2016 (c) Julian Grothoff
21609 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
21610 * Copyright 2016 (c) Lorenz Haas
21611 * Copyright 2017 (c) frax2222
21612 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
21613 * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
21614 * Copyright 2019 (c) Kalycito Infotech Private Limited
21615 * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
21616 * Copyright 2022 (c) Fraunhofer IOSB (Author: Andreas Ebner)
21617 */
21618
21619
21620#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
21621#endif
21622
21623
21624#ifdef UA_ENABLE_SUBSCRIPTIONS
21625#endif
21626
21627#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
21628#include <valgrind/memcheck.h>
21629#endif
21630
21631#define STARTCHANNELID 1
21632#define STARTTOKENID 1
21633
21634/**********************/
21635/* Namespace Handling */
21636/**********************/
21637
21638/* The NS1 Uri can be changed by the user to some custom string. This method is
21639 * called to initialize the NS1 Uri if it is not set before to the default
21640 * Application URI.
21641 *
21642 * This is done as soon as the Namespace Array is read or written via node value
21643 * read / write services, or UA_Server_addNamespace, or UA_Server_getNamespaceByIndex
21644 * UA_Server_getNamespaceByName or UA_Server_run_startup is called.
21645 *
21646 * Therefore one has to set the custom NS1 URI before one of the previously
21647 * mentioned steps. */
21648void
21649setupNs1Uri(UA_Server *server) {
21650 if(!server->namespaces[1].data) {
21651 UA_String_copy(src: &server->config.applicationDescription.applicationUri,
21652 dst: &server->namespaces[1]);
21653 }
21654}
21655
21656UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
21657 /* ensure that the uri for ns1 is set up from the app description */
21658 setupNs1Uri(server);
21659
21660 /* Check if the namespace already exists in the server's namespace array */
21661 for(UA_UInt16 i = 0; i < server->namespacesSize; ++i) {
21662 if(UA_String_equal(s1: &name, s2: &server->namespaces[i]))
21663 return i;
21664 }
21665
21666 /* Make the array bigger */
21667 UA_String *newNS = (UA_String*)UA_realloc(ptr: server->namespaces,
21668 size: sizeof(UA_String) * (server->namespacesSize + 1));
21669 UA_CHECK_MEM(newNS, return 0);
21670
21671 server->namespaces = newNS;
21672
21673 /* Copy the namespace string */
21674 UA_StatusCode retval = UA_String_copy(src: &name, dst: &server->namespaces[server->namespacesSize]);
21675 UA_CHECK_STATUS(retval, return 0);
21676
21677 /* Announce the change (otherwise, the array appears unchanged) */
21678 ++server->namespacesSize;
21679 return (UA_UInt16)(server->namespacesSize - 1);
21680}
21681
21682UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
21683 /* Override const attribute to get string (dirty hack) */
21684 UA_String nameString;
21685 nameString.length = strlen(s: name);
21686 nameString.data = (UA_Byte*)(uintptr_t)name;
21687 UA_LOCK(&server->serviceMutex);
21688 UA_UInt16 retVal = addNamespace(server, name: nameString);
21689 UA_UNLOCK(&server->serviceMutex);
21690 return retVal;
21691}
21692
21693UA_ServerConfig*
21694UA_Server_getConfig(UA_Server *server) {
21695 UA_CHECK_MEM(server, return NULL);
21696 return &server->config;
21697}
21698
21699UA_StatusCode
21700getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
21701 size_t *foundIndex) {
21702 /* ensure that the uri for ns1 is set up from the app description */
21703 setupNs1Uri(server);
21704 UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
21705 for(size_t idx = 0; idx < server->namespacesSize; idx++) {
21706 if(UA_String_equal(s1: &server->namespaces[idx], s2: &namespaceUri)) {
21707 (*foundIndex) = idx;
21708 res = UA_STATUSCODE_GOOD;
21709 break;
21710 }
21711 }
21712 return res;
21713}
21714
21715UA_StatusCode
21716getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
21717 UA_String *foundUri) {
21718 /* ensure that the uri for ns1 is set up from the app description */
21719 setupNs1Uri(server);
21720 UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
21721 if(namespaceIndex >= server->namespacesSize)
21722 return res;
21723 res = UA_String_copy(src: &server->namespaces[namespaceIndex], dst: foundUri);
21724 return res;
21725}
21726
21727UA_StatusCode
21728UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
21729 size_t *foundIndex) {
21730 UA_LOCK(&server->serviceMutex);
21731 UA_StatusCode res = getNamespaceByName(server, namespaceUri, foundIndex);
21732 UA_UNLOCK(&server->serviceMutex);
21733 return res;
21734}
21735
21736UA_StatusCode
21737UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
21738 UA_String *foundUri) {
21739 UA_LOCK(&server->serviceMutex);
21740 UA_StatusCode res = getNamespaceByIndex(server, namespaceIndex, foundUri);
21741 UA_UNLOCK(&server->serviceMutex);
21742 return res;
21743}
21744
21745UA_StatusCode
21746UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
21747 UA_NodeIteratorCallback callback, void *handle) {
21748 UA_BrowseDescription bd;
21749 UA_BrowseDescription_init(p: &bd);
21750 bd.nodeId = parentNodeId;
21751 bd.browseDirection = UA_BROWSEDIRECTION_BOTH;
21752 bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_ISFORWARD;
21753
21754 UA_BrowseResult br = UA_Server_browse(server, maxReferences: 0, bd: &bd);
21755 UA_StatusCode res = br.statusCode;
21756 UA_CHECK_STATUS(res, goto cleanup);
21757
21758 for(size_t i = 0; i < br.referencesSize; i++) {
21759 if(!UA_ExpandedNodeId_isLocal(n: &br.references[i].nodeId))
21760 continue;
21761 res = callback(br.references[i].nodeId.nodeId, !br.references[i].isForward,
21762 br.references[i].referenceTypeId, handle);
21763 UA_CHECK_STATUS(res, goto cleanup);
21764 }
21765cleanup:
21766 UA_BrowseResult_clear(p: &br);
21767 return res;
21768}
21769
21770/********************/
21771/* Server Lifecycle */
21772/********************/
21773
21774static void
21775serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
21776 void *callbackApplication, void *data);
21777
21778/* The server needs to be stopped before it can be deleted */
21779void UA_Server_delete(UA_Server *server) {
21780 UA_LOCK(&server->serviceMutex);
21781
21782 UA_Server_deleteSecureChannels(server);
21783 session_list_entry *current, *temp;
21784 LIST_FOREACH_SAFE(current, &server->sessions, pointers, temp) {
21785 UA_Server_removeSession(server, sentry: current, event: UA_DIAGNOSTICEVENT_CLOSE);
21786 }
21787 UA_Array_delete(p: server->namespaces, size: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]);
21788
21789#ifdef UA_ENABLE_SUBSCRIPTIONS
21790 UA_MonitoredItem *mon, *mon_tmp;
21791 LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
21792 LIST_REMOVE(mon, listEntry);
21793 UA_MonitoredItem_delete(server, monitoredItem: mon);
21794 }
21795
21796 /* Remove subscriptions without a session */
21797 UA_Subscription *sub, *sub_tmp;
21798 LIST_FOREACH_SAFE(sub, &server->subscriptions, serverListEntry, sub_tmp) {
21799 UA_Subscription_delete(server, sub);
21800 }
21801 UA_assert(server->monitoredItemsSize == 0);
21802 UA_assert(server->subscriptionsSize == 0);
21803
21804#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
21805 UA_ConditionList_delete(server);
21806#endif
21807
21808#endif
21809
21810#ifdef UA_ENABLE_PUBSUB
21811 UA_PubSubManager_delete(server, &server->pubSubManager);
21812#endif
21813
21814#ifdef UA_ENABLE_DISCOVERY
21815 UA_DiscoveryManager_clear(&server->discoveryManager, server);
21816#endif
21817
21818#if UA_MULTITHREADING >= 100
21819 UA_AsyncManager_clear(&server->asyncManager, server);
21820#endif
21821
21822 /* Clean up the Admin Session */
21823 UA_Session_clear(session: &server->adminSession, server);
21824
21825 UA_UNLOCK(&server->serviceMutex); /* The timer has its own mutex */
21826
21827 /* Execute all remaining delayed events and clean up the timer */
21828 UA_Timer_process(t: &server->timer, nowMonotonic: UA_DateTime_nowMonotonic() + 1,
21829 executionCallback: (UA_TimerExecutionCallback)serverExecuteRepeatedCallback, executionApplication: server);
21830 UA_Timer_clear(t: &server->timer);
21831
21832 /* Clean up the config */
21833 UA_ServerConfig_clean(config: &server->config);
21834
21835#if UA_MULTITHREADING >= 100
21836 UA_LOCK_DESTROY(&server->networkMutex);
21837 UA_LOCK_DESTROY(&server->serviceMutex);
21838#endif
21839
21840 /* Delete the server itself */
21841 UA_free(ptr: server);
21842}
21843
21844/* Recurring cleanup. Removing unused and timed-out channels and sessions */
21845static void
21846UA_Server_cleanup(UA_Server *server, void *_) {
21847 UA_LOCK(&server->serviceMutex);
21848 UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic();
21849 UA_Server_cleanupSessions(server, nowMonotonic);
21850 UA_Server_cleanupTimedOutSecureChannels(server, nowMonotonic);
21851#ifdef UA_ENABLE_DISCOVERY
21852 UA_Discovery_cleanupTimedOut(server, nowMonotonic);
21853#endif
21854 UA_UNLOCK(&server->serviceMutex);
21855}
21856
21857/********************/
21858/* Server Lifecycle */
21859/********************/
21860
21861static
21862UA_INLINE
21863UA_Boolean UA_Server_NodestoreIsConfigured(UA_Server *server) {
21864 return server->config.nodestore.getNode != NULL;
21865}
21866
21867static UA_Server *
21868UA_Server_init(UA_Server *server) {
21869
21870 UA_StatusCode res = UA_STATUSCODE_GOOD;
21871 UA_CHECK_FATAL(UA_Server_NodestoreIsConfigured(server), goto cleanup,
21872 &server->config.logger, UA_LOGCATEGORY_SERVER,
21873 "No Nodestore configured in the server"
21874 );
21875
21876 /* Init start time to zero, the actual start time will be sampled in
21877 * UA_Server_run_startup() */
21878 server->startTime = 0;
21879
21880 /* Set a seed for non-cyptographic randomness */
21881#ifndef UA_ENABLE_DETERMINISTIC_RNG
21882 UA_random_seed(seed: (UA_UInt64)UA_DateTime_now());
21883#endif
21884
21885#if UA_MULTITHREADING >= 100
21886 UA_LOCK_INIT(&server->networkMutex);
21887 UA_LOCK_INIT(&server->serviceMutex);
21888#endif
21889
21890 /* Initialize the handling of repeated callbacks */
21891 UA_Timer_init(t: &server->timer);
21892
21893 /* Initialize the adminSession */
21894 UA_Session_init(session: &server->adminSession);
21895 server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID;
21896 server->adminSession.sessionId.identifier.guid.data1 = 1;
21897 server->adminSession.validTill = UA_INT64_MAX;
21898 server->adminSession.sessionName = UA_STRING_ALLOC("Administrator");
21899
21900 /* Create Namespaces 0 and 1
21901 * Ns1 will be filled later with the uri from the app description */
21902 server->namespaces = (UA_String *)UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_STRING]);
21903 UA_CHECK_MEM(server->namespaces, goto cleanup);
21904
21905 server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
21906 server->namespaces[1] = UA_STRING_NULL;
21907 server->namespacesSize = 2;
21908
21909 /* Initialize SecureChannel */
21910 TAILQ_INIT(&server->channels);
21911 /* TODO: use an ID that is likely to be unique after a restart */
21912 server->lastChannelId = STARTCHANNELID;
21913 server->lastTokenId = STARTTOKENID;
21914
21915 /* Initialize Session Management */
21916 LIST_INIT(&server->sessions);
21917 server->sessionCount = 0;
21918
21919#if UA_MULTITHREADING >= 100
21920 UA_AsyncManager_init(&server->asyncManager, server);
21921#endif
21922
21923 /* Initialized discovery */
21924#ifdef UA_ENABLE_DISCOVERY
21925 UA_DiscoveryManager_init(&server->discoveryManager, server);
21926#endif
21927
21928 /* Add a regular callback for cleanup and maintenance. With a 10s interval. */
21929 UA_Server_addRepeatedCallback(server, callback: (UA_ServerCallback)UA_Server_cleanup, NULL,
21930 interval_ms: 10000.0, NULL);
21931
21932 /* Initialize namespace 0*/
21933 res = UA_Server_initNS0(server);
21934 UA_CHECK_STATUS(res, goto cleanup);
21935
21936#ifdef UA_ENABLE_PUBSUB
21937 /* Build PubSub information model */
21938#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
21939 UA_Server_initPubSubNS0(server);
21940#endif
21941
21942#ifdef UA_ENABLE_PUBSUB_MONITORING
21943 /* setup default PubSub monitoring callbacks */
21944 res = UA_PubSubManager_setDefaultMonitoringCallbacks(&server->config.pubSubConfig.monitoringInterface);
21945 UA_CHECK_STATUS(res, goto cleanup);
21946#endif /* UA_ENABLE_PUBSUB_MONITORING */
21947#endif /* UA_ENABLE_PUBSUB */
21948 return server;
21949
21950 cleanup:
21951 UA_Server_delete(server);
21952 return NULL;
21953}
21954
21955UA_Server *
21956UA_Server_newWithConfig(UA_ServerConfig *config) {
21957 UA_CHECK_MEM(config, return NULL);
21958
21959 UA_Server *server = (UA_Server *)UA_calloc(nmemb: 1, size: sizeof(UA_Server));
21960 UA_CHECK_MEM(server, UA_ServerConfig_clean(config); return NULL);
21961
21962 server->config = *config;
21963 /* The config might have been "moved" into the server struct. Ensure that
21964 * the logger pointer is correct. */
21965 for(size_t i = 0; i < server->config.securityPoliciesSize; i++)
21966 server->config.securityPolicies[i].logger = &server->config.logger;
21967
21968 /* Reset the old config */
21969 memset(s: config, c: 0, n: sizeof(UA_ServerConfig));
21970 return UA_Server_init(server);
21971}
21972
21973/* Returns if the server should be shut down immediately */
21974static UA_Boolean
21975setServerShutdown(UA_Server *server) {
21976 if(server->endTime != 0)
21977 return false;
21978 if(server->config.shutdownDelay == 0)
21979 return true;
21980 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
21981 msg: "Shutting down the server with a delay of %i ms", (int)server->config.shutdownDelay);
21982 server->endTime = UA_DateTime_now() + (UA_DateTime)(server->config.shutdownDelay * UA_DATETIME_MSEC);
21983 return false;
21984}
21985
21986/*******************/
21987/* Timed Callbacks */
21988/*******************/
21989
21990UA_StatusCode
21991UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
21992 void *data, UA_DateTime date, UA_UInt64 *callbackId) {
21993 UA_LOCK(&server->serviceMutex);
21994 UA_StatusCode retval =
21995 UA_Timer_addTimedCallback(t: &server->timer,
21996 callback: (UA_ApplicationCallback)callback,
21997 application: server, data, date, callbackId);
21998 UA_UNLOCK(&server->serviceMutex);
21999 return retval;
22000}
22001
22002UA_StatusCode
22003addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
22004 void *data, UA_Double interval_ms,
22005 UA_UInt64 *callbackId) {
22006 return UA_Timer_addRepeatedCallback(t: &server->timer,
22007 callback: (UA_ApplicationCallback)callback,
22008 application: server, data, interval_ms, NULL,
22009 timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
22010}
22011
22012UA_StatusCode
22013UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
22014 void *data, UA_Double interval_ms,
22015 UA_UInt64 *callbackId) {
22016 UA_LOCK(&server->serviceMutex);
22017 UA_StatusCode retval =
22018 addRepeatedCallback(server, callback, data, interval_ms, callbackId);
22019 UA_UNLOCK(&server->serviceMutex);
22020 return retval;
22021}
22022
22023UA_StatusCode
22024changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
22025 UA_Double interval_ms) {
22026 return UA_Timer_changeRepeatedCallback(t: &server->timer, callbackId,
22027 interval_ms, NULL, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
22028}
22029
22030UA_StatusCode
22031UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
22032 UA_Double interval_ms) {
22033 UA_LOCK(&server->serviceMutex);
22034 UA_StatusCode retval =
22035 changeRepeatedCallbackInterval(server, callbackId, interval_ms);
22036 UA_UNLOCK(&server->serviceMutex);
22037 return retval;
22038}
22039
22040void
22041removeCallback(UA_Server *server, UA_UInt64 callbackId) {
22042 UA_Timer_removeCallback(t: &server->timer, callbackId);
22043}
22044
22045void
22046UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId) {
22047 UA_LOCK(&server->serviceMutex);
22048 removeCallback(server, callbackId);
22049 UA_UNLOCK(&server->serviceMutex);
22050}
22051
22052UA_StatusCode
22053UA_Server_updateCertificate(UA_Server *server,
22054 const UA_ByteString *oldCertificate,
22055 const UA_ByteString *newCertificate,
22056 const UA_ByteString *newPrivateKey,
22057 UA_Boolean closeSessions,
22058 UA_Boolean closeSecureChannels) {
22059
22060 UA_CHECK(server && oldCertificate && newCertificate && newPrivateKey,
22061 return UA_STATUSCODE_BADINTERNALERROR);
22062
22063 if(closeSessions) {
22064 session_list_entry *current;
22065 LIST_FOREACH(current, &server->sessions, pointers) {
22066 if(UA_ByteString_equal(string1: oldCertificate,
22067 string2: &current->session.header.channel->securityPolicy->localCertificate)) {
22068 UA_LOCK(&server->serviceMutex);
22069 UA_Server_removeSessionByToken(server, token: &current->session.header.authenticationToken,
22070 event: UA_DIAGNOSTICEVENT_CLOSE);
22071 UA_UNLOCK(&server->serviceMutex);
22072 }
22073 }
22074
22075 }
22076
22077 if(closeSecureChannels) {
22078 channel_entry *entry;
22079 TAILQ_FOREACH(entry, &server->channels, pointers) {
22080 if(UA_ByteString_equal(string1: &entry->channel.securityPolicy->localCertificate, string2: oldCertificate))
22081 UA_Server_closeSecureChannel(server, channel: &entry->channel, event: UA_DIAGNOSTICEVENT_CLOSE);
22082 }
22083 }
22084
22085 size_t i = 0;
22086 while(i < server->config.endpointsSize) {
22087 UA_EndpointDescription *ed = &server->config.endpoints[i];
22088 if(UA_ByteString_equal(string1: &ed->serverCertificate, string2: oldCertificate)) {
22089 UA_String_clear(p: &ed->serverCertificate);
22090 UA_String_copy(src: newCertificate, dst: &ed->serverCertificate);
22091 UA_SecurityPolicy *sp = getSecurityPolicyByUri(server,
22092 securityPolicyUri: &server->config.endpoints[i].securityPolicyUri);
22093 UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR);
22094 sp->updateCertificateAndPrivateKey(sp, *newCertificate, *newPrivateKey);
22095 }
22096 i++;
22097 }
22098
22099 return UA_STATUSCODE_GOOD;
22100}
22101
22102/***************************/
22103/* Server lookup functions */
22104/***************************/
22105
22106UA_SecurityPolicy *
22107getSecurityPolicyByUri(const UA_Server *server, const UA_ByteString *securityPolicyUri) {
22108 for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
22109 UA_SecurityPolicy *securityPolicyCandidate = &server->config.securityPolicies[i];
22110 if(UA_ByteString_equal(string1: securityPolicyUri, string2: &securityPolicyCandidate->policyUri))
22111 return securityPolicyCandidate;
22112 }
22113 return NULL;
22114}
22115
22116#ifdef UA_ENABLE_ENCRYPTION
22117/* The local ApplicationURI has to match the certificates of the
22118 * SecurityPolicies */
22119static UA_StatusCode
22120verifyServerApplicationURI(const UA_Server *server) {
22121 const UA_String securityPolicyNoneUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
22122 for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
22123 UA_SecurityPolicy *sp = &server->config.securityPolicies[i];
22124 if(UA_String_equal(s1: &sp->policyUri, s2: &securityPolicyNoneUri) && (sp->localCertificate.length == 0))
22125 continue;
22126 UA_StatusCode retval = server->config.certificateVerification.
22127 verifyApplicationURI(server->config.certificateVerification.context,
22128 &sp->localCertificate,
22129 &server->config.applicationDescription.applicationUri);
22130
22131 UA_CHECK_STATUS_ERROR(retval, return retval, &server->config.logger, UA_LOGCATEGORY_SERVER,
22132 "The configured ApplicationURI \"%.*s\"does not match the "
22133 "ApplicationURI specified in the certificate for the "
22134 "SecurityPolicy %.*s",
22135 (int)server->config.applicationDescription.applicationUri.length,
22136 server->config.applicationDescription.applicationUri.data,
22137 (int)sp->policyUri.length, sp->policyUri.data);
22138 }
22139 return UA_STATUSCODE_GOOD;
22140}
22141#endif
22142
22143UA_ServerStatistics
22144UA_Server_getStatistics(UA_Server *server) {
22145 UA_ServerStatistics stat;
22146 stat.ns = server->networkStatistics;
22147 stat.scs = server->secureChannelStatistics;
22148
22149 stat.ss.currentSessionCount = server->activeSessionCount;
22150 stat.ss.cumulatedSessionCount =
22151 server->serverDiagnosticsSummary.cumulatedSessionCount;
22152 stat.ss.securityRejectedSessionCount =
22153 server->serverDiagnosticsSummary.securityRejectedSessionCount;
22154 stat.ss.rejectedSessionCount =
22155 server->serverDiagnosticsSummary.rejectedSessionCount;
22156 stat.ss.sessionTimeoutCount =
22157 server->serverDiagnosticsSummary.sessionTimeoutCount;
22158 stat.ss.sessionAbortCount =
22159 server->serverDiagnosticsSummary.sessionAbortCount;
22160
22161 return stat;
22162}
22163
22164/********************/
22165/* Main Server Loop */
22166/********************/
22167
22168#define UA_MAXTIMEOUT 50 /* Max timeout in ms between main-loop iterations */
22169
22170/* Start: Spin up the workers and the network layer and sample the server's
22171 * start time.
22172 * Iterate: Process repeated callbacks and events in the network layer. This
22173 * part can be driven from an external main-loop in an event-driven
22174 * single-threaded architecture.
22175 * Stop: Stop workers, finish all callbacks, stop the network layer, clean up */
22176
22177UA_StatusCode
22178UA_Server_run_startup(UA_Server *server) {
22179
22180#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
22181 /* Prominently warn user that fuzzing build is enabled. This will tamper with authentication tokens and other important variables
22182 * E.g. if fuzzing is enabled, and two clients are connected, subscriptions do not work properly,
22183 * since the tokens will be overridden to allow easier fuzzing. */
22184 UA_LOG_FATAL(&server->config.logger, UA_LOGCATEGORY_SERVER,
22185 "Server was built with unsafe fuzzing mode. "
22186 "This should only be used for specific fuzzing builds.");
22187#endif
22188
22189 /* ensure that the uri for ns1 is set up from the app description */
22190 setupNs1Uri(server);
22191
22192 /* write ServerArray with same ApplicationURI value as NamespaceArray */
22193 UA_StatusCode retVal =
22194 writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
22195 v: &server->config.applicationDescription.applicationUri,
22196 length: 1, type: &UA_TYPES[UA_TYPES_STRING]);
22197 UA_CHECK_STATUS(retVal, return retVal);
22198
22199 if(server->state > UA_SERVERLIFECYCLE_FRESH)
22200 return UA_STATUSCODE_GOOD;
22201
22202 /* At least one endpoint has to be configured */
22203 if(server->config.endpointsSize == 0) {
22204 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
22205 msg: "There has to be at least one endpoint.");
22206 }
22207
22208 /* Does the ApplicationURI match the local certificates? */
22209#ifdef UA_ENABLE_ENCRYPTION
22210 retVal = verifyServerApplicationURI(server);
22211 UA_CHECK_STATUS(retVal, return retVal);
22212#endif
22213
22214 /* Sample the start time and set it to the Server object */
22215 server->startTime = UA_DateTime_now();
22216 UA_Variant var;
22217 UA_Variant_init(p: &var);
22218 UA_Variant_setScalar(v: &var, p: &server->startTime, type: &UA_TYPES[UA_TYPES_DATETIME]);
22219 UA_Server_writeValue(server,
22220 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME),
22221 value: var);
22222
22223 /* Start the networklayers */
22224 UA_StatusCode result = UA_STATUSCODE_GOOD;
22225 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22226 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22227 nl->statistics = &server->networkStatistics;
22228 result |= nl->start(nl, &server->config.logger, &server->config.customHostname);
22229 }
22230 UA_CHECK_STATUS(result, return result);
22231
22232 /* Update the application description to match the previously added
22233 * discovery urls. We can only do this after the network layer is started
22234 * since it inits the discovery url */
22235 if(server->config.applicationDescription.discoveryUrlsSize != 0) {
22236 UA_Array_delete(p: server->config.applicationDescription.discoveryUrls,
22237 size: server->config.applicationDescription.discoveryUrlsSize,
22238 type: &UA_TYPES[UA_TYPES_STRING]);
22239 server->config.applicationDescription.discoveryUrlsSize = 0;
22240 }
22241 server->config.applicationDescription.discoveryUrls = (UA_String *)
22242 UA_Array_new(size: server->config.networkLayersSize, type: &UA_TYPES[UA_TYPES_STRING]);
22243 UA_CHECK_MEM(server->config.applicationDescription.discoveryUrls,
22244 return UA_STATUSCODE_BADOUTOFMEMORY);
22245
22246 server->config.applicationDescription.discoveryUrlsSize =
22247 server->config.networkLayersSize;
22248 for(size_t i = 0; i < server->config.applicationDescription.discoveryUrlsSize; i++) {
22249 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22250 UA_String_copy(src: &nl->discoveryUrl,
22251 dst: &server->config.applicationDescription.discoveryUrls[i]);
22252 }
22253
22254 /* Start the multicast discovery server */
22255#ifdef UA_ENABLE_DISCOVERY_MULTICAST
22256 if(server->config.mdnsEnabled)
22257 startMulticastDiscoveryServer(server);
22258#endif
22259
22260 /* Update Endpoint description */
22261 for(size_t i = 0; i < server->config.endpointsSize; ++i){
22262 UA_ApplicationDescription_clear(p: &server->config.endpoints[i].server);
22263 UA_ApplicationDescription_copy(src: &server->config.applicationDescription,
22264 dst: &server->config.endpoints[i].server);
22265 }
22266
22267 server->state = UA_SERVERLIFECYCLE_FRESH;
22268
22269 return result;
22270}
22271
22272static void
22273serverExecuteRepeatedCallback(UA_Server *server, UA_ApplicationCallback cb,
22274 void *callbackApplication, void *data) {
22275 /* Service mutex is not set inside the timer that triggers the callback */
22276 /* The following check cannot be used since another thread can take the
22277 * serviceMutex during a server_iterate_call. */
22278 //UA_LOCK_ASSERT(&server->serviceMutex, 0);
22279 cb(callbackApplication, data);
22280}
22281
22282UA_UInt16
22283UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
22284 /* Process repeated work */
22285 UA_DateTime now = UA_DateTime_nowMonotonic();
22286 UA_DateTime nextRepeated = UA_Timer_process(t: &server->timer, nowMonotonic: now,
22287 executionCallback: (UA_TimerExecutionCallback)serverExecuteRepeatedCallback, executionApplication: server);
22288 UA_DateTime latest = now + (UA_MAXTIMEOUT * UA_DATETIME_MSEC);
22289 if(nextRepeated > latest)
22290 nextRepeated = latest;
22291
22292 UA_UInt16 timeout = 0;
22293
22294 /* round always to upper value to avoid timeout to be set to 0
22295 * if(nextRepeated - now) < (UA_DATETIME_MSEC/2) */
22296 if(waitInternal)
22297 timeout = (UA_UInt16)(((nextRepeated - now) + (UA_DATETIME_MSEC - 1)) / UA_DATETIME_MSEC);
22298
22299 /* Listen on the networklayer */
22300 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22301 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22302 nl->listen(nl, server, timeout);
22303 }
22304
22305#if defined(UA_ENABLE_PUBSUB_MQTT)
22306 /* Listen on the pubsublayer, but only if the yield function is set */
22307 UA_PubSubConnection *connection;
22308 TAILQ_FOREACH(connection, &server->pubSubManager.connections, listEntry){
22309 UA_PubSubConnection *ps = connection;
22310 if(ps && ps->channel->yield){
22311 ps->channel->yield(ps->channel, timeout);
22312 }
22313 }
22314#endif
22315
22316 UA_LOCK(&server->serviceMutex);
22317
22318#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && (UA_MULTITHREADING < 200)
22319 if(server->config.mdnsEnabled) {
22320 /* TODO multicastNextRepeat does not consider new input data (requests)
22321 * on the socket. It will be handled on the next call. if needed, we
22322 * need to use select with timeout on the multicast socket
22323 * server->mdnsSocket (see example in mdnsd library) on higher level. */
22324 UA_DateTime multicastNextRepeat = 0;
22325 UA_StatusCode hasNext =
22326 iterateMulticastDiscoveryServer(server, &multicastNextRepeat, true);
22327 if(hasNext == UA_STATUSCODE_GOOD && multicastNextRepeat < nextRepeated)
22328 nextRepeated = multicastNextRepeat;
22329 }
22330#endif
22331
22332 UA_UNLOCK(&server->serviceMutex);
22333
22334 now = UA_DateTime_nowMonotonic();
22335 timeout = 0;
22336 if(nextRepeated > now)
22337 timeout = (UA_UInt16)((nextRepeated - now) / UA_DATETIME_MSEC);
22338 return timeout;
22339}
22340
22341UA_StatusCode
22342UA_Server_run_shutdown(UA_Server *server) {
22343 /* Stop the netowrk layer */
22344 for(size_t i = 0; i < server->config.networkLayersSize; ++i) {
22345 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
22346 nl->stop(nl, server);
22347 }
22348
22349#ifdef UA_ENABLE_DISCOVERY_MULTICAST
22350 /* Stop multicast discovery */
22351 if(server->config.mdnsEnabled)
22352 stopMulticastDiscoveryServer(server);
22353#endif
22354
22355 return UA_STATUSCODE_GOOD;
22356}
22357
22358static UA_Boolean
22359testShutdownCondition(UA_Server *server) {
22360 if(server->endTime == 0)
22361 return false;
22362 return (UA_DateTime_now() > server->endTime);
22363}
22364
22365UA_StatusCode
22366UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) {
22367 UA_StatusCode retval = UA_Server_run_startup(server);
22368 UA_CHECK_STATUS(retval, return retval);
22369
22370#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
22371 size_t loopCount = 0;
22372#endif
22373 while(!testShutdownCondition(server)) {
22374#ifdef UA_ENABLE_VALGRIND_INTERACTIVE
22375 if(loopCount == 0) {
22376 VALGRIND_DO_LEAK_CHECK;
22377 }
22378 ++loopCount;
22379 loopCount %= UA_VALGRIND_INTERACTIVE_INTERVAL;
22380#endif
22381 UA_Server_run_iterate(server, true);
22382 if(!*running) {
22383 if(setServerShutdown(server))
22384 break;
22385 }
22386 }
22387 return UA_Server_run_shutdown(server);
22388}
22389
22390/**** amalgamated original file "/src/server/ua_server_ns0.c" ****/
22391
22392/* This Source Code Form is subject to the terms of the Mozilla Public
22393 * License, v. 2.0. If a copy of the MPL was not distributed with this
22394 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
22395 *
22396 * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
22397 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
22398 * Copyright 2017 (c) Thomas Bender
22399 * Copyright 2017 (c) Julian Grothoff
22400 * Copyright 2017 (c) Henrik Norrman
22401 * Copyright 2018 (c) Fabian Arndt, Root-Core
22402 * Copyright 2019 (c) Kalycito Infotech Private Limited
22403 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
22404 */
22405
22406
22407
22408static UA_StatusCode
22409addNode_raw(UA_Server *server, UA_NodeClass nodeClass,
22410 UA_UInt32 nodeId, char *name, void *attributes,
22411 const UA_DataType *attributesType) {
22412 UA_AddNodesItem item;
22413 UA_AddNodesItem_init(p: &item);
22414 item.nodeClass = nodeClass;
22415 item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId);
22416 item.browseName = UA_QUALIFIEDNAME(nsIndex: 0, chars: name);
22417 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
22418 p: attributes, type: attributesType);
22419 return AddNode_raw(server, session: &server->adminSession, NULL, item: &item, NULL);
22420}
22421
22422static UA_StatusCode
22423addNode_finish(UA_Server *server, UA_UInt32 nodeId,
22424 UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) {
22425 const UA_NodeId sourceId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId);
22426 const UA_NodeId refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceTypeId);
22427 const UA_ExpandedNodeId targetId = UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, identifier: parentNodeId);
22428 UA_StatusCode retval = UA_Server_addReference(server, sourceId, refTypeId, targetId, false);
22429 if(retval != UA_STATUSCODE_GOOD)
22430 return retval;
22431 return AddNode_finish(server, session: &server->adminSession, nodeId: &sourceId);
22432}
22433
22434static UA_StatusCode
22435addObjectNode(UA_Server *server, char* name, UA_UInt32 objectid,
22436 UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) {
22437 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
22438 object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
22439 return UA_Server_addObjectNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: objectid),
22440 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid),
22441 referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceid),
22442 browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
22443 typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, identifier: type_id),
22444 attr: object_attr, NULL, NULL);
22445}
22446
22447static UA_StatusCode
22448addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid,
22449 UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) {
22450 UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default;
22451 reference_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
22452 reference_attr.isAbstract = isabstract;
22453 reference_attr.symmetric = symmetric;
22454 if(inverseName)
22455 reference_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: inverseName);
22456 return UA_Server_addReferenceTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referencetypeid),
22457 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid), referenceTypeId: UA_NODEID_NULL,
22458 browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), attr: reference_attr, NULL, NULL);
22459}
22460
22461/***************************/
22462/* Bootstrap NS0 hierarchy */
22463/***************************/
22464
22465/* Creates the basic nodes which are expected by the nodeset compiler to be
22466 * already created. This is necessary to reduce the dependencies for the nodeset
22467 * compiler. */
22468static UA_StatusCode
22469UA_Server_createNS0_base(UA_Server *server) {
22470 /* Bootstrap ReferenceTypes. The order of these is important for the
22471 * ReferenceTypeIndex. The ReferenceTypeIndex is created with the raw node.
22472 * The ReferenceTypeSet of subtypes for every ReferenceType is created
22473 * during the call to AddNode_finish. */
22474 UA_StatusCode ret = UA_STATUSCODE_GOOD;
22475 UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default;
22476 references_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "References");
22477 references_attr.isAbstract = true;
22478 references_attr.symmetric = true;
22479 references_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "References");
22480 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, name: "References",
22481 attributes: &references_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22482
22483 UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default;
22484 hassubtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasSubtype");
22485 hassubtype_attr.isAbstract = false;
22486 hassubtype_attr.symmetric = false;
22487 hassubtype_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "SubtypeOf");
22488 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, name: "HasSubtype",
22489 attributes: &hassubtype_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22490
22491 UA_ReferenceTypeAttributes aggregates_attr = UA_ReferenceTypeAttributes_default;
22492 aggregates_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Aggregates");
22493 aggregates_attr.isAbstract = true;
22494 aggregates_attr.symmetric = false;
22495 aggregates_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AggregatedBy");
22496 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_AGGREGATES, name: "Aggregates",
22497 attributes: &aggregates_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]);
22498
22499 ret |= addReferenceTypeNode(server, name: "HierarchicalReferences", NULL,
22500 UA_NS0ID_HIERARCHICALREFERENCES, true, false, UA_NS0ID_REFERENCES);
22501
22502 ret |= addReferenceTypeNode(server, name: "NonHierarchicalReferences", NULL,
22503 UA_NS0ID_NONHIERARCHICALREFERENCES, true, true, UA_NS0ID_REFERENCES);
22504
22505 ret |= addReferenceTypeNode(server, name: "HasChild", NULL, UA_NS0ID_HASCHILD,
22506 true, false, UA_NS0ID_HIERARCHICALREFERENCES);
22507
22508 ret |= addReferenceTypeNode(server, name: "Organizes", inverseName: "OrganizedBy", UA_NS0ID_ORGANIZES,
22509 false, false, UA_NS0ID_HIERARCHICALREFERENCES);
22510
22511 ret |= addReferenceTypeNode(server, name: "HasEventSource", inverseName: "EventSourceOf", UA_NS0ID_HASEVENTSOURCE,
22512 false, false, UA_NS0ID_HIERARCHICALREFERENCES);
22513
22514 ret |= addReferenceTypeNode(server, name: "HasModellingRule", inverseName: "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE,
22515 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22516
22517 ret |= addReferenceTypeNode(server, name: "HasEncoding", inverseName: "EncodingOf", UA_NS0ID_HASENCODING,
22518 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22519
22520 ret |= addReferenceTypeNode(server, name: "HasDescription", inverseName: "DescriptionOf", UA_NS0ID_HASDESCRIPTION,
22521 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22522
22523 ret |= addReferenceTypeNode(server, name: "HasTypeDefinition", inverseName: "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION,
22524 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22525
22526 ret |= addReferenceTypeNode(server, name: "GeneratesEvent", inverseName: "GeneratedBy", UA_NS0ID_GENERATESEVENT,
22527 false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22528
22529 /* Complete bootstrap of Aggregates */
22530 ret |= addNode_finish(server, UA_NS0ID_AGGREGATES, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
22531
22532 /* Complete bootstrap of HasSubtype */
22533 ret |= addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE);
22534
22535 ret |= addReferenceTypeNode(server, name: "HasProperty", inverseName: "PropertyOf", UA_NS0ID_HASPROPERTY,
22536 false, false, UA_NS0ID_AGGREGATES);
22537
22538 ret |= addReferenceTypeNode(server, name: "HasComponent", inverseName: "ComponentOf", UA_NS0ID_HASCOMPONENT,
22539 false, false, UA_NS0ID_AGGREGATES);
22540
22541 ret |= addReferenceTypeNode(server, name: "HasNotifier", inverseName: "NotifierOf", UA_NS0ID_HASNOTIFIER,
22542 false, false, UA_NS0ID_HASEVENTSOURCE);
22543
22544 ret |= addReferenceTypeNode(server, name: "HasOrderedComponent", inverseName: "OrderedComponentOf",
22545 UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT);
22546
22547 ret |= addReferenceTypeNode(server, name: "HasInterface", inverseName: "InterfaceOf",
22548 UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES);
22549
22550 /**************/
22551 /* Data Types */
22552 /**************/
22553
22554 /* Bootstrap BaseDataType */
22555 UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default;
22556 basedatatype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataType");
22557 basedatatype_attr.isAbstract = true;
22558 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, name: "BaseDataType",
22559 attributes: &basedatatype_attr, attributesType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]);
22560
22561 /*****************/
22562 /* VariableTypes */
22563 /*****************/
22564
22565 UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default;
22566 basevar_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseVariableType");
22567 basevar_attr.isAbstract = true;
22568 basevar_attr.valueRank = UA_VALUERANK_ANY;
22569 basevar_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22570 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_VARIABLETYPE, UA_NS0ID_BASEVARIABLETYPE, name: "BaseVariableType",
22571 attributes: &basevar_attr, attributesType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]);
22572
22573 UA_VariableTypeAttributes bdv_attr = UA_VariableTypeAttributes_default;
22574 bdv_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataVariableType");
22575 bdv_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22576 bdv_attr.valueRank = UA_VALUERANK_ANY;
22577 ret |= UA_Server_addVariableTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE),
22578 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE),
22579 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "BaseDataVariableType"),
22580 typeDefinition: UA_NODEID_NULL, attr: bdv_attr, NULL, NULL);
22581
22582 UA_VariableTypeAttributes prop_attr = UA_VariableTypeAttributes_default;
22583 prop_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PropertyType");
22584 prop_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE);
22585 prop_attr.valueRank = UA_VALUERANK_ANY;
22586 ret |= UA_Server_addVariableTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PROPERTYTYPE),
22587 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE),
22588 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PropertyType"),
22589 typeDefinition: UA_NODEID_NULL, attr: prop_attr, NULL, NULL);
22590
22591 /***************/
22592 /* ObjectTypes */
22593 /***************/
22594
22595 UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default;
22596 baseobj_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseObjectType");
22597 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_OBJECTTYPE, UA_NS0ID_BASEOBJECTTYPE, name: "BaseObjectType",
22598 attributes: &baseobj_attr, attributesType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
22599
22600 UA_ObjectTypeAttributes folder_attr = UA_ObjectTypeAttributes_default;
22601 folder_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FolderType");
22602 ret |= UA_Server_addObjectTypeNode(server, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_FOLDERTYPE),
22603 parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE),
22604 referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "FolderType"),
22605 attr: folder_attr, NULL, NULL);
22606
22607 /******************/
22608 /* Root and below */
22609 /******************/
22610
22611 ret |= addObjectNode(server, name: "Root", UA_NS0ID_ROOTFOLDER, parentid: 0, referenceid: 0, UA_NS0ID_FOLDERTYPE);
22612
22613 ret |= addObjectNode(server, name: "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER,
22614 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22615
22616 ret |= addObjectNode(server, name: "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER,
22617 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22618
22619 ret |= addObjectNode(server, name: "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22620 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22621 ret |= addNode_finish(server, UA_NS0ID_REFERENCES, UA_NS0ID_REFERENCETYPESFOLDER,
22622 UA_NS0ID_ORGANIZES);
22623
22624 ret |= addObjectNode(server, name: "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22625 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22626 ret |= addNode_finish(server, UA_NS0ID_BASEDATATYPE, UA_NS0ID_DATATYPESFOLDER,
22627 UA_NS0ID_ORGANIZES);
22628
22629 ret |= addObjectNode(server, name: "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22630 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22631 ret |= addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE, UA_NS0ID_VARIABLETYPESFOLDER,
22632 UA_NS0ID_ORGANIZES);
22633
22634 ret |= addObjectNode(server, name: "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22635 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22636 ret |= addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE, UA_NS0ID_OBJECTTYPESFOLDER,
22637 UA_NS0ID_ORGANIZES);
22638
22639 ret |= addObjectNode(server, name: "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER,
22640 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22641
22642 ret |= addObjectNode(server, name: "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER,
22643 UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE);
22644
22645 /* Add BaseEventType */
22646 UA_ObjectTypeAttributes eventtype_attr = UA_ObjectTypeAttributes_default;
22647 eventtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseEventType");
22648 ret |= addNode_raw(server, nodeClass: UA_NODECLASS_OBJECTTYPE, UA_NS0ID_BASEEVENTTYPE, name: "BaseEventType",
22649 attributes: &eventtype_attr, attributesType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]);
22650 ret |= addNode_finish(server, UA_NS0ID_BASEEVENTTYPE, UA_NS0ID_EVENTTYPESFOLDER,
22651 UA_NS0ID_ORGANIZES);
22652
22653 if(ret != UA_STATUSCODE_GOOD)
22654 ret = UA_STATUSCODE_BADINTERNALERROR;
22655
22656 return ret;
22657}
22658
22659/****************/
22660/* Data Sources */
22661/****************/
22662
22663static UA_StatusCode
22664readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22665 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
22666 const UA_NumericRange *range, UA_DataValue *value) {
22667 if(range) {
22668 value->hasStatus = true;
22669 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22670 return UA_STATUSCODE_GOOD;
22671 }
22672
22673 if(sourceTimestamp) {
22674 value->hasSourceTimestamp = true;
22675 value->sourceTimestamp = UA_DateTime_now();
22676 }
22677
22678 void *data = NULL;
22679
22680 UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
22681
22682 switch(nodeId->identifier.numeric) {
22683 case UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN: {
22684 UA_UInt32 *shutdown = UA_UInt32_new();
22685 if(!shutdown)
22686 return UA_STATUSCODE_BADOUTOFMEMORY;
22687 if(server->endTime != 0)
22688 *shutdown = (UA_UInt32)((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
22689 value->value.data = shutdown;
22690 value->value.type = &UA_TYPES[UA_TYPES_UINT32];
22691 value->hasValue = true;
22692 return UA_STATUSCODE_GOOD;
22693 }
22694
22695 case UA_NS0ID_SERVER_SERVERSTATUS_STATE: {
22696 UA_ServerState *state = UA_ServerState_new();
22697 if(!state)
22698 return UA_STATUSCODE_BADOUTOFMEMORY;
22699 if(server->endTime != 0)
22700 *state = UA_SERVERSTATE_SHUTDOWN;
22701 value->value.data = state;
22702 value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE];
22703 value->hasValue = true;
22704 return UA_STATUSCODE_GOOD;
22705 }
22706
22707 case UA_NS0ID_SERVER_SERVERSTATUS: {
22708 UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new();
22709 if(!statustype)
22710 return UA_STATUSCODE_BADOUTOFMEMORY;
22711 statustype->startTime = server->startTime;
22712 statustype->currentTime = UA_DateTime_now();
22713
22714 statustype->state = UA_SERVERSTATE_RUNNING;
22715 statustype->secondsTillShutdown = 0;
22716 if(server->endTime != 0) {
22717 statustype->state = UA_SERVERSTATE_SHUTDOWN;
22718 statustype->secondsTillShutdown = (UA_UInt32)
22719 ((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC);
22720 }
22721
22722 value->value.data = statustype;
22723 value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE];
22724 value->hasValue = true;
22725 return UA_BuildInfo_copy(src: &server->config.buildInfo, dst: &statustype->buildInfo);
22726 }
22727
22728 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO:
22729 value->value.type = &UA_TYPES[UA_TYPES_BUILDINFO];
22730 data = &server->config.buildInfo;
22731 break;
22732
22733 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI:
22734 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22735 data = &server->config.buildInfo.productUri;
22736 break;
22737
22738 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME:
22739 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22740 data = &server->config.buildInfo.manufacturerName;
22741 break;
22742
22743 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME:
22744 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22745 data = &server->config.buildInfo.productName;
22746 break;
22747
22748 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION:
22749 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22750 data = &server->config.buildInfo.softwareVersion;
22751 break;
22752
22753 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER:
22754 value->value.type = &UA_TYPES[UA_TYPES_STRING];
22755 data = &server->config.buildInfo.buildNumber;
22756 break;
22757
22758 case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE:
22759 value->value.type = &UA_TYPES[UA_TYPES_DATETIME];
22760 data = &server->config.buildInfo.buildDate;
22761 break;
22762
22763 default:
22764 value->hasStatus = true;
22765 value->status = UA_STATUSCODE_BADINTERNALERROR;
22766 return UA_STATUSCODE_GOOD;
22767 }
22768
22769 value->value.data = UA_new(type: value->value.type);
22770 if(!value->value.data) {
22771 value->value.type = NULL;
22772 return UA_STATUSCODE_BADOUTOFMEMORY;
22773 }
22774
22775 value->hasValue = true;
22776 return UA_copy(src: data, dst: value->value.data, type: value->value.type);
22777}
22778
22779#ifdef UA_GENERATED_NAMESPACE_ZERO
22780static UA_StatusCode
22781readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22782 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22783 const UA_NumericRange *range, UA_DataValue *value) {
22784 if(range) {
22785 value->hasStatus = true;
22786 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22787 return UA_STATUSCODE_GOOD;
22788 }
22789
22790 value->value.type = &UA_TYPES[UA_TYPES_BYTE];
22791 value->value.arrayLength = 0;
22792 UA_Byte *byte = UA_Byte_new();
22793 *byte = 255;
22794 value->value.data = byte;
22795 value->value.arrayDimensionsSize = 0;
22796 value->value.arrayDimensions = NULL;
22797 value->hasValue = true;
22798 if(includeSourceTimeStamp) {
22799 value->hasSourceTimestamp = true;
22800 value->sourceTimestamp = UA_DateTime_now();
22801 }
22802 return UA_STATUSCODE_GOOD;
22803}
22804
22805static UA_StatusCode
22806readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22807 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22808 const UA_NumericRange *range, UA_DataValue *value) {
22809 if(range) {
22810 value->hasStatus = true;
22811 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22812 return UA_STATUSCODE_GOOD;
22813 }
22814
22815 value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN];
22816 value->value.arrayLength = 0;
22817 UA_Boolean *boolean = UA_Boolean_new();
22818 *boolean = false;
22819 value->value.data = boolean;
22820 value->value.arrayDimensionsSize = 0;
22821 value->value.arrayDimensions = NULL;
22822 value->hasValue = true;
22823 if(includeSourceTimeStamp) {
22824 value->hasSourceTimestamp = true;
22825 value->sourceTimestamp = UA_DateTime_now();
22826 }
22827 return UA_STATUSCODE_GOOD;
22828}
22829#endif
22830
22831static UA_StatusCode
22832readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22833 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22834 const UA_NumericRange *range,
22835 UA_DataValue *value) {
22836 /* ensure that the uri for ns1 is set up from the app description */
22837 setupNs1Uri(server);
22838
22839 if(range) {
22840 value->hasStatus = true;
22841 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22842 return UA_STATUSCODE_GOOD;
22843 }
22844 UA_StatusCode retval;
22845 retval = UA_Variant_setArrayCopy(v: &value->value, array: server->namespaces,
22846 arraySize: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]);
22847 if(retval != UA_STATUSCODE_GOOD)
22848 return retval;
22849 value->hasValue = true;
22850 if(includeSourceTimeStamp) {
22851 value->hasSourceTimestamp = true;
22852 value->sourceTimestamp = UA_DateTime_now();
22853 }
22854 return UA_STATUSCODE_GOOD;
22855}
22856
22857static UA_StatusCode
22858writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22859 const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range,
22860 const UA_DataValue *value) {
22861 /* Check the data type */
22862 if(!value->hasValue ||
22863 value->value.type != &UA_TYPES[UA_TYPES_STRING])
22864 return UA_STATUSCODE_BADTYPEMISMATCH;
22865
22866 /* Check that the variant is not empty */
22867 if(!value->value.data)
22868 return UA_STATUSCODE_BADTYPEMISMATCH;
22869
22870 /* TODO: Writing with a range is not implemented */
22871 if(range)
22872 return UA_STATUSCODE_BADINTERNALERROR;
22873
22874 UA_String *newNamespaces = (UA_String*)value->value.data;
22875 size_t newNamespacesSize = value->value.arrayLength;
22876
22877 /* Test if we append to the existing namespaces */
22878 if(newNamespacesSize <= server->namespacesSize)
22879 return UA_STATUSCODE_BADTYPEMISMATCH;
22880
22881 /* ensure that the uri for ns1 is set up from the app description */
22882 setupNs1Uri(server);
22883
22884 /* Test if the existing namespaces are unchanged */
22885 for(size_t i = 0; i < server->namespacesSize; ++i) {
22886 if(!UA_String_equal(s1: &server->namespaces[i], s2: &newNamespaces[i]))
22887 return UA_STATUSCODE_BADINTERNALERROR;
22888 }
22889
22890 /* Add namespaces */
22891 for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i)
22892 addNamespace(server, name: newNamespaces[i]);
22893 return UA_STATUSCODE_GOOD;
22894}
22895
22896static UA_StatusCode
22897readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22898 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean sourceTimeStamp,
22899 const UA_NumericRange *range, UA_DataValue *value) {
22900 if(range) {
22901 value->hasStatus = true;
22902 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22903 return UA_STATUSCODE_GOOD;
22904 }
22905 UA_DateTime currentTime = UA_DateTime_now();
22906 UA_StatusCode retval = UA_Variant_setScalarCopy(v: &value->value, p: &currentTime,
22907 type: &UA_TYPES[UA_TYPES_DATETIME]);
22908 if(retval != UA_STATUSCODE_GOOD)
22909 return retval;
22910 value->hasValue = true;
22911 if(sourceTimeStamp) {
22912 value->hasSourceTimestamp = true;
22913 value->sourceTimestamp = currentTime;
22914 }
22915 return UA_STATUSCODE_GOOD;
22916}
22917
22918#ifdef UA_GENERATED_NAMESPACE_ZERO
22919static UA_StatusCode
22920readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22921 const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp,
22922 const UA_NumericRange *range,
22923 UA_DataValue *value) {
22924 if(range) {
22925 value->hasStatus = true;
22926 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
22927 return UA_STATUSCODE_GOOD;
22928 }
22929
22930 UA_StatusCode retval;
22931 UA_Duration minInterval;
22932#ifdef UA_ENABLE_SUBSCRIPTIONS
22933 minInterval = server->config.samplingIntervalLimits.min;
22934#else
22935 minInterval = 0.0;
22936#endif
22937 retval = UA_Variant_setScalarCopy(v: &value->value, p: &minInterval, type: &UA_TYPES[UA_TYPES_DURATION]);
22938 if(retval != UA_STATUSCODE_GOOD)
22939 return retval;
22940 value->hasValue = true;
22941 if(includeSourceTimeStamp) {
22942 value->hasSourceTimestamp = true;
22943 value->sourceTimestamp = UA_DateTime_now();
22944 }
22945 return UA_STATUSCODE_GOOD;
22946}
22947#endif
22948
22949#if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
22950static UA_StatusCode
22951readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
22952 const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId,
22953 void *objectContext, size_t inputSize, const UA_Variant *input,
22954 size_t outputSize, UA_Variant *output) {
22955 /* Return two empty arrays by default */
22956 UA_Variant_setArray(v: &output[0], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]),
22957 arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]);
22958 UA_Variant_setArray(v: &output[1], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]),
22959 arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]);
22960
22961 /* Get the Session */
22962 UA_LOCK(&server->serviceMutex);
22963 UA_Session *session = UA_Server_getSessionById(server, sessionId);
22964 if(!session) {
22965 UA_UNLOCK(&server->serviceMutex);
22966 return UA_STATUSCODE_BADINTERNALERROR;
22967 }
22968 if(inputSize == 0 || !input[0].data) {
22969 UA_UNLOCK(&server->serviceMutex);
22970 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
22971 }
22972
22973 /* Get the Subscription */
22974 UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data));
22975 UA_Subscription *subscription = UA_Server_getSubscriptionById(server, subscriptionId);
22976 if(!subscription) {
22977 UA_UNLOCK(&server->serviceMutex);
22978 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
22979 }
22980
22981 /* The Subscription is not attached to this Session */
22982 if(subscription->session != session) {
22983 UA_UNLOCK(&server->serviceMutex);
22984 return UA_STATUSCODE_BADUSERACCESSDENIED;
22985 }
22986
22987 /* Count the MonitoredItems */
22988 UA_UInt32 sizeOfOutput = 0;
22989 UA_MonitoredItem* monitoredItem;
22990 LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
22991 ++sizeOfOutput;
22992 }
22993 if(sizeOfOutput == 0) {
22994 UA_UNLOCK(&server->serviceMutex);
22995 return UA_STATUSCODE_GOOD;
22996 }
22997
22998 /* Allocate the output arrays */
22999 UA_UInt32 *clientHandles = (UA_UInt32*)
23000 UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23001 if(!clientHandles) {
23002 UA_UNLOCK(&server->serviceMutex);
23003 return UA_STATUSCODE_BADOUTOFMEMORY;
23004 }
23005 UA_UInt32 *serverHandles = (UA_UInt32*)
23006 UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23007 if(!serverHandles) {
23008 UA_UNLOCK(&server->serviceMutex);
23009 UA_free(ptr: clientHandles);
23010 return UA_STATUSCODE_BADOUTOFMEMORY;
23011 }
23012
23013 /* Fill the array */
23014 UA_UInt32 i = 0;
23015 LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) {
23016 clientHandles[i] = monitoredItem->parameters.clientHandle;
23017 serverHandles[i] = monitoredItem->monitoredItemId;
23018 ++i;
23019 }
23020 UA_Variant_setArray(v: &output[0], array: serverHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23021 UA_Variant_setArray(v: &output[1], array: clientHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]);
23022
23023 UA_UNLOCK(&server->serviceMutex);
23024 return UA_STATUSCODE_GOOD;
23025}
23026#endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */
23027
23028UA_StatusCode
23029writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
23030 size_t length, const UA_DataType *type) {
23031 UA_Variant var;
23032 UA_Variant_init(p: &var);
23033 UA_Variant_setArray(v: &var, array: v, arraySize: length, type);
23034 return UA_Server_writeValue(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: var);
23035}
23036
23037#ifndef UA_GENERATED_NAMESPACE_ZERO
23038static UA_StatusCode
23039addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid,
23040 UA_UInt32 parentid, UA_UInt32 referenceid,
23041 UA_Int32 valueRank, UA_UInt32 dataType) {
23042 UA_VariableAttributes attr = UA_VariableAttributes_default;
23043 attr.displayName = UA_LOCALIZEDTEXT("", name);
23044 attr.dataType = UA_NODEID_NUMERIC(0, dataType);
23045 attr.valueRank = valueRank;
23046 attr.accessLevel = UA_ACCESSLEVELMASK_READ;
23047 return UA_Server_addVariableNode(server, UA_NODEID_NUMERIC(0, variableid),
23048 UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid),
23049 UA_QUALIFIEDNAME(0, name),
23050 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
23051 attr, NULL, NULL);
23052}
23053
23054/* A minimal server object that is not complete and does not use the mandated
23055 * references to a server type. To be used on very constrained devices. */
23056static UA_StatusCode
23057UA_Server_minimalServerObject(UA_Server *server) {
23058 /* Server */
23059 UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER,
23060 UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE);
23061
23062 /* Use a valuerank of -2 for now. The array is added later on and the valuerank set to 1. */
23063 retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY,
23064 UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
23065 UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
23066
23067 retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY,
23068 UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY,
23069 UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE);
23070
23071 retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS,
23072 UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT,
23073 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23074
23075 retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME,
23076 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23077 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23078
23079 retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE,
23080 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23081 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23082
23083 retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO,
23084 UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT,
23085 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23086
23087 retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI,
23088 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23089 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23090
23091 retval |= addVariableNode(server, "ManufacturerName",
23092 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME,
23093 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23094 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23095
23096 retval |= addVariableNode(server, "ProductName",
23097 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME,
23098 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23099 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23100
23101 retval |= addVariableNode(server, "SoftwareVersion",
23102 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION,
23103 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23104 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23105
23106 retval |= addVariableNode(server, "BuildNumber",
23107 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER,
23108 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23109 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23110
23111 retval |= addVariableNode(server, "BuildDate",
23112 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE,
23113 UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT,
23114 UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE);
23115
23116 return retval;
23117}
23118
23119#else
23120
23121static UA_StatusCode
23122writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) {
23123 UA_Variant var;
23124 UA_Variant_init(p: &var);
23125 UA_Variant_setScalar(v: &var, p: v, type);
23126 return UA_Server_writeValue(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: var);
23127}
23128
23129static void
23130addModellingRules(UA_Server *server) {
23131 /* Test if the ModellingRules folder was added. (Only for the full ns0.) */
23132 UA_NodeClass mrnc = UA_NODECLASS_UNSPECIFIED;
23133 UA_StatusCode retval = UA_Server_readNodeClass(server,
23134 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23135 outNodeClass: &mrnc);
23136 if(retval != UA_STATUSCODE_GOOD)
23137 return;
23138
23139 /* Add ExposesItsArray */
23140 UA_Server_addReference(server,
23141 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23142 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23143 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_EXPOSESITSARRAY),
23144 true);
23145
23146 /* Add Mandatory */
23147 UA_Server_addReference(server,
23148 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23149 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23150 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORY),
23151 true);
23152
23153
23154 /* Add MandatoryPlaceholder */
23155 UA_Server_addReference(server,
23156 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23157 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23158 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORYPLACEHOLDER),
23159 true);
23160
23161 /* Add Optional */
23162 UA_Server_addReference(server,
23163 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23164 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23165 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONAL),
23166 true);
23167
23168 /* Add OptionalPlaceholder */
23169 UA_Server_addReference(server,
23170 sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES),
23171 refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT),
23172 targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONALPLACEHOLDER),
23173 true);
23174}
23175
23176#endif
23177
23178/* Initialize the nodeset 0 by using the generated code of the nodeset compiler.
23179 * This also initialized the data sources for various variables, such as for
23180 * example server time. */
23181UA_StatusCode
23182UA_Server_initNS0(UA_Server *server) {
23183 /* Initialize base nodes which are always required an cannot be created
23184 * through the NS compiler */
23185 server->bootstrapNS0 = true;
23186 UA_StatusCode retVal = UA_Server_createNS0_base(server);
23187
23188#ifdef UA_GENERATED_NAMESPACE_ZERO
23189 /* Load nodes and references generated from the XML ns0 definition */
23190 retVal |= namespace0_generated(server);
23191#else
23192 /* Create a minimal server object */
23193 retVal |= UA_Server_minimalServerObject(server);
23194#endif
23195
23196 server->bootstrapNS0 = false;
23197
23198 if(retVal != UA_STATUSCODE_GOOD) {
23199 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
23200 msg: "Initialization of Namespace 0 failed with %s. "
23201 "See previous outputs for any error messages.",
23202 UA_StatusCode_name(code: retVal));
23203 return UA_STATUSCODE_BADINTERNALERROR;
23204 }
23205
23206 /* NamespaceArray */
23207 UA_DataSource namespaceDataSource = {readNamespaces, writeNamespaces};
23208 retVal |= UA_Server_setVariableNode_dataSource(server,
23209 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY),
23210 dataSource: namespaceDataSource);
23211 retVal |= UA_Server_writeValueRank(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY), valueRank: 1);
23212
23213 /* ServerArray */
23214 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY,
23215 v: &server->config.applicationDescription.applicationUri,
23216 length: 1, type: &UA_TYPES[UA_TYPES_STRING]);
23217 retVal |= UA_Server_writeValueRank(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERARRAY), valueRank: 1);
23218
23219 /* ServerStatus */
23220 UA_DataSource serverStatus = {readStatus, NULL};
23221 retVal |= UA_Server_setVariableNode_dataSource(server,
23222 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS), dataSource: serverStatus);
23223
23224 /* StartTime will be sampled in UA_Server_run_startup()*/
23225
23226 /* CurrentTime */
23227 UA_DataSource currentTime = {readCurrentTime, NULL};
23228 UA_NodeId currTime = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME);
23229 retVal |= UA_Server_setVariableNode_dataSource(server, nodeId: currTime, dataSource: currentTime);
23230 retVal |= UA_Server_writeMinimumSamplingInterval(server, nodeId: currTime, miniumSamplingInterval: 100.0);
23231
23232 /* State */
23233 retVal |= UA_Server_setVariableNode_dataSource(server,
23234 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE),
23235 dataSource: serverStatus);
23236
23237 /* BuildInfo */
23238 retVal |= UA_Server_setVariableNode_dataSource(server,
23239 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), dataSource: serverStatus);
23240
23241 /* BuildInfo - ProductUri */
23242 retVal |= UA_Server_setVariableNode_dataSource(server,
23243 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI),
23244 dataSource: serverStatus);
23245
23246 /* BuildInfo - ManufacturerName */
23247 retVal |= UA_Server_setVariableNode_dataSource(server,
23248 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME),
23249 dataSource: serverStatus);
23250
23251 /* BuildInfo - ProductName */
23252 retVal |= UA_Server_setVariableNode_dataSource(server,
23253 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME),
23254 dataSource: serverStatus);
23255
23256 /* BuildInfo - SoftwareVersion */
23257 retVal |= UA_Server_setVariableNode_dataSource(server,
23258 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION),
23259 dataSource: serverStatus);
23260
23261 /* BuildInfo - BuildNumber */
23262 retVal |= UA_Server_setVariableNode_dataSource(server,
23263 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER),
23264 dataSource: serverStatus);
23265
23266 /* BuildInfo - BuildDate */
23267 retVal |= UA_Server_setVariableNode_dataSource(server,
23268 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE),
23269 dataSource: serverStatus);
23270
23271#ifdef UA_GENERATED_NAMESPACE_ZERO
23272
23273 /* SecondsTillShutdown */
23274 retVal |= UA_Server_setVariableNode_dataSource(server,
23275 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN),
23276 dataSource: serverStatus);
23277
23278 /* ShutDownReason */
23279 UA_LocalizedText shutdownReason;
23280 UA_LocalizedText_init(p: &shutdownReason);
23281 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON,
23282 v: &shutdownReason, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
23283
23284 /* ServiceLevel */
23285 UA_DataSource serviceLevel = {readServiceLevel, NULL};
23286 retVal |= UA_Server_setVariableNode_dataSource(server,
23287 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVICELEVEL), dataSource: serviceLevel);
23288
23289 /* ServerDiagnostics - EnabledFlag */
23290#ifdef UA_ENABLE_DIAGNOSTICS
23291 UA_Boolean enabledFlag = true;
23292#else
23293 UA_Boolean enabledFlag = false;
23294#endif
23295 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG,
23296 v: &enabledFlag, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23297
23298 /* According to Specification part-5 - pg.no-11(PDF pg.no-29), when the ServerDiagnostics is disabled the client
23299 * may modify the value of enabledFlag=true in the server. By default, this node have CurrentRead/Write access.
23300 * In CTT, Subscription_Minimum_1/002.js test will modify the above flag. This will not be a problem when build
23301 * configuration is set at UA_NAMESPACE_ZERO="REDUCED" as NodeIds will not be present. When UA_NAMESPACE_ZERO="FULL",
23302 * the test will fail. Hence made the NodeId as read only */
23303 retVal |= UA_Server_writeAccessLevel(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG),
23304 UA_ACCESSLEVELMASK_READ);
23305
23306 /* Auditing */
23307 UA_DataSource auditing = {readAuditing, NULL};
23308 retVal |= UA_Server_setVariableNode_dataSource(server,
23309 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_AUDITING), dataSource: auditing);
23310
23311 /* Redundancy Support */
23312 UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE;
23313 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT,
23314 v: &redundancySupport, type: &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]);
23315
23316 /* Remove unused subtypes of ServerRedundancy */
23317 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_CURRENTSERVERID), true);
23318 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANTSERVERARRAY), true);
23319 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERURIARRAY), true);
23320 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERNETWORKGROUPS), true);
23321
23322 /* ServerCapabilities - LocaleIdArray */
23323 UA_LocaleId locale_en = UA_STRING(chars: "en");
23324 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY,
23325 v: &locale_en, length: 1, type: &UA_TYPES[UA_TYPES_LOCALEID]);
23326
23327 /* ServerCapabilities - MaxBrowseContinuationPoints */
23328 UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS;
23329 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS,
23330 v: &maxBrowseContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23331
23332 /* ServerProfileArray */
23333 UA_String profileArray[3];
23334 UA_UInt16 profileArraySize = 0;
23335#define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x)
23336 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/MicroEmbeddedDevice");
23337#ifdef UA_ENABLE_NODEMANAGEMENT
23338 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement");
23339#endif
23340#ifdef UA_ENABLE_METHODCALLS
23341 ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods");
23342#endif
23343 retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY,
23344 v: profileArray, length: profileArraySize, type: &UA_TYPES[UA_TYPES_STRING]);
23345
23346 /* ServerCapabilities - MaxQueryContinuationPoints */
23347 UA_UInt16 maxQueryContinuationPoints = 0;
23348 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS,
23349 v: &maxQueryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23350
23351 /* ServerCapabilities - MaxHistoryContinuationPoints */
23352 UA_UInt16 maxHistoryContinuationPoints = 0;
23353 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS,
23354 v: &maxHistoryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]);
23355
23356 /* ServerCapabilities - MinSupportedSampleRate */
23357 UA_DataSource samplingInterval = {readMinSamplingInterval, NULL};
23358 retVal |= UA_Server_setVariableNode_dataSource(server,
23359 nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE),
23360 dataSource: samplingInterval);
23361
23362 /* ServerCapabilities - OperationLimits - MaxNodesPerRead */
23363 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD,
23364 v: &server->config.maxNodesPerRead, type: &UA_TYPES[UA_TYPES_UINT32]);
23365
23366 /* ServerCapabilities - OperationLimits - maxNodesPerWrite */
23367 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE,
23368 v: &server->config.maxNodesPerWrite, type: &UA_TYPES[UA_TYPES_UINT32]);
23369
23370 /* ServerCapabilities - OperationLimits - MaxNodesPerMethodCall */
23371 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL,
23372 v: &server->config.maxNodesPerMethodCall, type: &UA_TYPES[UA_TYPES_UINT32]);
23373
23374 /* ServerCapabilities - OperationLimits - MaxNodesPerBrowse */
23375 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE,
23376 v: &server->config.maxNodesPerBrowse, type: &UA_TYPES[UA_TYPES_UINT32]);
23377
23378 /* ServerCapabilities - OperationLimits - MaxNodesPerRegisterNodes */
23379 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES,
23380 v: &server->config.maxNodesPerRegisterNodes, type: &UA_TYPES[UA_TYPES_UINT32]);
23381
23382 /* ServerCapabilities - OperationLimits - MaxNodesPerTranslateBrowsePathsToNodeIds */
23383 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS,
23384 v: &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, type: &UA_TYPES[UA_TYPES_UINT32]);
23385
23386 /* ServerCapabilities - OperationLimits - MaxNodesPerNodeManagement */
23387 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT,
23388 v: &server->config.maxNodesPerNodeManagement, type: &UA_TYPES[UA_TYPES_UINT32]);
23389
23390 /* ServerCapabilities - OperationLimits - MaxMonitoredItemsPerCall */
23391 retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL,
23392 v: &server->config.maxMonitoredItemsPerCall, type: &UA_TYPES[UA_TYPES_UINT32]);
23393
23394 /* Remove unused operation limit components */
23395 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true);
23396 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true);
23397 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEDATA), true);
23398 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEEVENTS), true);
23399 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET), true);
23400 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSTRINGLENGTH), true);
23401 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true);
23402 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true);
23403
23404 /* Remove not supported server configurations */
23405 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_ESTIMATEDRETURNTIME), true);
23406 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_LOCALTIME), true);
23407 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_REQUESTSERVERSTATECHANGE), true);
23408 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_RESENDDATA), true);
23409 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVERCONFIGURATION), true);
23410 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SETSUBSCRIPTIONDURABLE), true);
23411
23412#ifdef UA_ENABLE_DIAGNOSTICS
23413 /* ServerDiagnostics - ServerDiagnosticsSummary */
23414 UA_DataSource serverDiagSummary = {readDiagnostics, NULL};
23415 retVal |= UA_Server_setVariableNode_dataSource(server,
23416 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), serverDiagSummary);
23417
23418 /* ServerDiagnostics - ServerDiagnosticsSummary - ServerViewCount */
23419 retVal |= UA_Server_setVariableNode_dataSource(server,
23420 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), serverDiagSummary);
23421
23422 /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSessionCount */
23423 retVal |= UA_Server_setVariableNode_dataSource(server,
23424 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), serverDiagSummary);
23425
23426 /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSessionCount */
23427 retVal |= UA_Server_setVariableNode_dataSource(server,
23428 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), serverDiagSummary);
23429
23430 /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedSessionCount */
23431 retVal |= UA_Server_setVariableNode_dataSource(server,
23432 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), serverDiagSummary);
23433
23434 /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedSessionCount */
23435 retVal |= UA_Server_setVariableNode_dataSource(server,
23436 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), serverDiagSummary);
23437
23438 /* ServerDiagnostics - ServerDiagnosticsSummary - SessionTimeoutCount */
23439 retVal |= UA_Server_setVariableNode_dataSource(server,
23440 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), serverDiagSummary);
23441
23442 /* ServerDiagnostics - ServerDiagnosticsSummary - SessionAbortCount */
23443 retVal |= UA_Server_setVariableNode_dataSource(server,
23444 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), serverDiagSummary);
23445
23446 /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSubscriptionCount */
23447 retVal |= UA_Server_setVariableNode_dataSource(server,
23448 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), serverDiagSummary);
23449
23450 /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSubscriptionCount */
23451 retVal |= UA_Server_setVariableNode_dataSource(server,
23452 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), serverDiagSummary);
23453
23454 /* ServerDiagnostics - ServerDiagnosticsSummary - PublishingIntervalCount */
23455 retVal |= UA_Server_setVariableNode_dataSource(server,
23456 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), serverDiagSummary);
23457
23458 /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedRequestsCount */
23459 retVal |= UA_Server_setVariableNode_dataSource(server,
23460 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), serverDiagSummary);
23461
23462 /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedRequestsCount */
23463 retVal |= UA_Server_setVariableNode_dataSource(server,
23464 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), serverDiagSummary);
23465
23466 /* ServerDiagnostics - SubscriptionDiagnosticsArray */
23467#ifdef UA_ENABLE_SUBSCRIPTIONS
23468 UA_DataSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL};
23469 retVal |= UA_Server_setVariableNode_dataSource(server,
23470 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), serverSubDiagSummary);
23471#endif
23472
23473 /* ServerDiagnostics - SessionDiagnosticsSummary - SessionDiagnosticsArray */
23474 UA_DataSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL};
23475 retVal |= UA_Server_setVariableNode_dataSource(server,
23476 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), sessionDiagSummary);
23477
23478 /* ServerDiagnostics - SessionDiagnosticsSummary - SessionSecurityDiagnosticsArray */
23479 UA_DataSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL};
23480 retVal |= UA_Server_setVariableNode_dataSource(server,
23481 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), sessionSecDiagSummary);
23482
23483#else
23484 /* Removing these NodeIds make Server Object to be non-complaint with UA
23485 * 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js) In the
23486 * 1.04 specification this has been resolved by allowing to remove these
23487 * static nodes as well */
23488 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true);
23489 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true);
23490 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true);
23491 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true);
23492#endif
23493
23494#ifndef UA_ENABLE_PUBSUB
23495 UA_Server_deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE), true);
23496#endif
23497
23498#ifndef UA_ENABLE_HISTORIZING
23499 UA_Server_deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HISTORYSERVERCAPABILITIES), true);
23500#else
23501 /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryDataCapability */
23502 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYDATACAPABILITY,
23503 v: &server->config.accessHistoryDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23504
23505 /* ServerCapabilities - HistoryServerCapabilities - MaxReturnDataValues */
23506 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNDATAVALUES,
23507 v: &server->config.maxReturnDataValues, type: &UA_TYPES[UA_TYPES_UINT32]);
23508
23509 /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryEventsCapability */
23510 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYEVENTSCAPABILITY,
23511 v: &server->config.accessHistoryEventsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23512
23513 /* ServerCapabilities - HistoryServerCapabilities - MaxReturnEventValues */
23514 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNEVENTVALUES,
23515 v: &server->config.maxReturnEventValues, type: &UA_TYPES[UA_TYPES_UINT32]);
23516
23517 /* ServerCapabilities - HistoryServerCapabilities - InsertDataCapability */
23518 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTDATACAPABILITY,
23519 v: &server->config.insertDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23520
23521 /* ServerCapabilities - HistoryServerCapabilities - InsertEventCapability */
23522 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTEVENTCAPABILITY,
23523 v: &server->config.insertEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23524
23525 /* ServerCapabilities - HistoryServerCapabilities - InsertAnnotationsCapability */
23526 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTANNOTATIONCAPABILITY,
23527 v: &server->config.insertAnnotationsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23528
23529 /* ServerCapabilities - HistoryServerCapabilities - ReplaceDataCapability */
23530 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEDATACAPABILITY,
23531 v: &server->config.replaceDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23532
23533 /* ServerCapabilities - HistoryServerCapabilities - ReplaceEventCapability */
23534 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEEVENTCAPABILITY,
23535 v: &server->config.replaceEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23536
23537 /* ServerCapabilities - HistoryServerCapabilities - UpdateDataCapability */
23538 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEDATACAPABILITY,
23539 v: &server->config.updateDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23540
23541 /* ServerCapabilities - HistoryServerCapabilities - UpdateEventCapability */
23542 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEEVENTCAPABILITY,
23543 v: &server->config.updateEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23544
23545 /* ServerCapabilities - HistoryServerCapabilities - DeleteRawCapability */
23546 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETERAWCAPABILITY,
23547 v: &server->config.deleteRawCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23548
23549 /* ServerCapabilities - HistoryServerCapabilities - DeleteEventCapability */
23550 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEEVENTCAPABILITY,
23551 v: &server->config.deleteEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23552
23553 /* ServerCapabilities - HistoryServerCapabilities - DeleteAtTimeDataCapability */
23554 retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEATTIMECAPABILITY,
23555 v: &server->config.deleteAtTimeDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
23556#endif
23557
23558#if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS)
23559 retVal |= UA_Server_setMethodNodeCallback(server,
23560 methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_GETMONITOREDITEMS), methodCallback: readMonitoredItems);
23561#endif
23562
23563 /* The HasComponent references to the ModellingRules are not part of the
23564 * Nodeset2.xml. So we add the references manually. */
23565 addModellingRules(server);
23566
23567#endif /* UA_GENERATED_NAMESPACE_ZERO */
23568
23569 if(retVal != UA_STATUSCODE_GOOD) {
23570 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
23571 msg: "Initialization of Namespace 0 (after bootstrapping) "
23572 "failed with %s. See previous outputs for any error messages.",
23573 UA_StatusCode_name(code: retVal));
23574 return UA_STATUSCODE_BADINTERNALERROR;
23575 }
23576 return UA_STATUSCODE_GOOD;
23577}
23578
23579/**** amalgamated original file "/src/server/ua_server_ns0_diagnostics.c" ****/
23580
23581/* This Source Code Form is subject to the terms of the Mozilla Public
23582 * License, v. 2.0. If a copy of the MPL was not distributed with this
23583 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
23584 *
23585 * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
23586 */
23587
23588
23589#ifdef UA_ENABLE_DIAGNOSTICS
23590
23591static UA_Boolean
23592equalBrowseName(UA_String *bn, char *n) {
23593 UA_String name = UA_STRING(n);
23594 return UA_String_equal(bn, &name);
23595}
23596
23597#ifdef UA_ENABLE_SUBSCRIPTIONS
23598
23599/****************************/
23600/* Subscription Diagnostics */
23601/****************************/
23602
23603static void
23604fillSubscriptionDiagnostics(UA_Subscription *sub,
23605 UA_SubscriptionDiagnosticsDataType *diag) {
23606 UA_NodeId_copy(&sub->session->sessionId, &diag->sessionId); /* ignore status */
23607 diag->subscriptionId = sub->subscriptionId;
23608 diag->priority = sub->priority;
23609 diag->publishingInterval = sub->publishingInterval;
23610 diag->maxKeepAliveCount = sub->maxKeepAliveCount;
23611 diag->maxLifetimeCount = sub->lifeTimeCount;
23612 diag->maxNotificationsPerPublish = sub->notificationsPerPublish;
23613 diag->publishingEnabled = sub->publishingEnabled;
23614 diag->modifyCount = sub->modifyCount;
23615 diag->enableCount = sub->enableCount;
23616 diag->disableCount = sub->disableCount;
23617 diag->republishRequestCount = sub->republishRequestCount;
23618 diag->republishMessageRequestCount =
23619 sub->republishRequestCount; /* Always equal to the previous republishRequestCount */
23620 diag->republishMessageCount = sub->republishMessageCount;
23621 diag->transferRequestCount = sub->transferRequestCount;
23622 diag->transferredToAltClientCount = sub->transferredToAltClientCount;
23623 diag->transferredToSameClientCount = sub->transferredToSameClientCount;
23624 diag->publishRequestCount = sub->publishRequestCount;
23625 diag->dataChangeNotificationsCount = sub->dataChangeNotificationsCount;
23626 diag->eventNotificationsCount = sub->eventNotificationsCount;
23627 diag->notificationsCount = sub->notificationsCount;
23628 diag->latePublishRequestCount = sub->latePublishRequestCount;
23629 diag->currentKeepAliveCount = sub->currentKeepAliveCount;
23630 diag->currentLifetimeCount = sub->currentLifetimeCount;
23631 diag->unacknowledgedMessageCount = (UA_UInt32)sub->retransmissionQueueSize;
23632 diag->discardedMessageCount = sub->discardedMessageCount;
23633 diag->monitoredItemCount = sub->monitoredItemsSize;
23634 diag->monitoringQueueOverflowCount = sub->monitoringQueueOverflowCount;
23635 diag->nextSequenceNumber = sub->nextSequenceNumber;
23636 diag->eventQueueOverFlowCount = sub->eventQueueOverFlowCount;
23637
23638 /* Count the disabled MonitoredItems */
23639 UA_MonitoredItem *mon;
23640 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
23641 if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED)
23642 diag->disabledMonitoredItemCount++;
23643 }
23644}
23645
23646/* The node context points to the subscription */
23647static UA_StatusCode
23648readSubscriptionDiagnostics(UA_Server *server,
23649 const UA_NodeId *sessionId, void *sessionContext,
23650 const UA_NodeId *nodeId, void *nodeContext,
23651 UA_Boolean sourceTimestamp,
23652 const UA_NumericRange *range, UA_DataValue *value) {
23653 UA_LOCK(&server->serviceMutex);
23654
23655 /* Check the Subscription pointer */
23656 UA_Subscription *sub = (UA_Subscription*)nodeContext;
23657 if(!sub) {
23658 UA_UNLOCK(&server->serviceMutex);
23659 return UA_STATUSCODE_BADINTERNALERROR;
23660 }
23661
23662 /* Read the BrowseName */
23663 UA_QualifiedName bn;
23664 UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
23665 if(res != UA_STATUSCODE_GOOD) {
23666 UA_UNLOCK(&server->serviceMutex);
23667 return res;
23668 }
23669
23670 /* Set the value */
23671 UA_SubscriptionDiagnosticsDataType sddt;
23672 UA_SubscriptionDiagnosticsDataType_init(&sddt);
23673 fillSubscriptionDiagnostics(sub, &sddt);
23674
23675 char memberName[128];
23676 memcpy(memberName, bn.name.data, bn.name.length);
23677 memberName[bn.name.length] = 0;
23678
23679 size_t memberOffset;
23680 const UA_DataType *memberType;
23681 UA_Boolean isArray;
23682 UA_Boolean found =
23683 UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE],
23684 memberName, &memberOffset, &memberType, &isArray);
23685 if(!found) {
23686 /* Not the member, but the main subscription diagnostics variable... */
23687 memberOffset = 0;
23688 memberType = &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE];
23689 }
23690
23691 void *content = (void*)(((uintptr_t)&sddt) + memberOffset);
23692 res = UA_Variant_setScalarCopy(&value->value, content, memberType);
23693 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
23694 value->hasValue = true;
23695
23696 UA_SubscriptionDiagnosticsDataType_clear(&sddt);
23697 UA_QualifiedName_clear(&bn);
23698
23699 UA_UNLOCK(&server->serviceMutex);
23700 return res;
23701}
23702
23703/* If the nodeContext == NULL, return all subscriptions in the server.
23704 * Otherwise only for the current session. */
23705static UA_StatusCode
23706readSubscriptionDiagnosticsArrayLocked(UA_Server *server,
23707 const UA_NodeId *sessionId, void *sessionContext,
23708 const UA_NodeId *nodeId, void *nodeContext,
23709 UA_Boolean sourceTimestamp,
23710 const UA_NumericRange *range, UA_DataValue *value) {
23711 UA_LOCK_ASSERT(&server->serviceMutex, 1);
23712
23713 /* Get the current session */
23714 size_t sdSize = 0;
23715 UA_Session *session = NULL;
23716 session_list_entry *sentry;
23717 if(nodeContext) {
23718 session = UA_Server_getSessionById(server, sessionId);
23719 if(!session)
23720 return UA_STATUSCODE_BADINTERNALERROR;
23721 sdSize = session->subscriptionsSize;
23722 } else {
23723 LIST_FOREACH(sentry, &server->sessions, pointers) {
23724 sdSize += sentry->session.subscriptionsSize;
23725 }
23726 }
23727
23728 /* Allocate the output array */
23729 UA_SubscriptionDiagnosticsDataType *sd = (UA_SubscriptionDiagnosticsDataType*)
23730 UA_Array_new(sdSize, &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
23731 if(!sd)
23732 return UA_STATUSCODE_BADOUTOFMEMORY;
23733
23734 /* Collect the statistics */
23735 size_t i = 0;
23736 UA_Subscription *sub;
23737 if(session) {
23738 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
23739 fillSubscriptionDiagnostics(sub, &sd[i]);
23740 i++;
23741 }
23742 } else {
23743 LIST_FOREACH(sentry, &server->sessions, pointers) {
23744 TAILQ_FOREACH(sub, &sentry->session.subscriptions, sessionListEntry) {
23745 fillSubscriptionDiagnostics(sub, &sd[i]);
23746 i++;
23747 }
23748 }
23749 }
23750
23751 /* Set the output */
23752 value->hasValue = true;
23753 UA_Variant_setArray(&value->value, sd, sdSize,
23754 &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]);
23755 return UA_STATUSCODE_GOOD;
23756}
23757
23758UA_StatusCode
23759readSubscriptionDiagnosticsArray(UA_Server *server,
23760 const UA_NodeId *sessionId, void *sessionContext,
23761 const UA_NodeId *nodeId, void *nodeContext,
23762 UA_Boolean sourceTimestamp,
23763 const UA_NumericRange *range, UA_DataValue *value) {
23764 UA_LOCK(&server->serviceMutex);
23765 UA_StatusCode res = readSubscriptionDiagnosticsArrayLocked(
23766 server, sessionId, sessionContext, nodeId, nodeContext,
23767 sourceTimestamp, range, value);
23768 UA_UNLOCK(&server->serviceMutex);
23769 return res;
23770}
23771
23772void
23773createSubscriptionObject(UA_Server *server, UA_Session *session,
23774 UA_Subscription *sub) {
23775 UA_ExpandedNodeId *children = NULL;
23776 size_t childrenSize = 0;
23777 UA_ReferenceTypeSet refTypes;
23778 UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
23779
23780 char subIdStr[32];
23781 snprintf(subIdStr, 32, "%u", sub->subscriptionId);
23782
23783 /* Find the NodeId of the SubscriptionDiagnosticsArray */
23784 UA_BrowsePath bp;
23785 UA_BrowsePath_init(&bp);
23786 bp.startingNode = sub->session->sessionId;
23787 UA_RelativePathElement rpe[1];
23788 memset(rpe, 0, sizeof(UA_RelativePathElement) * 1);
23789 rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
23790 bp.relativePath.elements = rpe;
23791 bp.relativePath.elementsSize = 1;
23792 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
23793 if(bpr.targetsSize < 1)
23794 return;
23795
23796 /* Create an object for the subscription. Instantiates all the mandatory
23797 * children. */
23798 UA_VariableAttributes var_attr = UA_VariableAttributes_default;
23799 var_attr.displayName.text = UA_STRING(subIdStr);
23800 var_attr.dataType = UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE].typeId;
23801 UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
23802 UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, subIdStr);
23803 UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SUBSCRIPTIONDIAGNOSTICSTYPE);
23804 UA_NodeId objId = UA_NODEID_NUMERIC(1, 0); /* 0 => assign a random free id */
23805 UA_StatusCode res = addNode(server, UA_NODECLASS_VARIABLE,
23806 &objId,
23807 &bpr.targets[0].targetId.nodeId /* parent */,
23808 &refId, browseName, &typeId,
23809 (UA_NodeAttributes*)&var_attr,
23810 &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, &objId);
23811 UA_CHECK_STATUS(res, goto cleanup);
23812
23813 /* Add a second reference from the overall SubscriptionDiagnosticsArray variable */
23814 const UA_NodeId subDiagArray =
23815 UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY);
23816 res = addRef(server, session, &subDiagArray, &refId, &objId, true);
23817
23818 /* Get all children (including the variable itself) and set the contenxt + callback */
23819 res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
23820 if(res != UA_STATUSCODE_GOOD)
23821 goto cleanup;
23822 res = browseRecursive(server, 1, &objId,
23823 UA_BROWSEDIRECTION_FORWARD, &refTypes,
23824 UA_NODECLASS_VARIABLE, true, &childrenSize, &children);
23825 if(res != UA_STATUSCODE_GOOD)
23826 goto cleanup;
23827
23828 /* Add the callback to all variables */
23829 UA_DataSource subDiagSource = {readSubscriptionDiagnostics, NULL};
23830 for(size_t i = 0; i < childrenSize; i++) {
23831 setVariableNode_dataSource(server, children[i].nodeId, subDiagSource);
23832 setNodeContext(server, children[i].nodeId, sub);
23833 }
23834
23835 UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
23836
23837 cleanup:
23838 UA_BrowsePathResult_clear(&bpr);
23839 if(res != UA_STATUSCODE_GOOD) {
23840 UA_LOG_WARNING_SESSION(&server->config.logger, session,
23841 "Creating the subscription diagnostics object failed "
23842 "with StatusCode %s", UA_StatusCode_name(res));
23843 }
23844}
23845
23846#endif /* UA_ENABLE_SUBSCRIPTIONS */
23847
23848/***********************/
23849/* Session Diagnostics */
23850/***********************/
23851
23852static void
23853setSessionDiagnostics(UA_Session *session, UA_SessionDiagnosticsDataType *sd) {
23854 UA_SessionDiagnosticsDataType_copy(&session->diagnostics, sd);
23855 UA_NodeId_copy(&session->sessionId, &sd->sessionId);
23856 UA_String_copy(&session->sessionName, &sd->sessionName);
23857 UA_ApplicationDescription_copy(&session->clientDescription,
23858 &sd->clientDescription);
23859 sd->maxResponseMessageSize = session->maxResponseMessageSize;
23860#ifdef UA_ENABLE_SUBSCRIPTIONS
23861 sd->currentPublishRequestsInQueue = (UA_UInt32)session->responseQueueSize;
23862#endif
23863 sd->actualSessionTimeout = session->timeout;
23864
23865 /* Set LocaleIds */
23866 UA_StatusCode res =
23867 UA_Array_copy(session->localeIds, session->localeIdsSize,
23868 (void **)&sd->localeIds, &UA_TYPES[UA_TYPES_STRING]);
23869 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
23870 sd->localeIdsSize = session->localeIdsSize;
23871
23872 /* Set Subscription diagnostics */
23873#ifdef UA_ENABLE_SUBSCRIPTIONS
23874 sd->currentSubscriptionsCount = (UA_UInt32)session->subscriptionsSize;
23875
23876 UA_Subscription *sub;
23877 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
23878 sd->currentMonitoredItemsCount += (UA_UInt32)sub->monitoredItemsSize;
23879 }
23880#endif
23881}
23882
23883UA_StatusCode
23884readSessionDiagnosticsArray(UA_Server *server,
23885 const UA_NodeId *sessionId, void *sessionContext,
23886 const UA_NodeId *nodeId, void *nodeContext,
23887 UA_Boolean sourceTimestamp,
23888 const UA_NumericRange *range, UA_DataValue *value) {
23889 /* Allocate the output array */
23890 UA_SessionDiagnosticsDataType *sd = (UA_SessionDiagnosticsDataType*)
23891 UA_Array_new(server->sessionCount,
23892 &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
23893 if(!sd)
23894 return UA_STATUSCODE_BADOUTOFMEMORY;
23895
23896 /* Collect the statistics */
23897 size_t i = 0;
23898 session_list_entry *session;
23899 LIST_FOREACH(session, &server->sessions, pointers) {
23900 setSessionDiagnostics(&session->session, &sd[i]);
23901 i++;
23902 }
23903
23904 /* Set the output */
23905 value->hasValue = true;
23906 UA_Variant_setArray(&value->value, sd, server->sessionCount,
23907 &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]);
23908 return UA_STATUSCODE_GOOD;
23909}
23910
23911static void
23912setSessionSecurityDiagnostics(UA_Session *session,
23913 UA_SessionSecurityDiagnosticsDataType *sd) {
23914 UA_SessionSecurityDiagnosticsDataType_copy(&session->securityDiagnostics, sd);
23915 UA_NodeId_copy(&session->sessionId, &sd->sessionId);
23916 UA_SecureChannel *channel = session->header.channel;
23917 if(channel) {
23918 UA_ByteString_copy(&channel->remoteCertificate, &sd->clientCertificate);
23919 UA_String_copy(&channel->securityPolicy->policyUri, &sd->securityPolicyUri);
23920 sd->securityMode = channel->securityMode;
23921 sd->encoding = UA_STRING_ALLOC("UA Binary"); /* The only one atm */
23922 sd->transportProtocol = UA_STRING_ALLOC("opc.tcp"); /* The only one atm */
23923 }
23924}
23925
23926static UA_StatusCode
23927readSessionDiagnostics(UA_Server *server,
23928 const UA_NodeId *sessionId, void *sessionContext,
23929 const UA_NodeId *nodeId, void *nodeContext,
23930 UA_Boolean sourceTimestamp,
23931 const UA_NumericRange *range, UA_DataValue *value) {
23932 UA_LOCK(&server->serviceMutex);
23933
23934 /* Get the Session */
23935 UA_Session *session = UA_Server_getSessionById(server, sessionId);
23936 if(!session) {
23937 UA_UNLOCK(&server->serviceMutex);
23938 return UA_STATUSCODE_BADINTERNALERROR;
23939 }
23940
23941 /* Read the BrowseName */
23942 UA_QualifiedName bn;
23943 UA_StatusCode res = readWithReadValue(server, nodeId, UA_ATTRIBUTEID_BROWSENAME, &bn);
23944 if(res != UA_STATUSCODE_GOOD) {
23945 UA_UNLOCK(&server->serviceMutex);
23946 return res;
23947 }
23948
23949 union {
23950 UA_SessionDiagnosticsDataType sddt;
23951 UA_SessionSecurityDiagnosticsDataType ssddt;
23952 } data;
23953 void *content;
23954 UA_Boolean isArray = false;
23955 const UA_DataType *type = NULL;
23956 UA_Boolean securityDiagnostics = false;
23957
23958 char memberName[128];
23959 size_t memberOffset;
23960 UA_Boolean found;
23961
23962 if(equalBrowseName(&bn.name, "SubscriptionDiagnosticsArray")) {
23963 /* Reuse the datasource callback. Forward a non-null nodeContext to
23964 * indicate that we want to see only the subscriptions for the current
23965 * session. */
23966 res = readSubscriptionDiagnosticsArrayLocked(server, sessionId, sessionContext,
23967 nodeId, (void*)0x01,
23968 sourceTimestamp, range, value);
23969 goto cleanup;
23970 } else if(equalBrowseName(&bn.name, "SessionDiagnostics")) {
23971 setSessionDiagnostics(session, &data.sddt);
23972 content = &data.sddt;
23973 type = &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE];
23974 goto set_value;
23975 } else if(equalBrowseName(&bn.name, "SessionSecurityDiagnostics")) {
23976 setSessionSecurityDiagnostics(session, &data.ssddt);
23977 securityDiagnostics = true;
23978 content = &data.ssddt;
23979 type = &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE];
23980 goto set_value;
23981 }
23982
23983 /* Try to find the member in SessionDiagnosticsDataType and
23984 * SessionSecurityDiagnosticsDataType */
23985 memcpy(memberName, bn.name.data, bn.name.length);
23986 memberName[bn.name.length] = 0;
23987 found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE],
23988 memberName, &memberOffset, &type, &isArray);
23989 if(found) {
23990 setSessionDiagnostics(session, &data.sddt);
23991 content = (void*)(((uintptr_t)&data.sddt) + memberOffset);
23992 } else {
23993 found = UA_DataType_getStructMember(&UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE],
23994 memberName, &memberOffset, &type, &isArray);
23995 if(!found) {
23996 res = UA_STATUSCODE_BADNOTIMPLEMENTED;
23997 goto cleanup;
23998 }
23999 setSessionSecurityDiagnostics(session, &data.ssddt);
24000 securityDiagnostics = true;
24001 content = (void*)(((uintptr_t)&data.ssddt) + memberOffset);
24002 }
24003
24004 set_value:
24005 if(!isArray) {
24006 res = UA_Variant_setScalarCopy(&value->value, content, type);
24007 } else {
24008 size_t len = *(size_t*)content;
24009 content = *(void**)((uintptr_t)content + sizeof(size_t));
24010 res = UA_Variant_setArrayCopy(&value->value, content, len, type);
24011 }
24012 if(UA_LIKELY(res == UA_STATUSCODE_GOOD))
24013 value->hasValue = true;
24014
24015 if(securityDiagnostics)
24016 UA_SessionSecurityDiagnosticsDataType_clear(&data.ssddt);
24017 else
24018 UA_SessionDiagnosticsDataType_clear(&data.sddt);
24019
24020 cleanup:
24021 UA_QualifiedName_clear(&bn);
24022 UA_UNLOCK(&server->serviceMutex);
24023 return res;
24024}
24025
24026UA_StatusCode
24027readSessionSecurityDiagnostics(UA_Server *server,
24028 const UA_NodeId *sessionId, void *sessionContext,
24029 const UA_NodeId *nodeId, void *nodeContext,
24030 UA_Boolean sourceTimestamp,
24031 const UA_NumericRange *range, UA_DataValue *value) {
24032 /* Allocate the output array */
24033 UA_SessionSecurityDiagnosticsDataType *sd = (UA_SessionSecurityDiagnosticsDataType*)
24034 UA_Array_new(server->sessionCount,
24035 &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
24036 if(!sd)
24037 return UA_STATUSCODE_BADOUTOFMEMORY;
24038
24039 /* Collect the statistics */
24040 size_t i = 0;
24041 session_list_entry *session;
24042 LIST_FOREACH(session, &server->sessions, pointers) {
24043 setSessionSecurityDiagnostics(&session->session, &sd[i]);
24044 i++;
24045 }
24046
24047 /* Set the output */
24048 value->hasValue = true;
24049 UA_Variant_setArray(&value->value, sd, server->sessionCount,
24050 &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]);
24051 return UA_STATUSCODE_GOOD;
24052}
24053
24054void
24055createSessionObject(UA_Server *server, UA_Session *session) {
24056 UA_ExpandedNodeId *children = NULL;
24057 size_t childrenSize = 0;
24058 UA_ReferenceTypeSet refTypes;
24059 UA_NodeId hasComponent = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
24060
24061 /* Create an object for the session. Instantiates all the mandatory children. */
24062 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
24063 object_attr.displayName.text = session->sessionName;
24064 UA_NodeId parentId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY);
24065 UA_NodeId refId = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT);
24066 UA_QualifiedName browseName = UA_QUALIFIEDNAME(0, "");
24067 browseName.name = session->sessionName; /* shallow copy */
24068 UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SESSIONDIAGNOSTICSOBJECTTYPE);
24069 UA_StatusCode res = addNode(server, UA_NODECLASS_OBJECT,
24070 &session->sessionId, &parentId, &refId, browseName, &typeId,
24071 (UA_NodeAttributes*)&object_attr,
24072 &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL);
24073 if(res != UA_STATUSCODE_GOOD)
24074 goto cleanup;
24075
24076 /* Recursively browse all children */
24077 res = referenceTypeIndices(server, &hasComponent, &refTypes, false);
24078 if(res != UA_STATUSCODE_GOOD)
24079 goto cleanup;
24080 res = browseRecursive(server, 1, &session->sessionId,
24081 UA_BROWSEDIRECTION_FORWARD, &refTypes,
24082 UA_NODECLASS_VARIABLE, false, &childrenSize, &children);
24083 if(res != UA_STATUSCODE_GOOD)
24084 goto cleanup;
24085
24086 /* Add the callback to all variables */
24087 UA_DataSource sessionDiagSource = {readSessionDiagnostics, NULL};
24088 for(size_t i = 0; i < childrenSize; i++) {
24089 setVariableNode_dataSource(server, children[i].nodeId, sessionDiagSource);
24090 }
24091
24092 cleanup:
24093 if(res != UA_STATUSCODE_GOOD) {
24094 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24095 "Creating the session diagnostics object failed "
24096 "with StatusCode %s", UA_StatusCode_name(res));
24097 }
24098 UA_Array_delete(children, childrenSize, &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
24099}
24100
24101/***************************/
24102/* Server-Wide Diagnostics */
24103/***************************/
24104
24105UA_StatusCode
24106readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
24107 const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp,
24108 const UA_NumericRange *range, UA_DataValue *value) {
24109 if(range) {
24110 value->hasStatus = true;
24111 value->status = UA_STATUSCODE_BADINDEXRANGEINVALID;
24112 return UA_STATUSCODE_GOOD;
24113 }
24114
24115 if(sourceTimestamp) {
24116 value->hasSourceTimestamp = true;
24117 value->sourceTimestamp = UA_DateTime_now();
24118 }
24119
24120 UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC);
24121
24122 void *data = NULL;
24123 const UA_DataType *type = &UA_TYPES[UA_TYPES_UINT32]; /* Default */
24124
24125 switch(nodeId->identifier.numeric) {
24126 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY:
24127 server->serverDiagnosticsSummary.currentSessionCount =
24128 server->activeSessionCount;
24129 data = &server->serverDiagnosticsSummary;
24130 type = &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE];
24131 break;
24132 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT:
24133 data = &server->serverDiagnosticsSummary.serverViewCount;
24134 break;
24135 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT:
24136 data = &server->activeSessionCount;
24137 break;
24138 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT:
24139 data = &server->serverDiagnosticsSummary.cumulatedSessionCount;
24140 break;
24141 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT:
24142 data = &server->serverDiagnosticsSummary.securityRejectedSessionCount;
24143 break;
24144 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT:
24145 data = &server->serverDiagnosticsSummary.rejectedSessionCount;
24146 break;
24147 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT:
24148 data = &server->serverDiagnosticsSummary.sessionTimeoutCount;
24149 break;
24150 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT:
24151 data = &server->serverDiagnosticsSummary.sessionAbortCount;
24152 break;
24153 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT:
24154 data = &server->serverDiagnosticsSummary.currentSubscriptionCount;
24155 break;
24156 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT:
24157 data = &server->serverDiagnosticsSummary.cumulatedSubscriptionCount;
24158 break;
24159 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT:
24160 data = &server->serverDiagnosticsSummary.publishingIntervalCount;
24161 break;
24162 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT:
24163 data = &server->serverDiagnosticsSummary.securityRejectedRequestsCount;
24164 break;
24165 case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT:
24166 data = &server->serverDiagnosticsSummary.rejectedRequestsCount;
24167 break;
24168 default:
24169 return UA_STATUSCODE_BADINTERNALERROR;
24170 }
24171
24172 UA_StatusCode res = UA_Variant_setScalarCopy(&value->value, data, type);
24173 if(res == UA_STATUSCODE_GOOD)
24174 value->hasValue = true;
24175 return res;
24176}
24177
24178#endif /* UA_ENABLE_DIAGNOSTICS */
24179
24180/**** amalgamated original file "/src/server/ua_server_config.c" ****/
24181
24182/* This Source Code Form is subject to the terms of the Mozilla Public
24183 * License, v. 2.0. If a copy of the MPL was not distributed with this
24184 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
24185 *
24186 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
24187 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
24188 */
24189
24190
24191void
24192UA_ServerConfig_clean(UA_ServerConfig *config) {
24193 if(!config)
24194 return;
24195
24196 /* Server Description */
24197 UA_BuildInfo_clear(p: &config->buildInfo);
24198 UA_ApplicationDescription_clear(p: &config->applicationDescription);
24199#ifdef UA_ENABLE_DISCOVERY_MULTICAST
24200 UA_MdnsDiscoveryConfiguration_clear(&config->mdnsConfig);
24201 UA_String_clear(&config->mdnsInterfaceIP);
24202# if !defined(UA_HAS_GETIFADDR)
24203 if (config->mdnsIpAddressListSize) {
24204 UA_free(config->mdnsIpAddressList);
24205 }
24206# endif
24207#endif
24208
24209 /* Custom DataTypes */
24210 /* nothing to do */
24211
24212 /* Networking */
24213 for(size_t i = 0; i < config->networkLayersSize; ++i)
24214 config->networkLayers[i].clear(&config->networkLayers[i]);
24215 UA_free(ptr: config->networkLayers);
24216 config->networkLayers = NULL;
24217 config->networkLayersSize = 0;
24218 UA_String_clear(p: &config->customHostname);
24219 config->customHostname = UA_STRING_NULL;
24220
24221 for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
24222 UA_SecurityPolicy *policy = &config->securityPolicies[i];
24223 policy->clear(policy);
24224 }
24225 UA_free(ptr: config->securityPolicies);
24226 config->securityPolicies = NULL;
24227 config->securityPoliciesSize = 0;
24228
24229 for(size_t i = 0; i < config->endpointsSize; ++i)
24230 UA_EndpointDescription_clear(p: &config->endpoints[i]);
24231
24232 UA_free(ptr: config->endpoints);
24233 config->endpoints = NULL;
24234 config->endpointsSize = 0;
24235
24236 /* Nodestore */
24237 if(config->nodestore.context && config->nodestore.clear) {
24238 config->nodestore.clear(config->nodestore.context);
24239 config->nodestore.context = NULL;
24240 }
24241
24242 /* Certificate Validation */
24243 if(config->certificateVerification.clear)
24244 config->certificateVerification.clear(&config->certificateVerification);
24245
24246 /* Access Control */
24247 if(config->accessControl.clear)
24248 config->accessControl.clear(&config->accessControl);
24249
24250 /* Historical data */
24251#ifdef UA_ENABLE_HISTORIZING
24252 if(config->historyDatabase.clear)
24253 config->historyDatabase.clear(&config->historyDatabase);
24254#endif
24255
24256 /* Logger */
24257 if(config->logger.clear)
24258 config->logger.clear(config->logger.context);
24259 config->logger.log = NULL;
24260 config->logger.clear = NULL;
24261
24262#ifdef UA_ENABLE_PUBSUB
24263#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
24264 if(config->pubSubConfig.securityPolicies != NULL) {
24265 for(size_t i = 0; i < config->pubSubConfig.securityPoliciesSize; i++) {
24266 config->pubSubConfig.securityPolicies[i].clear(&config->pubSubConfig.securityPolicies[i]);
24267 }
24268 UA_free(config->pubSubConfig.securityPolicies);
24269 config->pubSubConfig.securityPolicies = NULL;
24270 config->pubSubConfig.securityPoliciesSize = 0;
24271 }
24272#endif
24273#endif /* UA_ENABLE_PUBSUB */
24274}
24275
24276#ifdef UA_ENABLE_PUBSUB
24277/* Add a pubsubTransportLayer to the configuration. Memory is reallocated on
24278 * demand. */
24279UA_StatusCode
24280UA_ServerConfig_addPubSubTransportLayer(UA_ServerConfig *config,
24281 UA_PubSubTransportLayer pubsubTransportLayer) {
24282 UA_PubSubTransportLayer *tmpLayers = (UA_PubSubTransportLayer*)
24283 UA_realloc(config->pubSubConfig.transportLayers,
24284 sizeof(UA_PubSubTransportLayer) *
24285 (config->pubSubConfig.transportLayersSize + 1));
24286 if(tmpLayers == NULL)
24287 return UA_STATUSCODE_BADOUTOFMEMORY;
24288
24289 config->pubSubConfig.transportLayers = tmpLayers;
24290 config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = pubsubTransportLayer;
24291 config->pubSubConfig.transportLayersSize++;
24292 return UA_STATUSCODE_GOOD;
24293}
24294#endif /* UA_ENABLE_PUBSUB */
24295
24296/**** amalgamated original file "/src/server/ua_server_binary.c" ****/
24297
24298/* This Source Code Form is subject to the terms of the Mozilla Public
24299 * License, v. 2.0. If a copy of the MPL was not distributed with this
24300 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
24301 *
24302 * Copyright 2014-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
24303 * Copyright 2014-2016 (c) Sten Grüner
24304 * Copyright 2014-2015, 2017 (c) Florian Palm
24305 * Copyright 2015-2016 (c) Chris Iatrou
24306 * Copyright 2015-2016 (c) Oleksiy Vasylyev
24307 * Copyright 2016 (c) Joakim L. Gilje
24308 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
24309 * Copyright 2016 (c) TorbenD
24310 * Copyright 2017 (c) frax2222
24311 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
24312 * Copyright 2019 (c) Kalycito Infotech Private Limited
24313 */
24314
24315
24316
24317#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
24318// store the authentication token and session ID so we can help fuzzing by setting
24319// these values in the next request automatically
24320UA_NodeId unsafe_fuzz_authenticationToken = {0, UA_NODEIDTYPE_NUMERIC, {0}};
24321#endif
24322
24323#ifdef UA_DEBUG_DUMP_PKGS_FILE
24324void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection,
24325 UA_ByteString *messageBuffer);
24326#endif
24327
24328/********************/
24329/* Helper Functions */
24330/********************/
24331
24332UA_StatusCode
24333sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId,
24334 UA_UInt32 requestHandle, UA_StatusCode statusCode) {
24335 UA_ServiceFault response;
24336 UA_ServiceFault_init(p: &response);
24337 UA_ResponseHeader *responseHeader = &response.responseHeader;
24338 responseHeader->requestHandle = requestHandle;
24339 responseHeader->timestamp = UA_DateTime_now();
24340 responseHeader->serviceResult = statusCode;
24341
24342 UA_LOG_DEBUG(logger: channel->securityPolicy->logger, category: UA_LOGCATEGORY_SERVER,
24343 msg: "Sending response for RequestId %u with ServiceResult %s",
24344 (unsigned)requestId, UA_StatusCode_name(code: statusCode));
24345
24346 /* Send error message. Message type is MSG and not ERR, since we are on a
24347 * SecureChannel! */
24348 return UA_SecureChannel_sendSymmetricMessage(channel, requestId,
24349 messageType: UA_MESSAGETYPE_MSG, payload: &response,
24350 payloadType: &UA_TYPES[UA_TYPES_SERVICEFAULT]);
24351}
24352
24353/* This is not an ERR message, the connection is not closed afterwards */
24354static UA_StatusCode
24355decodeHeaderSendServiceFault(UA_SecureChannel *channel, const UA_ByteString *msg,
24356 size_t offset, const UA_DataType *responseType,
24357 UA_UInt32 requestId, UA_StatusCode error) {
24358 UA_RequestHeader requestHeader;
24359 UA_StatusCode retval =
24360 UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &requestHeader,
24361 type: &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL);
24362 if(retval != UA_STATUSCODE_GOOD)
24363 return retval;
24364 retval = sendServiceFault(channel, requestId, requestHandle: requestHeader.requestHandle, statusCode: error);
24365 UA_RequestHeader_clear(p: &requestHeader);
24366 return retval;
24367}
24368
24369/* The counterOffset is the offset of the UA_ServiceCounterDataType for the
24370 * service in the UA_ SessionDiagnosticsDataType. */
24371#ifdef UA_ENABLE_DIAGNOSTICS
24372#define UA_SERVICECOUNTER_OFFSET(X) \
24373 *counterOffset = offsetof(UA_SessionDiagnosticsDataType, X)
24374#else
24375#define UA_SERVICECOUNTER_OFFSET(X)
24376#endif
24377
24378static void
24379getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType,
24380 const UA_DataType **responseType, UA_Service *service,
24381 UA_Boolean *requiresSession, size_t *counterOffset) {
24382 switch(requestTypeId) {
24383 case UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY:
24384 *service = (UA_Service)Service_GetEndpoints;
24385 *requestType = &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST];
24386 *responseType = &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE];
24387 *requiresSession = false;
24388 break;
24389 case UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY:
24390 *service = (UA_Service)Service_FindServers;
24391 *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST];
24392 *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE];
24393 *requiresSession = false;
24394 break;
24395#ifdef UA_ENABLE_DISCOVERY
24396# ifdef UA_ENABLE_DISCOVERY_MULTICAST
24397 case UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY:
24398 *service = (UA_Service)Service_FindServersOnNetwork;
24399 *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST];
24400 *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE];
24401 *requiresSession = false;
24402 break;
24403# endif
24404 case UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY:
24405 *service = (UA_Service)Service_RegisterServer;
24406 *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST];
24407 *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE];
24408 *requiresSession = false;
24409 break;
24410 case UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY:
24411 *service = (UA_Service)Service_RegisterServer2;
24412 *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST];
24413 *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE];
24414 *requiresSession = false;
24415 break;
24416#endif
24417 case UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24418 *service = (UA_Service)Service_CreateSession;
24419 *requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST];
24420 *responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE];
24421 *requiresSession = false;
24422 break;
24423 case UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24424 *service = (UA_Service)Service_ActivateSession;
24425 *requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST];
24426 *responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE];
24427 break;
24428 case UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY:
24429 *service = (UA_Service)Service_CloseSession;
24430 *requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST];
24431 *responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE];
24432 break;
24433 case UA_NS0ID_READREQUEST_ENCODING_DEFAULTBINARY:
24434 *service = NULL;
24435 *service = (UA_Service)Service_Read;
24436 *requestType = &UA_TYPES[UA_TYPES_READREQUEST];
24437 *responseType = &UA_TYPES[UA_TYPES_READRESPONSE];
24438 UA_SERVICECOUNTER_OFFSET(readCount);
24439 break;
24440 case UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY:
24441 *service = (UA_Service)Service_Write;
24442 *requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST];
24443 *responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE];
24444 UA_SERVICECOUNTER_OFFSET(writeCount);
24445 break;
24446 case UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY:
24447 *service = (UA_Service)Service_Browse;
24448 *requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST];
24449 *responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE];
24450 UA_SERVICECOUNTER_OFFSET(browseCount);
24451 break;
24452 case UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY:
24453 *service = (UA_Service)Service_BrowseNext;
24454 *requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST];
24455 *responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE];
24456 UA_SERVICECOUNTER_OFFSET(browseNextCount);
24457 break;
24458 case UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
24459 *service = (UA_Service)Service_RegisterNodes;
24460 *requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST];
24461 *responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE];
24462 UA_SERVICECOUNTER_OFFSET(registerNodesCount);
24463 break;
24464 case UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY:
24465 *service = (UA_Service)Service_UnregisterNodes;
24466 *requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST];
24467 *responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE];
24468 UA_SERVICECOUNTER_OFFSET(unregisterNodesCount);
24469 break;
24470 case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY:
24471 *service = (UA_Service)Service_TranslateBrowsePathsToNodeIds;
24472 *requestType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST];
24473 *responseType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE];
24474 UA_SERVICECOUNTER_OFFSET(translateBrowsePathsToNodeIdsCount);
24475 break;
24476
24477#ifdef UA_ENABLE_SUBSCRIPTIONS
24478 case UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
24479 *service = (UA_Service)Service_CreateSubscription;
24480 *requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST];
24481 *responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE];
24482 UA_SERVICECOUNTER_OFFSET(createSubscriptionCount);
24483 break;
24484 case UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY:
24485 *requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST];
24486 *responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE];
24487 UA_SERVICECOUNTER_OFFSET(publishCount);
24488 break;
24489 case UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY:
24490 *service = (UA_Service)Service_Republish;
24491 *requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST];
24492 *responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE];
24493 UA_SERVICECOUNTER_OFFSET(republishCount);
24494 break;
24495 case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY:
24496 *service = (UA_Service)Service_ModifySubscription;
24497 *requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST];
24498 *responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE];
24499 UA_SERVICECOUNTER_OFFSET(modifySubscriptionCount);
24500 break;
24501 case UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY:
24502 *service = (UA_Service)Service_SetPublishingMode;
24503 *requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST];
24504 *responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE];
24505 UA_SERVICECOUNTER_OFFSET(setPublishingModeCount);
24506 break;
24507 case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
24508 *service = (UA_Service)Service_DeleteSubscriptions;
24509 *requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST];
24510 *responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE];
24511 UA_SERVICECOUNTER_OFFSET(deleteSubscriptionsCount);
24512 break;
24513 case UA_NS0ID_TRANSFERSUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY:
24514 *service = (UA_Service)Service_TransferSubscriptions;
24515 *requestType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST];
24516 *responseType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE];
24517 UA_SERVICECOUNTER_OFFSET(transferSubscriptionsCount);
24518 break;
24519 case UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24520 *service = (UA_Service)Service_CreateMonitoredItems;
24521 *requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST];
24522 *responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE];
24523 UA_SERVICECOUNTER_OFFSET(createMonitoredItemsCount);
24524 break;
24525 case UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24526 *service = (UA_Service)Service_DeleteMonitoredItems;
24527 *requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST];
24528 *responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE];
24529 UA_SERVICECOUNTER_OFFSET(deleteMonitoredItemsCount);
24530 break;
24531 case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY:
24532 *service = (UA_Service)Service_ModifyMonitoredItems;
24533 *requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST];
24534 *responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE];
24535 UA_SERVICECOUNTER_OFFSET(modifyMonitoredItemsCount);
24536 break;
24537 case UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY:
24538 *service = (UA_Service)Service_SetMonitoringMode;
24539 *requestType = &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST];
24540 *responseType = &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE];
24541 UA_SERVICECOUNTER_OFFSET(setMonitoringModeCount);
24542 break;
24543 case UA_NS0ID_SETTRIGGERINGREQUEST_ENCODING_DEFAULTBINARY:
24544 *service = (UA_Service)Service_SetTriggering;
24545 *requestType = &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST];
24546 *responseType = &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE];
24547 UA_SERVICECOUNTER_OFFSET(setTriggeringCount);
24548 break;
24549#endif
24550#ifdef UA_ENABLE_HISTORIZING
24551 /* For History read */
24552 case UA_NS0ID_HISTORYREADREQUEST_ENCODING_DEFAULTBINARY:
24553 *service = (UA_Service)Service_HistoryRead;
24554 *requestType = &UA_TYPES[UA_TYPES_HISTORYREADREQUEST];
24555 *responseType = &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE];
24556 UA_SERVICECOUNTER_OFFSET(historyReadCount);
24557 break;
24558 /* For History update */
24559 case UA_NS0ID_HISTORYUPDATEREQUEST_ENCODING_DEFAULTBINARY:
24560 *service = (UA_Service)Service_HistoryUpdate;
24561 *requestType = &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST];
24562 *responseType = &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE];
24563 UA_SERVICECOUNTER_OFFSET(historyUpdateCount);
24564 break;
24565#endif
24566
24567#ifdef UA_ENABLE_METHODCALLS
24568 case UA_NS0ID_CALLREQUEST_ENCODING_DEFAULTBINARY:
24569 *service = (UA_Service)Service_Call;
24570 *requestType = &UA_TYPES[UA_TYPES_CALLREQUEST];
24571 *responseType = &UA_TYPES[UA_TYPES_CALLRESPONSE];
24572 UA_SERVICECOUNTER_OFFSET(callCount);
24573 break;
24574#endif
24575
24576#ifdef UA_ENABLE_NODEMANAGEMENT
24577 case UA_NS0ID_ADDNODESREQUEST_ENCODING_DEFAULTBINARY:
24578 *service = (UA_Service)Service_AddNodes;
24579 *requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST];
24580 *responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE];
24581 UA_SERVICECOUNTER_OFFSET(addNodesCount);
24582 break;
24583 case UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
24584 *service = (UA_Service)Service_AddReferences;
24585 *requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST];
24586 *responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE];
24587 UA_SERVICECOUNTER_OFFSET(addReferencesCount);
24588 break;
24589 case UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY:
24590 *service = (UA_Service)Service_DeleteNodes;
24591 *requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST];
24592 *responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE];
24593 UA_SERVICECOUNTER_OFFSET(deleteNodesCount);
24594 break;
24595 case UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY:
24596 *service = (UA_Service)Service_DeleteReferences;
24597 *requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST];
24598 *responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE];
24599 UA_SERVICECOUNTER_OFFSET(deleteReferencesCount);
24600 break;
24601#endif
24602
24603 default:
24604 break;
24605 }
24606}
24607
24608/*************************/
24609/* Process Message Types */
24610/*************************/
24611
24612/* HEL -> Open up the connection */
24613static UA_StatusCode
24614processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *msg) {
24615 if(channel->state != UA_SECURECHANNELSTATE_FRESH)
24616 return UA_STATUSCODE_BADINTERNALERROR;
24617 size_t offset = 0; /* Go to the beginning of the TcpHelloMessage */
24618 UA_TcpHelloMessage helloMessage;
24619 UA_StatusCode retval =
24620 UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &helloMessage,
24621 type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL);
24622 if(retval != UA_STATUSCODE_GOOD)
24623 return retval;
24624
24625 /* Currently not checked */
24626 UA_String_clear(p: &helloMessage.endpointUrl);
24627
24628 /* Parameterize the connection. The TcpHelloMessage casts to a
24629 * TcpAcknowledgeMessage. */
24630 retval = UA_SecureChannel_processHELACK(channel,
24631 remoteConfig: (UA_TcpAcknowledgeMessage*)&helloMessage);
24632 if(retval != UA_STATUSCODE_GOOD) {
24633 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
24634 msg: "Connection %i | Error during the HEL/ACK handshake",
24635 (int)(channel->connection->sockfd));
24636 return retval;
24637 }
24638
24639 /* Get the send buffer from the network layer */
24640 UA_Connection *connection = channel->connection;
24641 UA_ByteString ack_msg;
24642 UA_ByteString_init(p: &ack_msg);
24643 retval = connection->getSendBuffer(connection, channel->config.sendBufferSize, &ack_msg);
24644 if(retval != UA_STATUSCODE_GOOD)
24645 return retval;
24646
24647 /* Build acknowledge response */
24648 UA_TcpAcknowledgeMessage ackMessage;
24649 ackMessage.protocolVersion = 0;
24650 ackMessage.receiveBufferSize = channel->config.recvBufferSize;
24651 ackMessage.sendBufferSize = channel->config.sendBufferSize;
24652 ackMessage.maxMessageSize = channel->config.localMaxMessageSize;
24653 ackMessage.maxChunkCount = channel->config.localMaxChunkCount;
24654
24655 UA_TcpMessageHeader ackHeader;
24656 ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL;
24657 ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */
24658
24659 /* Encode and send the response */
24660 UA_Byte *bufPos = ack_msg.data;
24661 const UA_Byte *bufEnd = &ack_msg.data[ack_msg.length];
24662 retval |= UA_encodeBinaryInternal(src: &ackHeader,
24663 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
24664 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
24665 retval |= UA_encodeBinaryInternal(src: &ackMessage,
24666 type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE],
24667 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
24668 if(retval != UA_STATUSCODE_GOOD) {
24669 connection->releaseSendBuffer(connection, &ack_msg);
24670 return retval;
24671 }
24672
24673 ack_msg.length = ackHeader.messageSize;
24674 retval = connection->send(connection, &ack_msg);
24675 if(retval == UA_STATUSCODE_GOOD)
24676 channel->state = UA_SECURECHANNELSTATE_ACK_SENT;
24677 return retval;
24678}
24679
24680/* OPN -> Open up/renew the securechannel */
24681static UA_StatusCode
24682processOPN(UA_Server *server, UA_SecureChannel *channel,
24683 const UA_UInt32 requestId, const UA_ByteString *msg) {
24684 if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT &&
24685 channel->state != UA_SECURECHANNELSTATE_OPEN)
24686 return UA_STATUSCODE_BADINTERNALERROR;
24687 /* Decode the request */
24688 UA_NodeId requestType;
24689 UA_OpenSecureChannelRequest openSecureChannelRequest;
24690 size_t offset = 0;
24691 UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestType);
24692 if(retval != UA_STATUSCODE_GOOD) {
24693 UA_NodeId_clear(p: &requestType);
24694 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24695 "Could not decode the NodeId. Closing the connection");
24696 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24697 return retval;
24698 }
24699 retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &openSecureChannelRequest,
24700 type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL);
24701
24702 /* Error occurred */
24703 if(retval != UA_STATUSCODE_GOOD ||
24704 !UA_NodeId_equal(n1: &requestType, n2: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId)) {
24705 UA_NodeId_clear(p: &requestType);
24706 UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest);
24707 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24708 "Could not decode the OPN message. Closing the connection.");
24709 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24710 return retval;
24711 }
24712 UA_NodeId_clear(p: &requestType);
24713
24714 /* Call the service */
24715 UA_OpenSecureChannelResponse openScResponse;
24716 UA_OpenSecureChannelResponse_init(p: &openScResponse);
24717 Service_OpenSecureChannel(server, channel, request: &openSecureChannelRequest, response: &openScResponse);
24718 UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest);
24719 if(openScResponse.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
24720 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel, "Could not open a SecureChannel. "
24721 "Closing the connection.");
24722 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24723 return openScResponse.responseHeader.serviceResult;
24724 }
24725
24726 /* Send the response */
24727 retval = UA_SecureChannel_sendAsymmetricOPNMessage(channel, requestId, content: &openScResponse,
24728 contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]);
24729 UA_OpenSecureChannelResponse_clear(p: &openScResponse);
24730 if(retval != UA_STATUSCODE_GOOD) {
24731 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24732 "Could not send the OPN answer with error code %s",
24733 UA_StatusCode_name(retval));
24734 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_REJECT);
24735 }
24736
24737 return retval;
24738}
24739
24740/* The responseHeader must have the requestHandle already set */
24741UA_StatusCode
24742sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
24743 UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType) {
24744 if(!channel)
24745 return UA_STATUSCODE_BADINTERNALERROR;
24746
24747 /* If the overall service call failed, answer with a ServiceFault */
24748 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
24749 return sendServiceFault(channel, requestId, requestHandle: response->responseHeader.requestHandle,
24750 statusCode: response->responseHeader.serviceResult);
24751
24752 /* Prepare the ResponseHeader */
24753 response->responseHeader.timestamp = UA_DateTime_now();
24754
24755 if(session) {
24756#ifdef UA_ENABLE_TYPEDESCRIPTION
24757 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
24758 "Sending response for RequestId %u of type %s",
24759 (unsigned)requestId, responseType->typeName);
24760#else
24761 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
24762 "Sending reponse for RequestId %u of type %" PRIu32,
24763 (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
24764#endif
24765 } else {
24766#ifdef UA_ENABLE_TYPEDESCRIPTION
24767 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
24768 "Sending response for RequestId %u of type %s",
24769 (unsigned)requestId, responseType->typeName);
24770#else
24771 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
24772 "Sending reponse for RequestId %u of type %" PRIu32,
24773 (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric);
24774#endif
24775 }
24776
24777 /* Start the message context */
24778 UA_MessageContext mc;
24779 UA_StatusCode retval = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType: UA_MESSAGETYPE_MSG);
24780 if(retval != UA_STATUSCODE_GOOD)
24781 return retval;
24782
24783 /* Assert's required for clang-analyzer */
24784 UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]);
24785 UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]);
24786
24787 /* Encode the response type */
24788 retval = UA_MessageContext_encode(mc: &mc, content: &responseType->binaryEncodingId,
24789 contentType: &UA_TYPES[UA_TYPES_NODEID]);
24790 if(retval != UA_STATUSCODE_GOOD)
24791 return retval;
24792
24793 /* Encode the response */
24794 retval = UA_MessageContext_encode(mc: &mc, content: response, contentType: responseType);
24795 if(retval != UA_STATUSCODE_GOOD)
24796 return retval;
24797
24798 /* Finish / send out */
24799 return UA_MessageContext_finish(mc: &mc);
24800}
24801
24802/* A Session is "bound" to a SecureChannel if it was created by the
24803 * SecureChannel or if it was activated on it. A Session can only be bound to
24804 * one SecureChannel. A Session can only be closed from the SecureChannel to
24805 * which it is bound.
24806 *
24807 * Returns Good if the AuthenticationToken exists nowhere (for CTT). */
24808UA_StatusCode
24809getBoundSession(UA_Server *server, const UA_SecureChannel *channel,
24810 const UA_NodeId *token, UA_Session **session) {
24811 UA_DateTime now = UA_DateTime_nowMonotonic();
24812 UA_SessionHeader *sh;
24813 SLIST_FOREACH(sh, &channel->sessions, next) {
24814 if(!UA_NodeId_equal(n1: token, n2: &sh->authenticationToken))
24815 continue;
24816 UA_Session *current = (UA_Session*)sh;
24817 /* Has the session timed out? */
24818 if(current->validTill < now) {
24819 server->serverDiagnosticsSummary.rejectedSessionCount++;
24820 return UA_STATUSCODE_BADSESSIONCLOSED;
24821 }
24822 *session = current;
24823 return UA_STATUSCODE_GOOD;
24824 }
24825
24826 server->serverDiagnosticsSummary.rejectedSessionCount++;
24827
24828 /* Session exists on another SecureChannel. The CTT expect this error. */
24829 UA_Session *tmpSession = getSessionByToken(server, token);
24830 if(tmpSession) {
24831#ifdef UA_ENABLE_DIAGNOSTICS
24832 tmpSession->diagnostics.unauthorizedRequestCount++;
24833#endif
24834 return UA_STATUSCODE_BADSECURECHANNELIDINVALID;
24835 }
24836
24837 return UA_STATUSCODE_GOOD;
24838}
24839
24840static const UA_String securityPolicyNone =
24841 UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#None");
24842
24843/* Returns a status of the SecureChannel. The detailed service status (usually
24844 * part of the response) is set in the serviceResult argument. */
24845static UA_StatusCode
24846processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 requestId,
24847 UA_Service service, const UA_Request *request,
24848 const UA_DataType *requestType, UA_Response *response,
24849 const UA_DataType *responseType, UA_Boolean sessionRequired,
24850 size_t counterOffset) {
24851 UA_Session *session = NULL;
24852 UA_StatusCode channelRes = UA_STATUSCODE_GOOD;
24853 UA_StatusCode serviceRes = UA_STATUSCODE_GOOD;
24854 const UA_RequestHeader *requestHeader = &request->requestHeader;
24855
24856 /* If it is an unencrypted (#None) channel, only allow the discovery services */
24857 if(server->config.securityPolicyNoneDiscoveryOnly &&
24858 UA_String_equal(s1: &channel->securityPolicy->policyUri, s2: &securityPolicyNone ) &&
24859 requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] &&
24860 requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]
24861#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
24862 && requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]
24863#endif
24864 ) {
24865 serviceRes = UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
24866 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24867 UA_STATUSCODE_BADSECURITYPOLICYREJECTED);
24868 goto update_statistics;
24869 }
24870
24871 /* Session lifecycle services. */
24872 if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] ||
24873 requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] ||
24874 requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) {
24875 UA_LOCK(&server->serviceMutex);
24876 ((UA_ChannelService)service)(server, channel, request, response);
24877 UA_UNLOCK(&server->serviceMutex);
24878#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
24879 /* Store the authentication token so we can help fuzzing by setting
24880 * these values in the next request automatically */
24881 if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) {
24882 UA_CreateSessionResponse *res = &response->createSessionResponse;
24883 UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken);
24884 }
24885#endif
24886 serviceRes = response->responseHeader.serviceResult;
24887 channelRes = sendResponse(server, NULL, channel, requestId, response, responseType);
24888 goto update_statistics;
24889 }
24890
24891 /* Get the Session bound to the SecureChannel (not necessarily activated) */
24892 if(!UA_NodeId_isNull(p: &requestHeader->authenticationToken)) {
24893 UA_LOCK(&server->serviceMutex);
24894 UA_StatusCode retval =
24895 getBoundSession(server, channel,
24896 token: &requestHeader->authenticationToken, session: &session);
24897 UA_UNLOCK(&server->serviceMutex);
24898 if(retval != UA_STATUSCODE_GOOD) {
24899 serviceRes = response->responseHeader.serviceResult;
24900 channelRes = sendServiceFault(channel, requestId,
24901 requestHandle: requestHeader->requestHandle, statusCode: retval);
24902 goto update_statistics;
24903 }
24904 }
24905
24906 /* Set an anonymous, inactive session for services that need no session */
24907 UA_Session anonymousSession;
24908 if(!session) {
24909 if(sessionRequired) {
24910#ifdef UA_ENABLE_TYPEDESCRIPTION
24911 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24912 "%s refused without a valid session",
24913 requestType->typeName);
24914#else
24915 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
24916 "Service %" PRIu32 " refused without a valid session",
24917 requestType->binaryEncodingId.identifier.numeric);
24918#endif
24919 serviceRes = UA_STATUSCODE_BADSESSIONIDINVALID;
24920 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24921 UA_STATUSCODE_BADSESSIONIDINVALID);
24922 goto update_statistics;
24923 }
24924
24925 UA_Session_init(session: &anonymousSession);
24926 anonymousSession.sessionId = UA_NODEID_GUID(nsIndex: 0, guid: UA_GUID_NULL);
24927 anonymousSession.header.channel = channel;
24928 session = &anonymousSession;
24929 }
24930
24931 UA_assert(session != NULL);
24932
24933 /* Trying to use a non-activated session? */
24934 if(sessionRequired && !session->activated) {
24935#ifdef UA_ENABLE_TYPEDESCRIPTION
24936 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24937 "%s refused on a non-activated session",
24938 requestType->typeName);
24939#else
24940 UA_LOG_WARNING_SESSION(&server->config.logger, session,
24941 "Service %" PRIu32 " refused on a non-activated session",
24942 requestType->binaryEncodingId.identifier.numeric);
24943#endif
24944 if(session != &anonymousSession) {
24945 UA_LOCK(&server->serviceMutex);
24946 UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken,
24947 event: UA_DIAGNOSTICEVENT_ABORT);
24948 UA_UNLOCK(&server->serviceMutex);
24949 }
24950 serviceRes = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
24951 channelRes = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
24952 UA_STATUSCODE_BADSESSIONNOTACTIVATED);
24953 goto update_statistics;
24954 }
24955
24956 /* Update the session lifetime */
24957 UA_Session_updateLifetime(session);
24958
24959#ifdef UA_ENABLE_SUBSCRIPTIONS
24960 /* The publish request is not answered immediately */
24961 if(requestType == &UA_TYPES[UA_TYPES_PUBLISHREQUEST]) {
24962 UA_LOCK(&server->serviceMutex);
24963 serviceRes = Service_Publish(server, session, request: &request->publishRequest, requestId);
24964 /* No channelRes due to the async response */
24965 UA_UNLOCK(&server->serviceMutex);
24966 goto update_statistics;
24967 }
24968#endif
24969
24970#if UA_MULTITHREADING >= 100
24971 /* The call request might not be answered immediately */
24972 if(requestType == &UA_TYPES[UA_TYPES_CALLREQUEST]) {
24973 UA_Boolean finished = true;
24974 UA_LOCK(&server->serviceMutex);
24975 Service_CallAsync(server, session, requestId, &request->callRequest,
24976 &response->callResponse, &finished);
24977 UA_UNLOCK(&server->serviceMutex);
24978
24979 /* Async method calls remain. Don't send a response now. In case we have
24980 * an async call, count as a "good" request for the diagnostics
24981 * statistic. */
24982 if(UA_LIKELY(finished)) {
24983 serviceRes = response->responseHeader.serviceResult;
24984 channelRes = sendResponse(server, session, channel,
24985 requestId, response, responseType);
24986 }
24987 goto update_statistics;
24988 }
24989#endif
24990
24991 /* Execute the synchronous service call */
24992 UA_LOCK(&server->serviceMutex);
24993 service(server, session, request, response);
24994 UA_UNLOCK(&server->serviceMutex);
24995
24996 /* Send the response */
24997 serviceRes = response->responseHeader.serviceResult;
24998 channelRes = sendResponse(server, session, channel, requestId, response, responseType);
24999
25000 /* Update the diagnostics statistics */
25001 update_statistics:
25002#ifdef UA_ENABLE_DIAGNOSTICS
25003 if(session && session != &server->adminSession) {
25004 session->diagnostics.totalRequestCount.totalCount++;
25005 if(serviceRes != UA_STATUSCODE_GOOD)
25006 session->diagnostics.totalRequestCount.errorCount++;
25007 if(counterOffset != 0) {
25008 UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*)
25009 (((uintptr_t)&session->diagnostics) + counterOffset);
25010 serviceCounter->totalCount++;
25011 if(serviceRes != UA_STATUSCODE_GOOD)
25012 serviceCounter->errorCount++;
25013 }
25014 }
25015#else
25016 (void)serviceRes; /* Pacify compiler warnings */
25017#endif
25018
25019 return channelRes;
25020}
25021
25022static UA_StatusCode
25023processMSG(UA_Server *server, UA_SecureChannel *channel,
25024 UA_UInt32 requestId, const UA_ByteString *msg) {
25025 if(channel->state != UA_SECURECHANNELSTATE_OPEN)
25026 return UA_STATUSCODE_BADINTERNALERROR;
25027 /* Decode the nodeid */
25028 size_t offset = 0;
25029 UA_NodeId requestTypeId;
25030 UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestTypeId);
25031 if(retval != UA_STATUSCODE_GOOD)
25032 return retval;
25033 if(requestTypeId.namespaceIndex != 0 ||
25034 requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC)
25035 UA_NodeId_clear(p: &requestTypeId); /* leads to badserviceunsupported */
25036
25037 size_t requestPos = offset; /* Store the offset (for sendServiceFault) */
25038
25039 /* Get the service pointers */
25040 UA_Service service = NULL;
25041 UA_Boolean sessionRequired = true;
25042 const UA_DataType *requestType = NULL;
25043 const UA_DataType *responseType = NULL;
25044 size_t counterOffset = 0;
25045 getServicePointers(requestTypeId: requestTypeId.identifier.numeric, requestType: &requestType,
25046 responseType: &responseType, service: &service, requiresSession: &sessionRequired, counterOffset: &counterOffset);
25047 if(!requestType) {
25048 if(requestTypeId.identifier.numeric ==
25049 UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY) {
25050 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25051 "Client requested a subscription, "
25052 "but those are not enabled in the build");
25053 } else {
25054 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25055 "Unknown request with type identifier %" PRIi32,
25056 requestTypeId.identifier.numeric);
25057 }
25058 return decodeHeaderSendServiceFault(channel, msg, offset: requestPos,
25059 responseType: &UA_TYPES[UA_TYPES_SERVICEFAULT],
25060 requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED);
25061 }
25062 UA_assert(responseType);
25063
25064 /* Decode the request */
25065 UA_Request request;
25066 retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &request,
25067 type: requestType, customTypes: server->config.customDataTypes);
25068 if(retval != UA_STATUSCODE_GOOD) {
25069 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
25070 "Could not decode the request with StatusCode %s",
25071 UA_StatusCode_name(retval));
25072 return decodeHeaderSendServiceFault(channel, msg, offset: requestPos,
25073 responseType, requestId, error: retval);
25074 }
25075
25076 /* Check timestamp in the request header */
25077 UA_RequestHeader *requestHeader = &request.requestHeader;
25078 if(requestHeader->timestamp == 0) {
25079 if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_WARN) {
25080 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
25081 "The server sends no timestamp in the request header. "
25082 "See the 'verifyRequestTimestamp' setting.");
25083 if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) {
25084 retval = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle,
25085 UA_STATUSCODE_BADINVALIDTIMESTAMP);
25086 UA_clear(p: &request, type: requestType);
25087 return retval;
25088 }
25089 }
25090 }
25091
25092#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
25093 /* Set the authenticationToken from the create session request to help
25094 * fuzzing cover more lines */
25095 if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken) &&
25096 !UA_NodeId_isNull(&requestHeader->authenticationToken)) {
25097 UA_NodeId_clear(&requestHeader->authenticationToken);
25098 UA_NodeId_copy(&unsafe_fuzz_authenticationToken, &requestHeader->authenticationToken);
25099 }
25100#endif
25101
25102 /* Prepare the respone and process the request */
25103 UA_Response response;
25104 UA_init(p: &response, type: responseType);
25105 response.responseHeader.requestHandle = requestHeader->requestHandle;
25106 retval = processMSGDecoded(server, channel, requestId, service, request: &request, requestType,
25107 response: &response, responseType, sessionRequired, counterOffset);
25108
25109 /* Clean up */
25110 UA_clear(p: &request, type: requestType);
25111 UA_clear(p: &response, type: responseType);
25112 return retval;
25113}
25114
25115/* Takes decoded messages starting at the nodeid of the content type. */
25116static UA_StatusCode
25117processSecureChannelMessage(void *application, UA_SecureChannel *channel,
25118 UA_MessageType messagetype, UA_UInt32 requestId,
25119 UA_ByteString *message) {
25120 UA_Server *server = (UA_Server*)application;
25121
25122 UA_StatusCode retval = UA_STATUSCODE_GOOD;
25123 switch(messagetype) {
25124 case UA_MESSAGETYPE_HEL:
25125 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a HEL message");
25126 retval = processHEL(server, channel, msg: message);
25127 break;
25128 case UA_MESSAGETYPE_OPN:
25129 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process an OPN message");
25130 retval = processOPN(server, channel, requestId, msg: message);
25131 break;
25132 case UA_MESSAGETYPE_MSG:
25133 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a MSG");
25134 retval = processMSG(server, channel, requestId, msg: message);
25135 break;
25136 case UA_MESSAGETYPE_CLO:
25137 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Process a CLO");
25138 Service_CloseSecureChannel(server, channel); /* Regular close */
25139 break;
25140 default:
25141 UA_LOG_TRACE_CHANNEL(&server->config.logger, channel, "Invalid message type");
25142 retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
25143 break;
25144 }
25145 if(retval != UA_STATUSCODE_GOOD) {
25146 if(!channel->connection) {
25147 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25148 "Processing the message failed. Channel already closed "
25149 "with StatusCode %s. ", UA_StatusCode_name(retval));
25150 return retval;
25151 }
25152
25153 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
25154 "Processing the message failed with StatusCode %s. "
25155 "Closing the channel.", UA_StatusCode_name(retval));
25156 UA_TcpErrorMessage errMsg;
25157 UA_TcpErrorMessage_init(p: &errMsg);
25158 errMsg.error = retval;
25159 UA_Connection_sendError(connection: channel->connection, error: &errMsg);
25160 switch(retval) {
25161 case UA_STATUSCODE_BADSECURITYMODEREJECTED:
25162 case UA_STATUSCODE_BADSECURITYCHECKSFAILED:
25163 case UA_STATUSCODE_BADSECURECHANNELIDINVALID:
25164 case UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN:
25165 case UA_STATUSCODE_BADSECURITYPOLICYREJECTED:
25166 case UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED:
25167 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_SECURITYREJECT);
25168 break;
25169 default:
25170 UA_Server_closeSecureChannel(server, channel, event: UA_DIAGNOSTICEVENT_CLOSE);
25171 break;
25172 }
25173 }
25174
25175 return retval;
25176}
25177
25178void
25179UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
25180 UA_ByteString *message) {
25181 UA_LOG_TRACE(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
25182 msg: "Connection %i | Received a packet.", (int)(connection->sockfd));
25183
25184 UA_TcpErrorMessage error;
25185 UA_StatusCode retval = UA_STATUSCODE_GOOD;
25186 UA_SecureChannel *channel = connection->channel;
25187
25188 /* Add a SecureChannel to a new connection */
25189 if(!channel) {
25190 retval = UA_Server_createSecureChannel(server, connection);
25191 if(retval != UA_STATUSCODE_GOOD)
25192 goto error;
25193 channel = connection->channel;
25194 UA_assert(channel);
25195 }
25196
25197#ifdef UA_DEBUG_DUMP_PKGS
25198 UA_dump_hex_pkg(message->data, message->length);
25199#endif
25200#ifdef UA_DEBUG_DUMP_PKGS_FILE
25201 UA_debug_dumpCompleteChunk(server, channel->connection, message);
25202#endif
25203
25204 retval = UA_SecureChannel_processBuffer(channel, application: server, callback: processSecureChannelMessage, buffer: message);
25205 if(retval != UA_STATUSCODE_GOOD) {
25206 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_NETWORK,
25207 msg: "Connection %i | Processing the message failed with error %s",
25208 (int)(connection->sockfd), UA_StatusCode_name(code: retval));
25209 goto error;
25210 }
25211
25212 return;
25213
25214 error:
25215 /* Send an ERR message and close the connection */
25216 error.error = retval;
25217 error.reason = UA_STRING_NULL;
25218 UA_Connection_sendError(connection, error: &error);
25219 connection->close(connection);
25220}
25221
25222void
25223UA_Server_removeConnection(UA_Server *server, UA_Connection *connection) {
25224 UA_Connection_detachSecureChannel(connection);
25225 connection->free(connection);
25226}
25227
25228/**** amalgamated original file "/src/server/ua_server_utils.c" ****/
25229
25230/* This Source Code Form is subject to the terms of the Mozilla Public
25231 * License, v. 2.0. If a copy of the MPL was not distributed with this
25232 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25233 *
25234 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25235 * Copyright 2016 (c) Lorenz Haas
25236 * Copyright 2017 (c) frax2222
25237 * Copyright 2017 (c) Florian Palm
25238 * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
25239 * Copyright 2017 (c) Julian Grothoff
25240 */
25241
25242
25243const UA_DataType *
25244UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) {
25245 return UA_findDataTypeWithCustom(typeId, customTypes: server->config.customDataTypes);
25246}
25247
25248/********************************/
25249/* Information Model Operations */
25250/********************************/
25251
25252const UA_Node *
25253getNodeType(UA_Server *server, const UA_NodeHead *head) {
25254 /* The reference to the parent is different for variable and variabletype */
25255 UA_Byte parentRefIndex;
25256 UA_Boolean inverse;
25257 UA_NodeClass typeNodeClass;
25258 switch(head->nodeClass) {
25259 case UA_NODECLASS_OBJECT:
25260 parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
25261 inverse = false;
25262 typeNodeClass = UA_NODECLASS_OBJECTTYPE;
25263 break;
25264 case UA_NODECLASS_VARIABLE:
25265 parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
25266 inverse = false;
25267 typeNodeClass = UA_NODECLASS_VARIABLETYPE;
25268 break;
25269 case UA_NODECLASS_OBJECTTYPE:
25270 case UA_NODECLASS_VARIABLETYPE:
25271 case UA_NODECLASS_REFERENCETYPE:
25272 case UA_NODECLASS_DATATYPE:
25273 parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE;
25274 inverse = true;
25275 typeNodeClass = head->nodeClass;
25276 break;
25277 default:
25278 return NULL;
25279 }
25280
25281 /* Return the first matching candidate */
25282 for(size_t i = 0; i < head->referencesSize; ++i) {
25283 UA_NodeReferenceKind *rk = &head->references[i];
25284 if(rk->isInverse != inverse)
25285 continue;
25286 if(rk->referenceTypeIndex != parentRefIndex)
25287 continue;
25288
25289 const UA_ReferenceTarget *t = NULL;
25290 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
25291 const UA_Node *type = UA_NODESTORE_GETFROMREF(server, target: t->targetId);
25292 if(!type)
25293 continue;
25294 if(type->head.nodeClass == typeNodeClass)
25295 return type; /* Don't release the node that is returned */
25296 UA_NODESTORE_RELEASE(server, type);
25297 }
25298 }
25299
25300 return NULL;
25301}
25302
25303UA_Boolean
25304UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) {
25305 for(size_t i = 0; i < head->referencesSize; ++i) {
25306 if(head->references[i].isInverse == false &&
25307 head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE)
25308 return true;
25309 if(head->references[i].isInverse == true &&
25310 head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION)
25311 return true;
25312 }
25313 return false;
25314}
25315
25316UA_StatusCode
25317getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode,
25318 UA_NodeId **typeHierarchy, size_t *typeHierarchySize) {
25319 UA_ReferenceTypeSet reftypes_subtype =
25320 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
25321 UA_ExpandedNodeId *subTypes = NULL;
25322 size_t subTypesSize = 0;
25323 UA_StatusCode retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode,
25324 browseDirection: UA_BROWSEDIRECTION_INVERSE,
25325 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
25326 false, resultsSize: &subTypesSize, results: &subTypes);
25327 if(retval != UA_STATUSCODE_GOOD)
25328 return retval;
25329
25330 UA_assert(subTypesSize < 1000);
25331
25332 UA_ReferenceTypeSet reftypes_interface =
25333 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
25334 UA_ExpandedNodeId *interfaces = NULL;
25335 size_t interfacesSize = 0;
25336 retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode, browseDirection: UA_BROWSEDIRECTION_FORWARD,
25337 refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
25338 false, resultsSize: &interfacesSize, results: &interfaces);
25339 if(retval != UA_STATUSCODE_GOOD) {
25340 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_NODEID]);
25341 return retval;
25342 }
25343
25344 UA_assert(interfacesSize < 1000);
25345
25346 UA_NodeId *hierarchy = (UA_NodeId*)
25347 UA_malloc(size: sizeof(UA_NodeId) * (1 + subTypesSize + interfacesSize));
25348 if(!hierarchy) {
25349 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25350 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25351 return UA_STATUSCODE_BADOUTOFMEMORY;
25352 }
25353
25354 retval = UA_NodeId_copy(src: typeNode, dst: hierarchy);
25355 if(retval != UA_STATUSCODE_GOOD) {
25356 UA_free(ptr: hierarchy);
25357 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25358 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25359 return UA_STATUSCODE_BADOUTOFMEMORY;
25360 }
25361
25362 for(size_t i = 0; i < subTypesSize; i++) {
25363 hierarchy[i+1] = subTypes[i].nodeId;
25364 UA_NodeId_init(p: &subTypes[i].nodeId);
25365 }
25366 for(size_t i = 0; i < interfacesSize; i++) {
25367 hierarchy[i+1+subTypesSize] = interfaces[i].nodeId;
25368 UA_NodeId_init(p: &interfaces[i].nodeId);
25369 }
25370
25371 *typeHierarchy = hierarchy;
25372 *typeHierarchySize = subTypesSize + interfacesSize + 1;
25373
25374 UA_assert(*typeHierarchySize < 1000);
25375
25376 UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25377 UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25378 return UA_STATUSCODE_GOOD;
25379}
25380
25381UA_StatusCode
25382getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode,
25383 const UA_NodeId *objectTypeNode,
25384 UA_NodeId **interfaceChildNodes,
25385 size_t *interfaceChildNodesSize) {
25386 if(interfaceChildNodesSize == NULL || interfaceChildNodes == NULL)
25387 return UA_STATUSCODE_BADINTERNALERROR;
25388 *interfaceChildNodesSize = 0;
25389 *interfaceChildNodes = NULL;
25390
25391 UA_ExpandedNodeId *hasInterfaceCandidates = NULL;
25392 size_t hasInterfaceCandidatesSize = 0;
25393 UA_ReferenceTypeSet reftypes_subtype =
25394 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
25395
25396 UA_StatusCode retval =
25397 browseRecursive(server, startNodesSize: 1, startNodes: objectTypeNode, browseDirection: UA_BROWSEDIRECTION_INVERSE,
25398 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
25399 true, resultsSize: &hasInterfaceCandidatesSize,
25400 results: &hasInterfaceCandidates);
25401
25402 if(retval != UA_STATUSCODE_GOOD)
25403 return retval;
25404
25405 /* The interface could also have been added manually before calling UA_Server_addNode_finish
25406 * This can be handled by adding the object node as a start node for the HasInterface lookup */
25407 UA_ExpandedNodeId *resizedHasInterfaceCandidates = (UA_ExpandedNodeId*)
25408 UA_realloc(ptr: hasInterfaceCandidates,
25409 size: (hasInterfaceCandidatesSize + 1) * sizeof(UA_ExpandedNodeId));
25410
25411 if(!resizedHasInterfaceCandidates) {
25412 if(hasInterfaceCandidates)
25413 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25414 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25415 return UA_STATUSCODE_BADOUTOFMEMORY;
25416 }
25417
25418 hasInterfaceCandidates = resizedHasInterfaceCandidates;
25419 hasInterfaceCandidatesSize += 1;
25420 UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
25421
25422 UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]);
25423 UA_NodeId_copy(src: objectNode, dst: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1].nodeId);
25424
25425 size_t outputIndex = 0;
25426
25427 for(size_t i = 0; i < hasInterfaceCandidatesSize; ++i) {
25428 UA_ReferenceTypeSet reftypes_interface =
25429 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
25430 UA_ExpandedNodeId *interfaceChildren = NULL;
25431 size_t interfacesChildrenSize = 0;
25432 retval = browseRecursive(server, startNodesSize: 1, startNodes: &hasInterfaceCandidates[i].nodeId,
25433 browseDirection: UA_BROWSEDIRECTION_FORWARD,
25434 refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
25435 false, resultsSize: &interfacesChildrenSize, results: &interfaceChildren);
25436 if(retval != UA_STATUSCODE_GOOD) {
25437 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25438 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25439 if(*interfaceChildNodesSize) {
25440 UA_Array_delete(p: *interfaceChildNodes, size: *interfaceChildNodesSize,
25441 type: &UA_TYPES[UA_TYPES_NODEID]);
25442 *interfaceChildNodesSize = 0;
25443 }
25444 return retval;
25445 }
25446
25447 UA_assert(interfacesChildrenSize < 1000);
25448
25449 if(interfacesChildrenSize == 0) {
25450 continue;
25451 }
25452
25453 if(!*interfaceChildNodes) {
25454 *interfaceChildNodes = (UA_NodeId*)
25455 UA_calloc(nmemb: interfacesChildrenSize, size: sizeof(UA_NodeId));
25456 *interfaceChildNodesSize = interfacesChildrenSize;
25457
25458 if(!*interfaceChildNodes) {
25459 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize,
25460 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25461 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25462 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25463 return UA_STATUSCODE_BADOUTOFMEMORY;
25464 }
25465 } else {
25466 UA_NodeId *resizedInterfaceChildNodes = (UA_NodeId*)
25467 UA_realloc(ptr: *interfaceChildNodes,
25468 size: ((*interfaceChildNodesSize + interfacesChildrenSize) * sizeof(UA_NodeId)));
25469
25470 if(!resizedInterfaceChildNodes) {
25471 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize,
25472 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25473 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize,
25474 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25475 return UA_STATUSCODE_BADOUTOFMEMORY;
25476 }
25477
25478 const size_t oldSize = *interfaceChildNodesSize;
25479 *interfaceChildNodesSize += interfacesChildrenSize;
25480 *interfaceChildNodes = resizedInterfaceChildNodes;
25481
25482 for(size_t j = oldSize; j < *interfaceChildNodesSize; ++j)
25483 UA_NodeId_init(p: &(*interfaceChildNodes)[j]);
25484 }
25485
25486 for(size_t j = 0; j < interfacesChildrenSize; j++) {
25487 (*interfaceChildNodes)[outputIndex++] = interfaceChildren[j].nodeId;
25488 }
25489
25490 UA_assert(*interfaceChildNodesSize < 1000);
25491 UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25492 }
25493
25494 UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
25495
25496 return UA_STATUSCODE_GOOD;
25497}
25498
25499/* For mulithreading: make a copy of the node, edit and replace.
25500 * For singlethreading: edit the original */
25501UA_StatusCode
25502UA_Server_editNode(UA_Server *server, UA_Session *session,
25503 const UA_NodeId *nodeId, UA_EditNodeCallback callback,
25504 void *data) {
25505#ifndef UA_ENABLE_IMMUTABLE_NODES
25506 /* Get the node and process it in-situ */
25507 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
25508 if(!node)
25509 return UA_STATUSCODE_BADNODEIDUNKNOWN;
25510 UA_StatusCode retval = callback(server, session, (UA_Node*)(uintptr_t)node, data);
25511 UA_NODESTORE_RELEASE(server, node);
25512 return retval;
25513#else
25514 UA_StatusCode retval;
25515 do {
25516 /* Get an editable copy of the node */
25517 UA_Node *node;
25518 retval = UA_NODESTORE_GETCOPY(server, nodeId, &node);
25519 if(retval != UA_STATUSCODE_GOOD)
25520 return retval;
25521
25522 /* Run the operation on the copy */
25523 retval = callback(server, session, node, data);
25524 if(retval != UA_STATUSCODE_GOOD) {
25525 UA_NODESTORE_DELETE(server, node);
25526 return retval;
25527 }
25528
25529 /* Replace the node */
25530 retval = UA_NODESTORE_REPLACE(server, node);
25531 } while(retval != UA_STATUSCODE_GOOD);
25532 return retval;
25533#endif
25534}
25535
25536UA_StatusCode
25537UA_Server_processServiceOperations(UA_Server *server, UA_Session *session,
25538 UA_ServiceOperation operationCallback,
25539 const void *context, const size_t *requestOperations,
25540 const UA_DataType *requestOperationsType,
25541 size_t *responseOperations,
25542 const UA_DataType *responseOperationsType) {
25543 size_t ops = *requestOperations;
25544 if(ops == 0)
25545 return UA_STATUSCODE_BADNOTHINGTODO;
25546
25547 /* No padding after size_t */
25548 void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
25549 *respPos = UA_Array_new(size: ops, type: responseOperationsType);
25550 if(!(*respPos))
25551 return UA_STATUSCODE_BADOUTOFMEMORY;
25552
25553 *responseOperations = ops;
25554 uintptr_t respOp = (uintptr_t)*respPos;
25555 /* No padding after size_t */
25556 uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
25557 for(size_t i = 0; i < ops; i++) {
25558 operationCallback(server, session, context, (void*)reqOp, (void*)respOp);
25559 reqOp += requestOperationsType->memSize;
25560 respOp += responseOperationsType->memSize;
25561 }
25562 return UA_STATUSCODE_GOOD;
25563}
25564
25565/* A few global NodeId definitions */
25566const UA_NodeId subtypeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
25567const UA_NodeId hierarchicalReferences = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HIERARCHICALREFERENCES}};
25568
25569/*********************************/
25570/* Default attribute definitions */
25571/*********************************/
25572
25573const UA_ObjectAttributes UA_ObjectAttributes_default = {
25574 0, /* specifiedAttributes */
25575 {{.length: 0, NULL}, {0, NULL}}, /* displayName */
25576 {{0, NULL}, {0, NULL}}, /* description */
25577 0, 0, /* writeMask (userWriteMask) */
25578 0 /* eventNotifier */
25579};
25580
25581const UA_VariableAttributes UA_VariableAttributes_default = {
25582 0, /* specifiedAttributes */
25583 {{0, NULL}, {0, NULL}}, /* displayName */
25584 {{0, NULL}, {0, NULL}}, /* description */
25585 0, 0, /* writeMask (userWriteMask) */
25586 {NULL, UA_VARIANT_DATA,
25587 0, NULL, 0, NULL}, /* value */
25588 {0, UA_NODEIDTYPE_NUMERIC,
25589 {UA_NS0ID_BASEDATATYPE}}, /* dataType */
25590 UA_VALUERANK_ANY, /* valueRank */
25591 0, NULL, /* arrayDimensions */
25592 UA_ACCESSLEVELMASK_READ, 0, /* accessLevel (userAccessLevel) */
25593 0.0, /* minimumSamplingInterval */
25594 false /* historizing */
25595};
25596
25597const UA_MethodAttributes UA_MethodAttributes_default = {
25598 0, /* specifiedAttributes */
25599 {{0, NULL}, {0, NULL}}, /* displayName */
25600 {{0, NULL}, {0, NULL}}, /* description */
25601 0, 0, /* writeMask (userWriteMask) */
25602 true, true /* executable (userExecutable) */
25603};
25604
25605const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = {
25606 0, /* specifiedAttributes */
25607 {{0, NULL}, {0, NULL}}, /* displayName */
25608 {{0, NULL}, {0, NULL}}, /* description */
25609 0, 0, /* writeMask (userWriteMask) */
25610 false /* isAbstract */
25611};
25612
25613const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = {
25614 0, /* specifiedAttributes */
25615 {{0, NULL}, {0, NULL}}, /* displayName */
25616 {{0, NULL}, {0, NULL}}, /* description */
25617 0, 0, /* writeMask (userWriteMask) */
25618 {NULL, UA_VARIANT_DATA,
25619 0, NULL, 0, NULL}, /* value */
25620 {0, UA_NODEIDTYPE_NUMERIC,
25621 {UA_NS0ID_BASEDATATYPE}}, /* dataType */
25622 UA_VALUERANK_ANY, /* valueRank */
25623 0, NULL, /* arrayDimensions */
25624 false /* isAbstract */
25625};
25626
25627const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = {
25628 0, /* specifiedAttributes */
25629 {{0, NULL}, {0, NULL}}, /* displayName */
25630 {{0, NULL}, {0, NULL}}, /* description */
25631 0, 0, /* writeMask (userWriteMask) */
25632 false, /* isAbstract */
25633 false, /* symmetric */
25634 {{0, NULL}, {0, NULL}} /* inverseName */
25635};
25636
25637const UA_DataTypeAttributes UA_DataTypeAttributes_default = {
25638 0, /* specifiedAttributes */
25639 {{0, NULL}, {0, NULL}}, /* displayName */
25640 {{0, NULL}, {0, NULL}}, /* description */
25641 0, 0, /* writeMask (userWriteMask) */
25642 false /* isAbstract */
25643};
25644
25645const UA_ViewAttributes UA_ViewAttributes_default = {
25646 0, /* specifiedAttributes */
25647 {{0, NULL}, {0, NULL}}, /* displayName */
25648 {{0, NULL}, {0, NULL}}, /* description */
25649 0, 0, /* writeMask (userWriteMask) */
25650 false, /* containsNoLoops */
25651 0 /* eventNotifier */
25652};
25653
25654
25655/**** amalgamated original file "/src/server/ua_server_discovery.c" ****/
25656
25657/* This Source Code Form is subject to the terms of the Mozilla Public
25658 * License, v. 2.0. If a copy of the MPL was not distributed with this
25659 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25660 *
25661 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25662 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
25663 * Copyright 2017 (c) HMS Industrial Networks AB (Author: Jonas Green)
25664 */
25665
25666
25667
25668#ifdef UA_ENABLE_DISCOVERY
25669
25670UA_StatusCode
25671register_server_with_discovery_server(UA_Server *server,
25672 void *pClient,
25673 const UA_Boolean isUnregister,
25674 const char* semaphoreFilePath) {
25675 UA_Client *client = (UA_Client *) pClient;
25676
25677 /* Prepare the request. Do not cleanup the request after the service call,
25678 * as the members are stack-allocated or point into the server config. */
25679 UA_RegisterServer2Request request;
25680 UA_RegisterServer2Request_init(&request);
25681 request.requestHeader.timestamp = UA_DateTime_now();
25682 request.requestHeader.timeoutHint = 10000;
25683
25684 request.server.isOnline = !isUnregister;
25685 request.server.serverUri = server->config.applicationDescription.applicationUri;
25686 request.server.productUri = server->config.applicationDescription.productUri;
25687 request.server.serverType = server->config.applicationDescription.applicationType;
25688 request.server.gatewayServerUri = server->config.applicationDescription.gatewayServerUri;
25689
25690 if(semaphoreFilePath) {
25691#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
25692 request.server.semaphoreFilePath =
25693 UA_STRING((char*)(uintptr_t)semaphoreFilePath); /* dirty cast */
25694#else
25695 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT,
25696 "Ignoring semaphore file path. open62541 not compiled "
25697 "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
25698#endif
25699 }
25700
25701 request.server.serverNames = &server->config.applicationDescription.applicationName;
25702 request.server.serverNamesSize = 1;
25703
25704 /* Mirror the discovery urls from the server config and the network layers */
25705 size_t config_discurls = server->config.applicationDescription.discoveryUrlsSize;
25706 size_t nl_discurls = server->config.networkLayersSize;
25707 size_t total_discurls = config_discurls + nl_discurls;
25708 request.server.discoveryUrls = (UA_String*)
25709 UA_Array_new(total_discurls, &UA_TYPES[UA_TYPES_STRING]);
25710 if(!request.server.discoveryUrls)
25711 return UA_STATUSCODE_BADOUTOFMEMORY;
25712
25713 for(size_t i = 0; i < config_discurls; ++i)
25714 request.server.discoveryUrls[i] = server->config.applicationDescription.discoveryUrls[i];
25715 /* TODO: Add nl only if discoveryUrl not already present */
25716 for(size_t i = 0; i < nl_discurls; ++i) {
25717 UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
25718 request.server.discoveryUrls[config_discurls + i] = nl->discoveryUrl;
25719 }
25720 request.server.discoveryUrlsSize = total_discurls;
25721
25722#ifdef UA_ENABLE_DISCOVERY_MULTICAST
25723 request.discoveryConfigurationSize = 1;
25724 request.discoveryConfiguration = UA_ExtensionObject_new();
25725 // Set to NODELETE so that we can just use a pointer to the mdns config
25726 UA_ExtensionObject_setValueNoDelete(request.discoveryConfiguration,
25727 &server->config.mdnsConfig,
25728 &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]);
25729#endif
25730
25731 // First try with RegisterServer2, if that isn't implemented, use RegisterServer
25732 UA_RegisterServer2Response response;
25733 __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST],
25734 &response, &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]);
25735
25736 UA_StatusCode serviceResult = response.responseHeader.serviceResult;
25737 UA_RegisterServer2Response_clear(&response);
25738 UA_Array_delete(request.discoveryConfiguration,
25739 request.discoveryConfigurationSize,
25740 &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
25741 if(total_discurls > 0)
25742 UA_free(request.server.discoveryUrls);
25743
25744 if(serviceResult == UA_STATUSCODE_BADNOTIMPLEMENTED ||
25745 serviceResult == UA_STATUSCODE_BADSERVICEUNSUPPORTED) {
25746 /* Try RegisterServer */
25747 UA_RegisterServerRequest request_fallback;
25748 UA_RegisterServerRequest_init(&request_fallback);
25749 /* Copy from RegisterServer2 request */
25750 request_fallback.requestHeader = request.requestHeader;
25751 request_fallback.server = request.server;
25752
25753 UA_RegisterServerResponse response_fallback;
25754
25755 __UA_Client_Service(client, &request_fallback,
25756 &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST],
25757 &response_fallback,
25758 &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]);
25759
25760 serviceResult = response_fallback.responseHeader.serviceResult;
25761 UA_RegisterServerResponse_clear(&response_fallback);
25762 }
25763
25764 if(serviceResult != UA_STATUSCODE_GOOD) {
25765 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_CLIENT,
25766 "RegisterServer/RegisterServer2 failed with statuscode %s",
25767 UA_StatusCode_name(serviceResult));
25768 }
25769
25770 return serviceResult;
25771}
25772
25773UA_StatusCode
25774UA_Server_register_discovery(UA_Server *server, UA_Client *client,
25775 const char* semaphoreFilePath) {
25776 UA_LOCK(&server->serviceMutex);
25777 UA_StatusCode retval = register_server_with_discovery_server(server, client,
25778 false, semaphoreFilePath);
25779 UA_UNLOCK(&server->serviceMutex);
25780 return retval;
25781}
25782
25783UA_StatusCode
25784UA_Server_unregister_discovery(UA_Server *server, UA_Client *client) {
25785 UA_LOCK(&server->serviceMutex);
25786 UA_StatusCode retval = register_server_with_discovery_server(server, client,
25787 true, NULL);
25788 UA_UNLOCK(&server->serviceMutex);
25789 return retval;
25790}
25791
25792#endif /* UA_ENABLE_DISCOVERY */
25793
25794/**** amalgamated original file "/src/server/ua_server_async.c" ****/
25795
25796/* This Source Code Form is subject to the terms of the Mozilla Public
25797 * License, v. 2.0. If a copy of the MPL was not distributed with this
25798 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
25799 *
25800 * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick)
25801 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
25802 */
25803
25804
25805#if UA_MULTITHREADING >= 100
25806
25807static void
25808UA_AsyncOperation_delete(UA_AsyncOperation *ar) {
25809 UA_CallMethodRequest_clear(&ar->request);
25810 UA_CallMethodResult_clear(&ar->response);
25811 UA_free(ar);
25812}
25813
25814static UA_StatusCode
25815UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server,
25816 UA_AsyncResponse *ar) {
25817 /* Get the session */
25818 UA_StatusCode res = UA_STATUSCODE_GOOD;
25819 UA_LOCK(&server->serviceMutex);
25820 UA_Session* session = UA_Server_getSessionById(server, &ar->sessionId);
25821 UA_UNLOCK(&server->serviceMutex);
25822 UA_SecureChannel* channel = NULL;
25823 UA_ResponseHeader *responseHeader = NULL;
25824 if(!session) {
25825 res = UA_STATUSCODE_BADSESSIONIDINVALID;
25826 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25827 "UA_Server_InsertMethodResponse: Session is gone");
25828 goto clean_up;
25829 }
25830
25831 /* Check the channel */
25832 channel = session->header.channel;
25833 if(!channel) {
25834 res = UA_STATUSCODE_BADSECURECHANNELCLOSED;
25835 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25836 "UA_Server_InsertMethodResponse: Channel is gone");
25837 goto clean_up;
25838 }
25839
25840 /* Okay, here we go, send the UA_CallResponse */
25841 responseHeader = (UA_ResponseHeader*)
25842 &ar->response.callResponse.responseHeader;
25843 responseHeader->requestHandle = ar->requestHandle;
25844 res = sendResponse(server, session, channel, ar->requestId,
25845 (UA_Response*)&ar->response, &UA_TYPES[UA_TYPES_CALLRESPONSE]);
25846 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25847 "UA_Server_SendResponse: Response for Req# %" PRIu32 " sent", ar->requestId);
25848
25849 clean_up:
25850 /* Remove from the AsyncManager */
25851 UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar);
25852 return res;
25853}
25854
25855/* Integrate operation result in the AsyncResponse and send out the response if
25856 * it is ready. */
25857static void
25858integrateOperationResult(UA_AsyncManager *am, UA_Server *server,
25859 UA_AsyncOperation *ao) {
25860 /* Grab the open request, so we can continue to construct the response */
25861 UA_AsyncResponse *ar = ao->parent;
25862
25863 /* Reduce the number of open results */
25864 ar->opCountdown -= 1;
25865
25866 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25867 "Return result in the server thread with %" PRIu32 " remaining",
25868 ar->opCountdown);
25869
25870 /* Move the UA_CallMethodResult to UA_CallResponse */
25871 ar->response.callResponse.results[ao->index] = ao->response;
25872 UA_CallMethodResult_init(&ao->response);
25873
25874 /* Are we done with all operations? */
25875 if(ar->opCountdown == 0)
25876 UA_AsyncManager_sendAsyncResponse(am, server, ar);
25877}
25878
25879/* Process all operations in the result queue -> move content over to the
25880 * AsyncResponse. This is only done by the server thread. */
25881static void
25882processAsyncResults(UA_Server *server, void *data) {
25883 UA_AsyncManager *am = &server->asyncManager;
25884 while(true) {
25885 UA_LOCK(&am->queueLock);
25886 UA_AsyncOperation *ao = TAILQ_FIRST(&am->resultQueue);
25887 if(ao)
25888 TAILQ_REMOVE(&am->resultQueue, ao, pointers);
25889 UA_UNLOCK(&am->queueLock);
25890 if(!ao)
25891 break;
25892 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
25893 "UA_Server_CallMethodResponse: Got Response: OKAY");
25894 integrateOperationResult(am, server, ao);
25895 UA_AsyncOperation_delete(ao);
25896 am->opsCount--;
25897 }
25898}
25899
25900/* Check if any operations have timed out */
25901static void
25902checkTimeouts(UA_Server *server, void *_) {
25903 /* Timeouts are not configured */
25904 if(server->config.asyncOperationTimeout <= 0.0)
25905 return;
25906
25907 UA_AsyncManager *am = &server->asyncManager;
25908 const UA_DateTime tNow = UA_DateTime_now();
25909
25910 UA_LOCK(&am->queueLock);
25911
25912 /* Loop over the queue of dispatched ops */
25913 UA_AsyncOperation *op = NULL, *op_tmp = NULL;
25914 TAILQ_FOREACH_SAFE(op, &am->dispatchedQueue, pointers, op_tmp) {
25915 /* The timeout has not passed. Also for all elements following in the queue. */
25916 if(tNow <= op->parent->timeout)
25917 break;
25918
25919 /* Mark as timed out and put it into the result queue */
25920 op->response.statusCode = UA_STATUSCODE_BADTIMEOUT;
25921 TAILQ_REMOVE(&am->dispatchedQueue, op, pointers);
25922 TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers);
25923 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25924 "Operation was removed due to a timeout");
25925 }
25926
25927 /* Loop over the queue of new ops */
25928 TAILQ_FOREACH_SAFE(op, &am->newQueue, pointers, op_tmp) {
25929 /* The timeout has not passed. Also for all elements following in the queue. */
25930 if(tNow <= op->parent->timeout)
25931 break;
25932
25933 /* Mark as timed out and put it into the result queue */
25934 op->response.statusCode = UA_STATUSCODE_BADTIMEOUT;
25935 TAILQ_REMOVE(&am->newQueue, op, pointers);
25936 TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers);
25937 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
25938 "Operation was removed due to a timeout");
25939 }
25940
25941 UA_UNLOCK(&am->queueLock);
25942
25943 /* Integrate async results and send out complete responses */
25944 processAsyncResults(server, NULL);
25945}
25946
25947void
25948UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server) {
25949 memset(am, 0, sizeof(UA_AsyncManager));
25950 TAILQ_INIT(&am->asyncResponses);
25951 TAILQ_INIT(&am->newQueue);
25952 TAILQ_INIT(&am->dispatchedQueue);
25953 TAILQ_INIT(&am->resultQueue);
25954 UA_LOCK_INIT(&am->queueLock);
25955
25956 /* Add a regular callback for cleanup and sending finished responses at a
25957 * 100s interval. */
25958 UA_Server_addRepeatedCallback(server, (UA_ServerCallback)checkTimeouts,
25959 NULL, 100.0, &am->checkTimeoutCallbackId);
25960}
25961
25962void
25963UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server) {
25964 removeCallback(server, am->checkTimeoutCallbackId);
25965
25966 UA_AsyncOperation *ar, *ar_tmp;
25967
25968 /* Clean up queues */
25969 UA_LOCK(&am->queueLock);
25970 TAILQ_FOREACH_SAFE(ar, &am->newQueue, pointers, ar_tmp) {
25971 TAILQ_REMOVE(&am->newQueue, ar, pointers);
25972 UA_AsyncOperation_delete(ar);
25973 }
25974 TAILQ_FOREACH_SAFE(ar, &am->dispatchedQueue, pointers, ar_tmp) {
25975 TAILQ_REMOVE(&am->dispatchedQueue, ar, pointers);
25976 UA_AsyncOperation_delete(ar);
25977 }
25978 TAILQ_FOREACH_SAFE(ar, &am->resultQueue, pointers, ar_tmp) {
25979 TAILQ_REMOVE(&am->resultQueue, ar, pointers);
25980 UA_AsyncOperation_delete(ar);
25981 }
25982 UA_UNLOCK(&am->queueLock);
25983
25984 /* Remove responses */
25985 UA_AsyncResponse *current, *temp;
25986 TAILQ_FOREACH_SAFE(current, &am->asyncResponses, pointers, temp) {
25987 UA_AsyncManager_removeAsyncResponse(am, current);
25988 }
25989
25990 /* Delete all locks */
25991 UA_LOCK_DESTROY(&am->queueLock);
25992}
25993
25994UA_StatusCode
25995UA_AsyncManager_createAsyncResponse(UA_AsyncManager *am, UA_Server *server,
25996 const UA_NodeId *sessionId,
25997 const UA_UInt32 requestId, const UA_UInt32 requestHandle,
25998 const UA_AsyncOperationType operationType,
25999 UA_AsyncResponse **outAr) {
26000 UA_AsyncResponse *newentry = (UA_AsyncResponse*)UA_calloc(1, sizeof(UA_AsyncResponse));
26001 if(!newentry)
26002 return UA_STATUSCODE_BADOUTOFMEMORY;
26003
26004 UA_StatusCode res = UA_NodeId_copy(sessionId, &newentry->sessionId);
26005 if(res != UA_STATUSCODE_GOOD) {
26006 UA_free(newentry);
26007 return res;
26008 }
26009
26010 am->asyncResponsesCount += 1;
26011 newentry->requestId = requestId;
26012 newentry->requestHandle = requestHandle;
26013 newentry->timeout = UA_DateTime_now();
26014 if(server->config.asyncOperationTimeout > 0.0)
26015 newentry->timeout += (UA_DateTime)
26016 (server->config.asyncOperationTimeout * (UA_DateTime)UA_DATETIME_MSEC);
26017 TAILQ_INSERT_TAIL(&am->asyncResponses, newentry, pointers);
26018
26019 *outAr = newentry;
26020 return UA_STATUSCODE_GOOD;
26021}
26022
26023/* Remove entry and free all allocated data */
26024void
26025UA_AsyncManager_removeAsyncResponse(UA_AsyncManager *am, UA_AsyncResponse *ar) {
26026 TAILQ_REMOVE(&am->asyncResponses, ar, pointers);
26027 am->asyncResponsesCount -= 1;
26028 UA_CallResponse_clear(&ar->response.callResponse);
26029 UA_NodeId_clear(&ar->sessionId);
26030 UA_free(ar);
26031}
26032
26033/* Enqueue next MethodRequest */
26034UA_StatusCode
26035UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server,
26036 UA_AsyncResponse *ar, size_t opIndex,
26037 const UA_CallMethodRequest *opRequest) {
26038 if(server->config.maxAsyncOperationQueueSize != 0 &&
26039 am->opsCount >= server->config.maxAsyncOperationQueueSize) {
26040 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26041 "UA_Server_SetNextAsyncMethod: Queue exceeds limit (%d).",
26042 (int unsigned)server->config.maxAsyncOperationQueueSize);
26043 return UA_STATUSCODE_BADUNEXPECTEDERROR;
26044 }
26045
26046 UA_AsyncOperation *ao = (UA_AsyncOperation*)UA_calloc(1, sizeof(UA_AsyncOperation));
26047 if(!ao) {
26048 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
26049 "UA_Server_SetNextAsyncMethod: Mem alloc failed.");
26050 return UA_STATUSCODE_BADOUTOFMEMORY;
26051 }
26052
26053 UA_StatusCode result = UA_CallMethodRequest_copy(opRequest, &ao->request);
26054 if(result != UA_STATUSCODE_GOOD) {
26055 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
26056 "UA_Server_SetAsyncMethodResult: UA_CallMethodRequest_copy failed.");
26057 UA_free(ao);
26058 return result;
26059 }
26060
26061 UA_CallMethodResult_init(&ao->response);
26062 ao->index = opIndex;
26063 ao->parent = ar;
26064
26065 UA_LOCK(&am->queueLock);
26066 TAILQ_INSERT_TAIL(&am->newQueue, ao, pointers);
26067 am->opsCount++;
26068 ar->opCountdown++;
26069 UA_UNLOCK(&am->queueLock);
26070
26071 if(server->config.asyncOperationNotifyCallback)
26072 server->config.asyncOperationNotifyCallback(server);
26073
26074 return UA_STATUSCODE_GOOD;
26075}
26076
26077/* Get and remove next Method Call Request */
26078UA_Boolean
26079UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type,
26080 const UA_AsyncOperationRequest **request,
26081 void **context, UA_DateTime *timeout) {
26082 UA_AsyncManager *am = &server->asyncManager;
26083
26084 UA_Boolean bRV = false;
26085 *type = UA_ASYNCOPERATIONTYPE_INVALID;
26086 UA_LOCK(&am->queueLock);
26087 UA_AsyncOperation *ao = TAILQ_FIRST(&am->newQueue);
26088 if(ao) {
26089 TAILQ_REMOVE(&am->newQueue, ao, pointers);
26090 TAILQ_INSERT_TAIL(&am->dispatchedQueue, ao, pointers);
26091 *type = UA_ASYNCOPERATIONTYPE_CALL;
26092 *request = (UA_AsyncOperationRequest*)&ao->request;
26093 *context = (void*)ao;
26094 if(timeout)
26095 *timeout = ao->parent->timeout;
26096 bRV = true;
26097 }
26098 UA_UNLOCK(&am->queueLock);
26099
26100 return bRV;
26101}
26102
26103/* Worker submits Method Call Response */
26104void
26105UA_Server_setAsyncOperationResult(UA_Server *server,
26106 const UA_AsyncOperationResponse *response,
26107 void *context) {
26108 UA_AsyncManager *am = &server->asyncManager;
26109
26110 UA_AsyncOperation *ao = (UA_AsyncOperation*)context;
26111 if(!ao) {
26112 /* Something went wrong. Not a good AsyncOp. */
26113 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26114 "UA_Server_SetAsyncMethodResult: Invalid context");
26115 return;
26116 }
26117
26118 UA_LOCK(&am->queueLock);
26119
26120 /* See if the operation is still in the dispatched queue. Otherwise it has
26121 * been removed due to a timeout.
26122 *
26123 * TODO: Add a tree-structure for the dispatch queue. The linear lookup does
26124 * not scale. */
26125 UA_Boolean found = false;
26126 UA_AsyncOperation *op = NULL;
26127 TAILQ_FOREACH(op, &am->dispatchedQueue, pointers) {
26128 if(op == ao) {
26129 found = true;
26130 break;
26131 }
26132 }
26133
26134 if(!found) {
26135 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26136 "UA_Server_SetAsyncMethodResult: The operation has timed out");
26137 UA_UNLOCK(&am->queueLock);
26138 return;
26139 }
26140
26141 /* Copy the result into the internal AsyncOperation */
26142 UA_StatusCode result =
26143 UA_CallMethodResult_copy(&response->callMethodResult, &ao->response);
26144 if(result != UA_STATUSCODE_GOOD) {
26145 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
26146 "UA_Server_SetAsyncMethodResult: UA_CallMethodResult_copy failed.");
26147 ao->response.statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
26148 }
26149
26150 /* Move to the result queue */
26151 TAILQ_REMOVE(&am->dispatchedQueue, ao, pointers);
26152 TAILQ_INSERT_TAIL(&am->resultQueue, ao, pointers);
26153
26154 UA_UNLOCK(&am->queueLock);
26155
26156 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
26157 "Set the result from the worker thread");
26158}
26159
26160/******************/
26161/* Server Methods */
26162/******************/
26163
26164static UA_StatusCode
26165setMethodNodeAsync(UA_Server *server, UA_Session *session,
26166 UA_Node *node, UA_Boolean *isAsync) {
26167 if(node->head.nodeClass != UA_NODECLASS_METHOD)
26168 return UA_STATUSCODE_BADNODECLASSINVALID;
26169 node->methodNode.async = *isAsync;
26170 return UA_STATUSCODE_GOOD;
26171}
26172
26173UA_StatusCode
26174UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id,
26175 UA_Boolean isAsync) {
26176 return UA_Server_editNode(server, &server->adminSession, &id,
26177 (UA_EditNodeCallback)setMethodNodeAsync, &isAsync);
26178}
26179
26180UA_StatusCode
26181UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session,
26182 UA_UInt32 requestId, UA_UInt32 requestHandle,
26183 UA_AsyncServiceOperation operationCallback,
26184 const size_t *requestOperations,
26185 const UA_DataType *requestOperationsType,
26186 size_t *responseOperations,
26187 const UA_DataType *responseOperationsType,
26188 UA_AsyncResponse **ar) {
26189 size_t ops = *requestOperations;
26190 if(ops == 0)
26191 return UA_STATUSCODE_BADNOTHINGTODO;
26192
26193 /* Allocate the response array. No padding after size_t */
26194 void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t));
26195 *respPos = UA_Array_new(ops, responseOperationsType);
26196 if(!*respPos)
26197 return UA_STATUSCODE_BADOUTOFMEMORY;
26198 *responseOperations = ops;
26199
26200 /* Finish / dispatch the operations. This may allocate a new AsyncResponse internally */
26201 uintptr_t respOp = (uintptr_t)*respPos;
26202 uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t));
26203 for(size_t i = 0; i < ops; i++) {
26204 operationCallback(server, session, requestId, requestHandle,
26205 i, (void*)reqOp, (void*)respOp, ar);
26206 reqOp += requestOperationsType->memSize;
26207 respOp += responseOperationsType->memSize;
26208 }
26209
26210 return UA_STATUSCODE_GOOD;
26211}
26212
26213#endif
26214
26215/**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.c" ****/
26216
26217/* This Source Code Form is subject to the terms of the Mozilla Public
26218 * License, v. 2.0. If a copy of the MPL was not distributed with this
26219 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
26220 *
26221 * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff)
26222 * Copyright (c) 2019 Fraunhofer IOSB (Author: Andreas Ebner)
26223 */
26224
26225
26226
26227#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
26228
26229const UA_Byte NM_VERSION_MASK = 15;
26230const UA_Byte NM_PUBLISHER_ID_ENABLED_MASK = 16;
26231const UA_Byte NM_GROUP_HEADER_ENABLED_MASK = 32;
26232const UA_Byte NM_PAYLOAD_HEADER_ENABLED_MASK = 64;
26233const UA_Byte NM_EXTENDEDFLAGS1_ENABLED_MASK = 128;
26234const UA_Byte NM_PUBLISHER_ID_MASK = 7;
26235const UA_Byte NM_DATASET_CLASSID_ENABLED_MASK = 8;
26236const UA_Byte NM_SECURITY_ENABLED_MASK = 16;
26237const UA_Byte NM_TIMESTAMP_ENABLED_MASK = 32;
26238const UA_Byte NM_PICOSECONDS_ENABLED_MASK = 64;
26239const UA_Byte NM_EXTENDEDFLAGS2_ENABLED_MASK = 128;
26240const UA_Byte NM_NETWORK_MSG_TYPE_MASK = 28;
26241const UA_Byte NM_CHUNK_MESSAGE_MASK = 1;
26242const UA_Byte NM_PROMOTEDFIELDS_ENABLED_MASK = 2;
26243const UA_Byte GROUP_HEADER_WRITER_GROUPID_ENABLED = 1;
26244const UA_Byte GROUP_HEADER_GROUP_VERSION_ENABLED = 2;
26245const UA_Byte GROUP_HEADER_NM_NUMBER_ENABLED = 4;
26246const UA_Byte GROUP_HEADER_SEQUENCE_NUMBER_ENABLED = 8;
26247const UA_Byte SECURITY_HEADER_NM_SIGNED = 1;
26248const UA_Byte SECURITY_HEADER_NM_ENCRYPTED = 2;
26249const UA_Byte SECURITY_HEADER_SEC_FOOTER_ENABLED = 4;
26250const UA_Byte SECURITY_HEADER_FORCE_KEY_RESET = 8;
26251const UA_Byte DS_MESSAGEHEADER_DS_MSG_VALID = 1;
26252const UA_Byte DS_MESSAGEHEADER_FIELD_ENCODING_MASK = 6;
26253const UA_Byte DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK = 8;
26254const UA_Byte DS_MESSAGEHEADER_STATUS_ENABLED_MASK = 16;
26255const UA_Byte DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK = 32;
26256const UA_Byte DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK = 64;
26257const UA_Byte DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK = 128;
26258const UA_Byte DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK = 15;
26259const UA_Byte DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK = 16;
26260const UA_Byte DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK = 32;
26261const UA_Byte NM_SHIFT_LEN = 2;
26262const UA_Byte DS_MH_SHIFT_LEN = 1;
26263
26264static UA_Boolean UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src);
26265static UA_Boolean UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src);
26266static UA_Boolean UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src);
26267
26268UA_StatusCode
26269UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer){
26270 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26271 for(size_t i = 0; i < buffer->offsetsSize; ++i) {
26272 UA_NetworkMessageOffset *nmo = &buffer->offsets[i];
26273 const UA_Byte *bufEnd = &buffer->buffer.data[buffer->buffer.length];
26274 UA_Byte *bufPos = &buffer->buffer.data[nmo->offset];
26275 switch(nmo->contentType) {
26276 case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
26277 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
26278 rv = UA_UInt16_encodeBinary((UA_UInt16 *)nmo->offsetData.value.value->value.data, &bufPos, bufEnd);
26279 if(*((UA_UInt16 *)nmo->offsetData.value.value->value.data) < UA_UINT16_MAX){
26280 (*((UA_UInt16 *)nmo->offsetData.value.value->value.data))++;
26281 } else {
26282 (*((UA_UInt16 *)nmo->offsetData.value.value->value.data)) = 0;
26283 }
26284 break;
26285 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
26286 rv = UA_DataValue_encodeBinary(nmo->offsetData.value.value,
26287 &bufPos, bufEnd);
26288 break;
26289 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
26290 rv = UA_Variant_encodeBinary(&nmo->offsetData.value.value->value,
26291 &bufPos, bufEnd);
26292 break;
26293 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
26294 rv = UA_encodeBinaryInternal(nmo->offsetData.value.value->value.data,
26295 nmo->offsetData.value.value->value.type,
26296 &bufPos, &bufEnd, NULL, NULL);
26297 break;
26298 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
26299 break;
26300 default:
26301 return UA_STATUSCODE_BADNOTSUPPORTED;
26302 }
26303 }
26304 return rv;
26305}
26306
26307UA_StatusCode
26308UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer,
26309 const UA_ByteString *src, size_t *bufferPosition){
26310 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26311 size_t payloadCounter = 0;
26312 size_t offset = 0;
26313 UA_DataSetMessage* dsm = buffer->nm->payload.dataSetPayload.dataSetMessages; //Considering one DSM in RT TODO: Clarify multiple DSM
26314 UA_DataSetMessageHeader header;
26315 size_t smallestRawOffset = UA_UINT32_MAX;
26316
26317 for (size_t i = 0; i < buffer->offsetsSize; ++i) {
26318 offset = buffer->offsets[i].offset + *bufferPosition;
26319 switch (buffer->offsets[i].contentType) {
26320 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING:
26321 rv = UA_DataSetMessageHeader_decodeBinary(src, &offset, &header);
26322 if(rv != UA_STATUSCODE_GOOD)
26323 return rv;
26324 break;
26325 case UA_PUBSUB_OFFSETTYPE_PUBLISHERID:
26326 switch (buffer->nm->publisherIdType) {
26327 case UA_PUBLISHERDATATYPE_BYTE:
26328 rv = UA_Byte_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdByte));
26329 break;
26330 case UA_PUBLISHERDATATYPE_UINT16:
26331 rv = UA_UInt16_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt16));
26332 break;
26333 case UA_PUBLISHERDATATYPE_UINT32:
26334 rv = UA_UInt32_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt32));
26335 break;
26336 case UA_PUBLISHERDATATYPE_UINT64:
26337 rv = UA_UInt64_decodeBinary(src, &offset, &(buffer->nm->publisherId.publisherIdUInt64));
26338 break;
26339 default:
26340 return UA_STATUSCODE_BADNOTSUPPORTED;
26341 }
26342 break;
26343 case UA_PUBSUB_OFFSETTYPE_WRITERGROUPID:
26344 rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.writerGroupId);
26345 UA_CHECK_STATUS(rv, return rv);
26346 break;
26347 case UA_PUBSUB_OFFSETTYPE_DATASETWRITERID:
26348 rv = UA_UInt16_decodeBinary(src, &offset,
26349 &buffer->nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]); /* TODO */
26350 UA_CHECK_STATUS(rv, return rv);
26351 break;
26352 case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER:
26353 rv = UA_UInt16_decodeBinary(src, &offset, &buffer->nm->groupHeader.sequenceNumber);
26354 UA_CHECK_STATUS(rv, return rv);
26355 break;
26356 case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER:
26357 rv = UA_UInt16_decodeBinary(src, &offset, &(dsm->header.dataSetMessageSequenceNr));
26358 UA_CHECK_STATUS(rv, return rv);
26359 break;
26360 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE:
26361 rv = UA_DataValue_decodeBinary(src, &offset,
26362 &(dsm->data.keyFrameData.dataSetFields[payloadCounter]));
26363 UA_CHECK_STATUS(rv, return rv);
26364 payloadCounter++;
26365 break;
26366 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT:
26367 rv = UA_Variant_decodeBinary(src, &offset,
26368 &dsm->data.keyFrameData.dataSetFields[payloadCounter].value);
26369 UA_CHECK_STATUS(rv, return rv);
26370 dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue = true;
26371 payloadCounter++;
26372 break;
26373 case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW:
26374 /* We need only the start address of the raw fields */
26375 if (smallestRawOffset > offset){
26376 smallestRawOffset = offset;
26377 dsm->data.keyFrameData.rawFields.data = &src->data[offset];
26378 dsm->data.keyFrameData.rawFields.length = buffer->rawMessageLength;
26379 }
26380 payloadCounter++;
26381 break;
26382 default:
26383 return UA_STATUSCODE_BADNOTSUPPORTED;
26384 }
26385 }
26386 //check if the frame is of type "raw" payload
26387 if(smallestRawOffset != UA_UINT32_MAX){
26388 *bufferPosition = smallestRawOffset + buffer->rawMessageLength;
26389 } else {
26390 *bufferPosition = offset;
26391 }
26392
26393 return rv;
26394}
26395
26396static
26397UA_StatusCode
26398UA_NetworkMessageHeader_encodeBinary(const UA_NetworkMessage *src, UA_Byte **bufPos,
26399 const UA_Byte *bufEnd) {
26400
26401 /* UADPVersion + UADP Flags */
26402 UA_Byte v = src->version;
26403 if(src->publisherIdEnabled)
26404 v |= NM_PUBLISHER_ID_ENABLED_MASK;
26405
26406 if(src->groupHeaderEnabled)
26407 v |= NM_GROUP_HEADER_ENABLED_MASK;
26408
26409 if(src->payloadHeaderEnabled)
26410 v |= NM_PAYLOAD_HEADER_ENABLED_MASK;
26411
26412 if(UA_NetworkMessage_ExtendedFlags1Enabled(src))
26413 v |= NM_EXTENDEDFLAGS1_ENABLED_MASK;
26414
26415 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26416 UA_CHECK_STATUS(rv, return rv);
26417 // ExtendedFlags1
26418 if(UA_NetworkMessage_ExtendedFlags1Enabled(src)) {
26419 v = (UA_Byte)src->publisherIdType;
26420
26421 if(src->dataSetClassIdEnabled)
26422 v |= NM_DATASET_CLASSID_ENABLED_MASK;
26423
26424 if(src->securityEnabled)
26425 v |= NM_SECURITY_ENABLED_MASK;
26426
26427 if(src->timestampEnabled)
26428 v |= NM_TIMESTAMP_ENABLED_MASK;
26429
26430 if(src->picosecondsEnabled)
26431 v |= NM_PICOSECONDS_ENABLED_MASK;
26432
26433 if(UA_NetworkMessage_ExtendedFlags2Enabled(src))
26434 v |= NM_EXTENDEDFLAGS2_ENABLED_MASK;
26435
26436 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26437 UA_CHECK_STATUS(rv, return rv);
26438
26439 // ExtendedFlags2
26440 if(UA_NetworkMessage_ExtendedFlags2Enabled(src)) {
26441 v = (UA_Byte)src->networkMessageType;
26442 // shift left 2 bit
26443 v = (UA_Byte) (v << NM_SHIFT_LEN);
26444
26445 if(src->chunkMessage)
26446 v |= NM_CHUNK_MESSAGE_MASK;
26447
26448 if(src->promotedFieldsEnabled)
26449 v |= NM_PROMOTEDFIELDS_ENABLED_MASK;
26450
26451 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26452 UA_CHECK_STATUS(rv, return rv);
26453 }
26454 }
26455
26456 // PublisherId
26457 if(src->publisherIdEnabled) {
26458 switch (src->publisherIdType) {
26459 case UA_PUBLISHERDATATYPE_BYTE:
26460 rv = UA_Byte_encodeBinary(&(src->publisherId.publisherIdByte), bufPos, bufEnd);
26461 break;
26462
26463 case UA_PUBLISHERDATATYPE_UINT16:
26464 rv = UA_UInt16_encodeBinary(&(src->publisherId.publisherIdUInt16), bufPos, bufEnd);
26465 break;
26466
26467 case UA_PUBLISHERDATATYPE_UINT32:
26468 rv = UA_UInt32_encodeBinary(&(src->publisherId.publisherIdUInt32), bufPos, bufEnd);
26469 break;
26470
26471 case UA_PUBLISHERDATATYPE_UINT64:
26472 rv = UA_UInt64_encodeBinary(&(src->publisherId.publisherIdUInt64), bufPos, bufEnd);
26473 break;
26474
26475 case UA_PUBLISHERDATATYPE_STRING:
26476 rv = UA_String_encodeBinary(&(src->publisherId.publisherIdString), bufPos, bufEnd);
26477 break;
26478
26479 default:
26480 rv = UA_STATUSCODE_BADINTERNALERROR;
26481 break;
26482 }
26483 UA_CHECK_STATUS(rv, return rv);
26484 }
26485
26486 // DataSetClassId
26487 if(src->dataSetClassIdEnabled) {
26488 rv = UA_Guid_encodeBinary(&(src->dataSetClassId), bufPos, bufEnd);
26489 UA_CHECK_STATUS(rv, return rv);
26490 }
26491 return UA_STATUSCODE_GOOD;
26492}
26493
26494static
26495UA_StatusCode
26496UA_GroupHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26497 const UA_Byte *bufEnd) {
26498
26499 UA_Byte v = 0;
26500
26501 if(src->groupHeader.writerGroupIdEnabled)
26502 v |= GROUP_HEADER_WRITER_GROUPID_ENABLED;
26503
26504 if(src->groupHeader.groupVersionEnabled)
26505 v |= GROUP_HEADER_GROUP_VERSION_ENABLED;
26506
26507 if(src->groupHeader.networkMessageNumberEnabled)
26508 v |= GROUP_HEADER_NM_NUMBER_ENABLED;
26509
26510 if(src->groupHeader.sequenceNumberEnabled)
26511 v |= GROUP_HEADER_SEQUENCE_NUMBER_ENABLED;
26512
26513 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26514 UA_CHECK_STATUS(rv, return rv);
26515
26516 if(src->groupHeader.writerGroupIdEnabled) {
26517 rv = UA_UInt16_encodeBinary(&(src->groupHeader.writerGroupId), bufPos, bufEnd);
26518 UA_CHECK_STATUS(rv, return rv);
26519 }
26520
26521 if(src->groupHeader.groupVersionEnabled) {
26522 rv = UA_UInt32_encodeBinary(&(src->groupHeader.groupVersion), bufPos, bufEnd);
26523 UA_CHECK_STATUS(rv, return rv);
26524 }
26525
26526 if(src->groupHeader.networkMessageNumberEnabled) {
26527 rv = UA_UInt16_encodeBinary(&(src->groupHeader.networkMessageNumber), bufPos, bufEnd);
26528 UA_CHECK_STATUS(rv, return rv);
26529 }
26530
26531 if(src->groupHeader.sequenceNumberEnabled) {
26532 rv = UA_UInt16_encodeBinary(&(src->groupHeader.sequenceNumber), bufPos, bufEnd);
26533 UA_CHECK_STATUS(rv, return rv);
26534 }
26535 return UA_STATUSCODE_GOOD;
26536}
26537
26538static
26539UA_StatusCode
26540UA_PayloadHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26541 const UA_Byte *bufEnd) {
26542
26543 if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26544 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26545
26546 UA_StatusCode rv = UA_Byte_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.count), bufPos, bufEnd);
26547 UA_CHECK_STATUS(rv, return rv);
26548
26549 if(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds == NULL)
26550 return UA_STATUSCODE_BADENCODINGERROR;
26551
26552 for(UA_Byte i = 0; i < src->payloadHeader.dataSetPayloadHeader.count; i++) {
26553 rv = UA_UInt16_encodeBinary(&(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]),
26554 bufPos, bufEnd);
26555 UA_CHECK_STATUS(rv, return rv);
26556 }
26557 return UA_STATUSCODE_GOOD;
26558}
26559
26560static
26561UA_StatusCode
26562UA_ExtendedNetworkMessageHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26563 const UA_Byte *bufEnd) {
26564
26565 UA_StatusCode rv = UA_STATUSCODE_GOOD;
26566 // Timestamp
26567 if(src->timestampEnabled)
26568 rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd);
26569
26570 UA_CHECK_STATUS(rv, return rv);
26571 // Picoseconds
26572 if(src->picosecondsEnabled)
26573 rv = UA_UInt16_encodeBinary(&(src->picoseconds), bufPos, bufEnd);
26574
26575 UA_CHECK_STATUS(rv, return rv);
26576 // PromotedFields
26577 if(src->promotedFieldsEnabled) {
26578 /* Size (calculate & encode) */
26579 UA_UInt16 pfSize = 0;
26580 for(UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
26581 pfSize = (UA_UInt16) (pfSize + UA_Variant_calcSizeBinary(&src->promotedFields[i]));
26582 rv |= UA_UInt16_encodeBinary(&pfSize, bufPos, bufEnd);
26583 UA_CHECK_STATUS(rv, return rv);
26584
26585 for (UA_UInt16 i = 0; i < src->promotedFieldsSize; i++)
26586 rv |= UA_Variant_encodeBinary(&(src->promotedFields[i]), bufPos, bufEnd);
26587 UA_CHECK_STATUS(rv, return rv);
26588 }
26589 return UA_STATUSCODE_GOOD;
26590}
26591
26592static
26593UA_StatusCode
26594UA_SecurityHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26595 const UA_Byte *bufEnd) {
26596 // SecurityFlags
26597 UA_Byte v = 0;
26598 if(src->securityHeader.networkMessageSigned)
26599 v |= SECURITY_HEADER_NM_SIGNED;
26600
26601 if(src->securityHeader.networkMessageEncrypted)
26602 v |= SECURITY_HEADER_NM_ENCRYPTED;
26603
26604 if(src->securityHeader.securityFooterEnabled)
26605 v |= SECURITY_HEADER_SEC_FOOTER_ENABLED;
26606
26607 if(src->securityHeader.forceKeyReset)
26608 v |= SECURITY_HEADER_FORCE_KEY_RESET;
26609
26610 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
26611 UA_CHECK_STATUS(rv, return rv);
26612 // SecurityTokenId
26613 rv = UA_UInt32_encodeBinary(&src->securityHeader.securityTokenId, bufPos, bufEnd);
26614 UA_CHECK_STATUS(rv, return rv);
26615 // NonceLength
26616 UA_Byte nonceLength = (UA_Byte)src->securityHeader.messageNonce.length;
26617 rv = UA_Byte_encodeBinary(&nonceLength, bufPos, bufEnd);
26618 UA_CHECK_STATUS(rv, return rv);
26619 // MessageNonce
26620 for (size_t i = 0; i < src->securityHeader.messageNonce.length; i++) {
26621 rv = UA_Byte_encodeBinary(&src->securityHeader.messageNonce.data[i],
26622 bufPos, bufEnd);
26623 UA_CHECK_STATUS(rv, return rv);
26624 }
26625
26626 // SecurityFooterSize
26627 if(src->securityHeader.securityFooterEnabled) {
26628 rv = UA_UInt16_encodeBinary(&src->securityHeader.securityFooterSize,
26629 bufPos, bufEnd);
26630 UA_CHECK_STATUS(rv, return rv);
26631 }
26632
26633 return UA_STATUSCODE_GOOD;
26634}
26635
26636UA_StatusCode
26637UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src, UA_Byte **bufPos,
26638 const UA_Byte *bufEnd) {
26639
26640 UA_StatusCode rv = UA_NetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
26641 UA_CHECK_STATUS(rv, return rv);
26642 // Group Header
26643 if(src->groupHeaderEnabled) {
26644 rv = UA_GroupHeader_encodeBinary(src, bufPos, bufEnd);
26645 UA_CHECK_STATUS(rv, return rv);
26646 }
26647
26648 // Payload Header
26649 if(src->payloadHeaderEnabled) {
26650 rv = UA_PayloadHeader_encodeBinary(src, bufPos, bufEnd);
26651 UA_CHECK_STATUS(rv, return rv);
26652 }
26653
26654 // Extended Network Message Header
26655 rv = UA_ExtendedNetworkMessageHeader_encodeBinary(src, bufPos, bufEnd);
26656 UA_CHECK_STATUS(rv, return rv);
26657 // SecurityHeader
26658 if(src->securityEnabled) {
26659 rv = UA_SecurityHeader_encodeBinary(src, bufPos, bufEnd);
26660 UA_CHECK_STATUS(rv, return rv);
26661 }
26662 return UA_STATUSCODE_GOOD;
26663}
26664
26665
26666UA_StatusCode
26667UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src, UA_Byte **bufPos,
26668 const UA_Byte *bufEnd) {
26669
26670 UA_StatusCode rv;
26671
26672 // Payload
26673 if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26674 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26675
26676 UA_Byte count = 1;
26677
26678 if(src->payloadHeaderEnabled) {
26679 count = src->payloadHeader.dataSetPayloadHeader.count;
26680 if(count > 1) {
26681 for (UA_Byte i = 0; i < count; i++) {
26682 // initially calculate the size, if not specified
26683 UA_UInt16 sz = 0;
26684 if((src->payload.dataSetPayload.sizes != NULL) &&
26685 (src->payload.dataSetPayload.sizes[i] != 0)) {
26686 sz = src->payload.dataSetPayload.sizes[i];
26687 } else {
26688 sz = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&src->payload.dataSetPayload.dataSetMessages[i],
26689 NULL, 0);
26690 }
26691
26692 rv = UA_UInt16_encodeBinary(&sz, bufPos, bufEnd);
26693 UA_CHECK_STATUS(rv, return rv);
26694 }
26695 }
26696 }
26697
26698 for(UA_Byte i = 0; i < count; i++) {
26699 rv = UA_DataSetMessage_encodeBinary(&(src->payload.dataSetPayload.dataSetMessages[i]), bufPos, bufEnd);
26700 UA_CHECK_STATUS(rv, return rv);
26701 }
26702
26703 return UA_STATUSCODE_GOOD;
26704}
26705
26706UA_StatusCode
26707UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src, UA_Byte **bufPos,
26708 const UA_Byte *bufEnd) {
26709
26710 if(src->securityEnabled) {
26711 // SecurityFooter
26712 if(src->securityHeader.securityFooterEnabled) {
26713 for(size_t i = 0; i < src->securityHeader.securityFooterSize; i++) {
26714 UA_StatusCode rv = UA_Byte_encodeBinary(&(src->securityFooter.data[i]), bufPos, bufEnd);
26715 UA_CHECK_STATUS(rv, return rv);
26716 }
26717 }
26718 }
26719 return UA_STATUSCODE_GOOD;
26720}
26721
26722UA_StatusCode
26723UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos,
26724 const UA_Byte *bufEnd, UA_Byte **dataToEncryptStart) {
26725
26726 UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(src, bufPos, bufEnd);
26727 UA_CHECK_STATUS(rv, return rv);
26728
26729 if(dataToEncryptStart) {
26730 *dataToEncryptStart = *bufPos;
26731 }
26732
26733 rv = UA_NetworkMessage_encodePayload(src, bufPos, bufEnd);
26734 UA_CHECK_STATUS(rv, return rv);
26735
26736 rv = UA_NetworkMessage_encodeFooters(src, bufPos, bufEnd);
26737 UA_CHECK_STATUS(rv, return rv);
26738
26739 return UA_STATUSCODE_GOOD;
26740}
26741
26742UA_StatusCode
26743UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
26744 UA_Byte decoded = 0;
26745 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26746 UA_CHECK_STATUS(rv, return rv);
26747
26748 dst->version = decoded & NM_VERSION_MASK;
26749
26750 if((decoded & NM_PUBLISHER_ID_ENABLED_MASK) != 0)
26751 dst->publisherIdEnabled = true;
26752
26753 if((decoded & NM_GROUP_HEADER_ENABLED_MASK) != 0)
26754 dst->groupHeaderEnabled = true;
26755
26756 if((decoded & NM_PAYLOAD_HEADER_ENABLED_MASK) != 0)
26757 dst->payloadHeaderEnabled = true;
26758
26759 if((decoded & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) {
26760 decoded = 0;
26761 rv = UA_Byte_decodeBinary(src, offset, &decoded);
26762 UA_CHECK_STATUS(rv, return rv);
26763
26764 dst->publisherIdType = (UA_PublisherIdDatatype)(decoded & NM_PUBLISHER_ID_MASK);
26765 if((decoded & NM_DATASET_CLASSID_ENABLED_MASK) != 0)
26766 dst->dataSetClassIdEnabled = true;
26767
26768 if((decoded & NM_SECURITY_ENABLED_MASK) != 0)
26769 dst->securityEnabled = true;
26770
26771 if((decoded & NM_TIMESTAMP_ENABLED_MASK) != 0)
26772 dst->timestampEnabled = true;
26773
26774 if((decoded & NM_PICOSECONDS_ENABLED_MASK) != 0)
26775 dst->picosecondsEnabled = true;
26776
26777 if((decoded & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) {
26778 decoded = 0;
26779 rv = UA_Byte_decodeBinary(src, offset, &decoded);
26780 UA_CHECK_STATUS(rv, return rv);
26781
26782 if((decoded & NM_CHUNK_MESSAGE_MASK) != 0)
26783 dst->chunkMessage = true;
26784
26785 if((decoded & NM_PROMOTEDFIELDS_ENABLED_MASK) != 0)
26786 dst->promotedFieldsEnabled = true;
26787
26788 decoded = decoded & NM_NETWORK_MSG_TYPE_MASK;
26789 decoded = (UA_Byte) (decoded >> NM_SHIFT_LEN);
26790 dst->networkMessageType = (UA_NetworkMessageType)decoded;
26791 }
26792 }
26793
26794 if(dst->publisherIdEnabled) {
26795 switch (dst->publisherIdType) {
26796 case UA_PUBLISHERDATATYPE_BYTE:
26797 rv = UA_Byte_decodeBinary(src, offset, &(dst->publisherId.publisherIdByte));
26798 break;
26799
26800 case UA_PUBLISHERDATATYPE_UINT16:
26801 rv = UA_UInt16_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt16));
26802 break;
26803
26804 case UA_PUBLISHERDATATYPE_UINT32:
26805 rv = UA_UInt32_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt32));
26806 break;
26807
26808 case UA_PUBLISHERDATATYPE_UINT64:
26809 rv = UA_UInt64_decodeBinary(src, offset, &(dst->publisherId.publisherIdUInt64));
26810 break;
26811
26812 case UA_PUBLISHERDATATYPE_STRING:
26813 rv = UA_String_decodeBinary(src, offset, &(dst->publisherId.publisherIdString));
26814 break;
26815
26816 default:
26817 rv = UA_STATUSCODE_BADINTERNALERROR;
26818 break;
26819 }
26820 UA_CHECK_STATUS(rv, return rv);
26821 }
26822
26823 if(dst->dataSetClassIdEnabled) {
26824 rv = UA_Guid_decodeBinary(src, offset, &(dst->dataSetClassId));
26825 UA_CHECK_STATUS(rv, return rv);
26826 }
26827 return UA_STATUSCODE_GOOD;
26828}
26829
26830static UA_StatusCode
26831UA_GroupHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26832 UA_NetworkMessage* dst) {
26833 UA_Byte decoded = 0;
26834 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26835 UA_CHECK_STATUS(rv, return rv);
26836
26837 if((decoded & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0)
26838 dst->groupHeader.writerGroupIdEnabled = true;
26839
26840 if((decoded & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0)
26841 dst->groupHeader.groupVersionEnabled = true;
26842
26843 if((decoded & GROUP_HEADER_NM_NUMBER_ENABLED) != 0)
26844 dst->groupHeader.networkMessageNumberEnabled = true;
26845
26846 if((decoded & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0)
26847 dst->groupHeader.sequenceNumberEnabled = true;
26848
26849 if(dst->groupHeader.writerGroupIdEnabled) {
26850 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.writerGroupId);
26851 UA_CHECK_STATUS(rv, return rv);
26852 }
26853 if(dst->groupHeader.groupVersionEnabled) {
26854 rv = UA_UInt32_decodeBinary(src, offset, &dst->groupHeader.groupVersion);
26855 UA_CHECK_STATUS(rv, return rv);
26856 }
26857 if(dst->groupHeader.networkMessageNumberEnabled) {
26858 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.networkMessageNumber);
26859 UA_CHECK_STATUS(rv, return rv);
26860 }
26861 if(dst->groupHeader.sequenceNumberEnabled) {
26862 rv = UA_UInt16_decodeBinary(src, offset, &dst->groupHeader.sequenceNumber);
26863 UA_CHECK_STATUS(rv, return rv);
26864 }
26865 return UA_STATUSCODE_GOOD;
26866}
26867
26868static UA_StatusCode
26869UA_PayloadHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26870 UA_NetworkMessage* dst) {
26871
26872 if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
26873 return UA_STATUSCODE_BADNOTIMPLEMENTED;
26874
26875 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &dst->payloadHeader.dataSetPayloadHeader.count);
26876 UA_CHECK_STATUS(rv, return rv);
26877
26878 dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds =
26879 (UA_UInt16 *)UA_Array_new(dst->payloadHeader.dataSetPayloadHeader.count,
26880 &UA_TYPES[UA_TYPES_UINT16]);
26881 for (UA_Byte i = 0; i < dst->payloadHeader.dataSetPayloadHeader.count; i++) {
26882 rv = UA_UInt16_decodeBinary(src, offset,
26883 &dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]);
26884 UA_CHECK_STATUS(rv, return rv);
26885 }
26886 return UA_STATUSCODE_GOOD;
26887}
26888
26889static UA_StatusCode
26890UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26891 UA_NetworkMessage* dst) {
26892 UA_StatusCode rv;
26893
26894 // Timestamp
26895 if(dst->timestampEnabled) {
26896 rv = UA_DateTime_decodeBinary(src, offset, &(dst->timestamp));
26897 UA_CHECK_STATUS(rv, goto error);
26898 }
26899
26900 // Picoseconds
26901 if(dst->picosecondsEnabled) {
26902 rv = UA_UInt16_decodeBinary(src, offset, &(dst->picoseconds));
26903 UA_CHECK_STATUS(rv, goto error);
26904 }
26905
26906 // PromotedFields
26907 if(dst->promotedFieldsEnabled) {
26908 // Size
26909 UA_UInt16 promotedFieldsSize = 0;
26910 rv = UA_UInt16_decodeBinary(src, offset, &promotedFieldsSize);
26911 UA_CHECK_STATUS(rv, goto error);
26912
26913 // promotedFieldsSize: here size in Byte, not the number of objects!
26914 if(promotedFieldsSize > 0) {
26915 // store offset, later compared with promotedFieldsSize
26916 size_t offsetEnd = (*offset) + promotedFieldsSize;
26917
26918 unsigned int counter = 0;
26919 do {
26920 if(counter == 0) {
26921 dst->promotedFields = (UA_Variant*)UA_malloc(UA_TYPES[UA_TYPES_VARIANT].memSize);
26922 UA_CHECK_MEM(dst->promotedFields,
26923 return UA_STATUSCODE_BADOUTOFMEMORY);
26924 // set promotedFieldsSize to the number of objects
26925 dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
26926 } else {
26927 dst->promotedFields = (UA_Variant*)
26928 UA_realloc(dst->promotedFields,
26929 (size_t) UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1));
26930 UA_CHECK_MEM(dst->promotedFields,
26931 return UA_STATUSCODE_BADOUTOFMEMORY);
26932 // set promotedFieldsSize to the number of objects
26933 dst->promotedFieldsSize = (UA_UInt16) (counter + 1);
26934 }
26935
26936 UA_Variant_init(&dst->promotedFields[counter]);
26937 rv = UA_Variant_decodeBinary(src, offset, &dst->promotedFields[counter]);
26938 UA_CHECK_STATUS(rv, goto error);
26939
26940 counter++;
26941 } while ((*offset) < offsetEnd);
26942 }
26943 }
26944 return UA_STATUSCODE_GOOD;
26945
26946error:
26947 if (dst->promotedFields) {
26948 UA_free(dst->promotedFields);
26949 }
26950 return rv;
26951}
26952
26953static UA_StatusCode
26954UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
26955 UA_NetworkMessage* dst) {
26956 UA_Byte decoded = 0;
26957 // SecurityFlags
26958 decoded = 0;
26959 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &decoded);
26960 UA_CHECK_STATUS(rv, return rv);
26961
26962 if((decoded & SECURITY_HEADER_NM_SIGNED) != 0)
26963 dst->securityHeader.networkMessageSigned = true;
26964
26965 if((decoded & SECURITY_HEADER_NM_ENCRYPTED) != 0)
26966 dst->securityHeader.networkMessageEncrypted = true;
26967
26968 if((decoded & SECURITY_HEADER_SEC_FOOTER_ENABLED) != 0)
26969 dst->securityHeader.securityFooterEnabled = true;
26970
26971 if((decoded & SECURITY_HEADER_FORCE_KEY_RESET) != 0)
26972 dst->securityHeader.forceKeyReset = true;
26973
26974 // SecurityTokenId
26975 rv = UA_UInt32_decodeBinary(src, offset, &dst->securityHeader.securityTokenId);
26976 UA_CHECK_STATUS(rv, return rv);
26977
26978 // NonceLength
26979 UA_Byte nonceLength;
26980 rv = UA_Byte_decodeBinary(src, offset, &nonceLength);
26981 UA_CHECK_STATUS(rv, return rv);
26982
26983 // MessageNonce
26984 if(nonceLength > 0) {
26985 //TODO: check for memory leaks
26986 rv = UA_ByteString_allocBuffer(&dst->securityHeader.messageNonce, nonceLength);
26987 UA_CHECK_STATUS(rv, return rv);
26988 for (UA_Byte i = 0; i < nonceLength; i++) {
26989 rv = UA_Byte_decodeBinary(src, offset,
26990 &dst->securityHeader.messageNonce.data[i]);
26991 UA_CHECK_STATUS(rv, return rv);
26992 }
26993 }
26994 // SecurityFooterSize
26995 if(dst->securityHeader.securityFooterEnabled) {
26996 rv = UA_UInt16_decodeBinary(src, offset, &dst->securityHeader.securityFooterSize);
26997 UA_CHECK_STATUS(rv, return rv);
26998 }
26999 return UA_STATUSCODE_GOOD;
27000}
27001
27002UA_StatusCode
27003UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
27004
27005 UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(src, offset, dst);
27006 UA_CHECK_STATUS(rv, return rv);
27007
27008 if (dst->groupHeaderEnabled) {
27009 rv = UA_GroupHeader_decodeBinary(src, offset, dst);
27010 UA_CHECK_STATUS(rv, return rv);
27011 }
27012
27013 if (dst->payloadHeaderEnabled) {
27014 rv = UA_PayloadHeader_decodeBinary(src, offset, dst);
27015 UA_CHECK_STATUS(rv, return rv);
27016 }
27017
27018 rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst);
27019 UA_CHECK_STATUS(rv, return rv);
27020
27021 if (dst->securityEnabled) {
27022 rv = UA_SecurityHeader_decodeBinary(src, offset, dst);
27023 UA_CHECK_STATUS(rv, return rv);
27024 }
27025
27026 return UA_STATUSCODE_GOOD;
27027}
27028
27029UA_StatusCode
27030UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
27031
27032 // Payload
27033 if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET)
27034 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27035
27036 UA_StatusCode rv;
27037
27038 UA_Byte count = 1;
27039 if(dst->payloadHeaderEnabled) {
27040 count = dst->payloadHeader.dataSetPayloadHeader.count;
27041 if(count > 1) {
27042 dst->payload.dataSetPayload.sizes = (UA_UInt16 *)UA_Array_new(count, &UA_TYPES[UA_TYPES_UINT16]);
27043 for (UA_Byte i = 0; i < count; i++) {
27044 rv = UA_UInt16_decodeBinary(src, offset, &(dst->payload.dataSetPayload.sizes[i]));
27045 UA_CHECK_STATUS(rv, return rv);
27046 }
27047 }
27048 }
27049
27050 dst->payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*)
27051 UA_calloc(count, sizeof(UA_DataSetMessage));
27052 UA_CHECK_MEM(dst->payload.dataSetPayload.dataSetMessages,
27053 return UA_STATUSCODE_BADOUTOFMEMORY);
27054
27055 if(count == 1)
27056 rv = UA_DataSetMessage_decodeBinary(src, offset,
27057 &(dst->payload.dataSetPayload.dataSetMessages[0]),
27058 0);
27059 else {
27060 for(UA_Byte i = 0; i < count; i++) {
27061 rv = UA_DataSetMessage_decodeBinary(src, offset,
27062 &(dst->payload.dataSetPayload.dataSetMessages[i]),
27063 dst->payload.dataSetPayload.sizes[i]);
27064 }
27065 }
27066 UA_CHECK_STATUS(rv, return rv);
27067
27068 return UA_STATUSCODE_GOOD;
27069
27070 /**
27071 * TODO: check if making the cleanup to free its own allocated memory is better,
27072 * currently the free happens in a parent context
27073 */
27074 // error:
27075 // if (dst->payload.dataSetPayload.dataSetMessages) {
27076 // UA_free(dst->payload.dataSetPayload.dataSetMessages);
27077 // }
27078 // return rv;
27079}
27080
27081UA_StatusCode
27082UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) {
27083
27084 if (dst->securityEnabled) {
27085 // SecurityFooter
27086 if(dst->securityHeader.securityFooterEnabled &&
27087 (dst->securityHeader.securityFooterSize > 0)) {
27088 UA_StatusCode rv = UA_ByteString_allocBuffer(&dst->securityFooter,
27089 dst->securityHeader.securityFooterSize);
27090 UA_CHECK_STATUS(rv, return rv);
27091
27092 for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) {
27093 rv = UA_Byte_decodeBinary(src, offset, &(dst->securityFooter.data[i]));
27094 UA_CHECK_STATUS(rv, return rv);
27095 }
27096 }
27097 }
27098 return UA_STATUSCODE_GOOD;
27099}
27100
27101UA_StatusCode
27102UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset,
27103 UA_NetworkMessage* dst) {
27104
27105 UA_StatusCode rv = UA_STATUSCODE_GOOD;
27106
27107 /* headers only need to be decoded when not in encryption mode
27108 * because headers are already decoded when encryption mode is enabled
27109 * to check for security parameters and decrypt/verify
27110 *
27111 * TODO: check if there is a workaround to use this function
27112 * also when encryption is enabled
27113 */
27114 // #ifndef UA_ENABLE_PUBSUB_ENCRYPTION
27115 // if (*offset == 0) {
27116 // rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
27117 // UA_CHECK_STATUS(rv, return rv);
27118 // }
27119 // #endif
27120
27121 rv = UA_NetworkMessage_decodeHeaders(src, offset, dst);
27122 UA_CHECK_STATUS(rv, return rv);
27123
27124 rv = UA_NetworkMessage_decodePayload(src, offset, dst);
27125 UA_CHECK_STATUS(rv, return rv);
27126
27127 rv = UA_NetworkMessage_decodeFooters(src, offset, dst);
27128 UA_CHECK_STATUS(rv, return rv);
27129
27130 return UA_STATUSCODE_GOOD;
27131}
27132
27133static UA_Boolean
27134increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) {
27135 UA_NetworkMessageOffset *tmpOffsets = (UA_NetworkMessageOffset *)
27136 UA_realloc(offsetBuffer->offsets, sizeof(UA_NetworkMessageOffset) * (offsetBuffer->offsetsSize + (size_t)1));
27137 UA_CHECK_MEM(tmpOffsets, return false);
27138
27139 offsetBuffer->offsets = tmpOffsets;
27140 offsetBuffer->offsetsSize++;
27141 return true;
27142}
27143
27144size_t
27145UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, UA_NetworkMessageOffsetBuffer *offsetBuffer) {
27146 size_t retval = 0;
27147 UA_Byte byte = 0;
27148 size_t size = UA_Byte_calcSizeBinary(&byte); // UADPVersion + UADPFlags
27149 if(UA_NetworkMessage_ExtendedFlags1Enabled(p)) {
27150 size += UA_Byte_calcSizeBinary(&byte);
27151 if(UA_NetworkMessage_ExtendedFlags2Enabled(p))
27152 size += UA_Byte_calcSizeBinary(&byte);
27153 }
27154
27155 if(p->publisherIdEnabled) {
27156 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27157 size_t pos = offsetBuffer->offsetsSize;
27158 if(!increaseOffsetArray(offsetBuffer))
27159 return 0;
27160
27161 offsetBuffer->offsets[pos].offset = size;
27162 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PUBLISHERID;
27163 }
27164 switch (p->publisherIdType) {
27165 case UA_PUBLISHERDATATYPE_BYTE:
27166 size += UA_Byte_calcSizeBinary(&p->publisherId.publisherIdByte);
27167 break;
27168
27169 case UA_PUBLISHERDATATYPE_UINT16:
27170 size += UA_UInt16_calcSizeBinary(&p->publisherId.publisherIdUInt16);
27171 break;
27172
27173 case UA_PUBLISHERDATATYPE_UINT32:
27174 size += UA_UInt32_calcSizeBinary(&p->publisherId.publisherIdUInt32);
27175 break;
27176
27177 case UA_PUBLISHERDATATYPE_UINT64:
27178 size += UA_UInt64_calcSizeBinary(&p->publisherId.publisherIdUInt64);
27179 break;
27180
27181 case UA_PUBLISHERDATATYPE_STRING:
27182 size += UA_String_calcSizeBinary(&p->publisherId.publisherIdString);
27183 break;
27184 }
27185 }
27186
27187 if(p->dataSetClassIdEnabled)
27188 size += UA_Guid_calcSizeBinary(&p->dataSetClassId);
27189
27190 // Group Header
27191 if(p->groupHeaderEnabled) {
27192 size += UA_Byte_calcSizeBinary(&byte);
27193
27194 if(p->groupHeader.writerGroupIdEnabled) {
27195 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27196 size_t pos = offsetBuffer->offsetsSize;
27197 if(!increaseOffsetArray(offsetBuffer))
27198 return 0;
27199
27200 offsetBuffer->offsets[pos].offset = size;
27201 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_WRITERGROUPID;
27202 }
27203 size += UA_UInt16_calcSizeBinary(&p->groupHeader.writerGroupId);
27204 }
27205
27206 if(p->groupHeader.groupVersionEnabled)
27207 size += UA_UInt32_calcSizeBinary(&p->groupHeader.groupVersion);
27208
27209 if(p->groupHeader.networkMessageNumberEnabled) {
27210 size += UA_UInt16_calcSizeBinary(&p->groupHeader.networkMessageNumber);
27211 }
27212
27213 if(p->groupHeader.sequenceNumberEnabled){
27214 if(offsetBuffer){
27215 size_t pos = offsetBuffer->offsetsSize;
27216 if(!increaseOffsetArray(offsetBuffer))
27217 return 0;
27218 offsetBuffer->offsets[pos].offset = size;
27219 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27220 UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27221 &p->groupHeader.sequenceNumber, &UA_TYPES[UA_TYPES_UINT16]);
27222 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER;
27223 }
27224 size += UA_UInt16_calcSizeBinary(&p->groupHeader.sequenceNumber);
27225 }
27226 }
27227
27228 // Payload Header
27229 if(p->payloadHeaderEnabled) {
27230 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27231 size += UA_Byte_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.count);
27232 if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
27233 if(offsetBuffer && offsetBuffer->RTsubscriberEnabled){
27234 size_t pos = offsetBuffer->offsetsSize;
27235 if(!increaseOffsetArray(offsetBuffer))
27236 return 0;
27237 offsetBuffer->offsets[pos].offset = size;
27238 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETWRITERID;
27239 }
27240 size += UA_UInt16_calcSizeBinary(&p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]) *
27241 p->payloadHeader.dataSetPayloadHeader.count;
27242 } else {
27243 return 0; /* no dataSetWriterIds given! */
27244 }
27245 } else {
27246 // not implemented
27247 }
27248 }
27249
27250 if(p->timestampEnabled) {
27251 if(offsetBuffer){
27252 size_t pos = offsetBuffer->offsetsSize;
27253 if(!increaseOffsetArray(offsetBuffer))
27254 return 0;
27255 offsetBuffer->offsets[pos].offset = size;
27256 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP;
27257 }
27258 size += UA_DateTime_calcSizeBinary(&p->timestamp);
27259 }
27260
27261 if(p->picosecondsEnabled){
27262 if (offsetBuffer) {
27263 size_t pos = offsetBuffer->offsetsSize;
27264 if(!increaseOffsetArray(offsetBuffer))
27265 return 0;
27266 offsetBuffer->offsets[pos].offset = size;
27267 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS;
27268 }
27269 size += UA_UInt16_calcSizeBinary(&p->picoseconds);
27270 }
27271
27272 if(p->promotedFieldsEnabled) {
27273 size += UA_UInt16_calcSizeBinary(&p->promotedFieldsSize);
27274 for (UA_UInt16 i = 0; i < p->promotedFieldsSize; i++)
27275 size += UA_Variant_calcSizeBinary(&p->promotedFields[i]);
27276 }
27277
27278 if(p->securityEnabled) {
27279 size += UA_Byte_calcSizeBinary(&byte);
27280 size += UA_UInt32_calcSizeBinary(&p->securityHeader.securityTokenId);
27281 size += 1; /* UA_Byte_calcSizeBinary(&p->securityHeader.nonceLength); */
27282 size += p->securityHeader.messageNonce.length;
27283 if(p->securityHeader.securityFooterEnabled)
27284 size += UA_UInt16_calcSizeBinary(&p->securityHeader.securityFooterSize);
27285 }
27286
27287 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27288 UA_Byte count = 1;
27289 if(p->payloadHeaderEnabled) {
27290 count = p->payloadHeader.dataSetPayloadHeader.count;
27291 if(count > 1)
27292 size += UA_UInt16_calcSizeBinary(&(p->payload.dataSetPayload.sizes[0])) * count;
27293 }
27294
27295 for (size_t i = 0; i < count; i++) {
27296 if (offsetBuffer)
27297 UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), offsetBuffer,
27298 size);
27299 size += UA_DataSetMessage_calcSizeBinary(&(p->payload.dataSetPayload.dataSetMessages[i]), NULL, 0);
27300 }
27301 }
27302
27303 if(p->securityEnabled) {
27304 if(p->securityHeader.securityFooterEnabled)
27305 size += p->securityHeader.securityFooterSize;
27306 }
27307
27308 retval = size;
27309 return retval;
27310}
27311
27312void
27313UA_NetworkMessage_clear(UA_NetworkMessage* p) {
27314 if(p->promotedFieldsEnabled)
27315 UA_Array_delete(p->promotedFields, p->promotedFieldsSize, &UA_TYPES[UA_TYPES_VARIANT]);
27316
27317 UA_ByteString_clear(&p->securityHeader.messageNonce);
27318
27319 if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) {
27320 if(p->payloadHeaderEnabled) {
27321 if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != NULL) {
27322 UA_Array_delete(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds,
27323 p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
27324 }
27325 if(p->payload.dataSetPayload.sizes != NULL) {
27326 UA_Array_delete(p->payload.dataSetPayload.sizes,
27327 p->payloadHeader.dataSetPayloadHeader.count, &UA_TYPES[UA_TYPES_UINT16]);
27328 }
27329 }
27330
27331 if(p->payload.dataSetPayload.dataSetMessages) {
27332 UA_Byte count = 1;
27333 if(p->payloadHeaderEnabled)
27334 count = p->payloadHeader.dataSetPayloadHeader.count;
27335
27336 for(size_t i = 0; i < count; i++)
27337 UA_DataSetMessage_clear(&(p->payload.dataSetPayload.dataSetMessages[i]));
27338
27339 UA_free(p->payload.dataSetPayload.dataSetMessages);
27340 }
27341 }
27342
27343 if(p->securityHeader.securityFooterEnabled && (p->securityHeader.securityFooterSize > 0))
27344 UA_ByteString_clear(&p->securityFooter);
27345
27346 if(p->messageIdEnabled){
27347 UA_String_clear(&p->messageId);
27348 }
27349
27350 if(p->publisherIdEnabled && p->publisherIdType == UA_PUBLISHERDATATYPE_STRING){
27351 UA_String_clear(&p->publisherId.publisherIdString);
27352 }
27353
27354 memset(p, 0, sizeof(UA_NetworkMessage));
27355}
27356
27357UA_Boolean
27358UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src) {
27359 UA_Boolean retval = false;
27360
27361 if((src->publisherIdType != UA_PUBLISHERDATATYPE_BYTE)
27362 || src->dataSetClassIdEnabled
27363 || src->securityEnabled
27364 || src->timestampEnabled
27365 || src->picosecondsEnabled
27366 || UA_NetworkMessage_ExtendedFlags2Enabled(src))
27367 {
27368 retval = true;
27369 }
27370
27371 return retval;
27372}
27373
27374UA_Boolean
27375UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src) {
27376 if(src->chunkMessage || src->promotedFieldsEnabled ||
27377 src->networkMessageType != UA_NETWORKMESSAGE_DATASET)
27378 return true;
27379 return false;
27380}
27381
27382UA_Boolean
27383UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src) {
27384 if(src->dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME ||
27385 src->timestampEnabled || src->picoSecondsIncluded)
27386 return true;
27387 return false;
27388}
27389
27390UA_StatusCode
27391UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, UA_Byte **bufPos,
27392 const UA_Byte *bufEnd) {
27393 UA_Byte v;
27394 // DataSetFlags1
27395 v = (UA_Byte)src->fieldEncoding;
27396 // shift left 1 bit
27397 v = (UA_Byte)(v << DS_MH_SHIFT_LEN);
27398
27399 if(src->dataSetMessageValid)
27400 v |= DS_MESSAGEHEADER_DS_MSG_VALID;
27401
27402 if(src->dataSetMessageSequenceNrEnabled)
27403 v |= DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK;
27404
27405 if(src->statusEnabled)
27406 v |= DS_MESSAGEHEADER_STATUS_ENABLED_MASK;
27407
27408 if(src->configVersionMajorVersionEnabled)
27409 v |= DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK;
27410
27411 if(src->configVersionMinorVersionEnabled)
27412 v |= DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK;
27413
27414 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src))
27415 v |= DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK;
27416
27417 UA_StatusCode rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
27418 UA_CHECK_STATUS(rv, return rv);
27419
27420 // DataSetFlags2
27421 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src)) {
27422 v = (UA_Byte)src->dataSetMessageType;
27423
27424 if(src->timestampEnabled)
27425 v |= DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK;
27426
27427 if(src->picoSecondsIncluded)
27428 v |= DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK;
27429
27430 rv = UA_Byte_encodeBinary(&v, bufPos, bufEnd);
27431 UA_CHECK_STATUS(rv, return rv);
27432 }
27433
27434 // DataSetMessageSequenceNr
27435 if(src->dataSetMessageSequenceNrEnabled) {
27436 rv = UA_UInt16_encodeBinary(&src->dataSetMessageSequenceNr, bufPos, bufEnd);
27437 UA_CHECK_STATUS(rv, return rv);
27438 }
27439
27440 // Timestamp
27441 if(src->timestampEnabled) {
27442 rv = UA_DateTime_encodeBinary(&(src->timestamp), bufPos, bufEnd); /* UtcTime */
27443 UA_CHECK_STATUS(rv, return rv);
27444 }
27445
27446 // PicoSeconds
27447 if(src->picoSecondsIncluded) {
27448 rv = UA_UInt16_encodeBinary(&(src->picoSeconds), bufPos, bufEnd);
27449 UA_CHECK_STATUS(rv, return rv);
27450 }
27451
27452 // Status
27453 if(src->statusEnabled) {
27454 rv = UA_UInt16_encodeBinary(&(src->status), bufPos, bufEnd);
27455 UA_CHECK_STATUS(rv, return rv);
27456 }
27457
27458 // ConfigVersionMajorVersion
27459 if(src->configVersionMajorVersionEnabled) {
27460 rv = UA_UInt32_encodeBinary(&(src->configVersionMajorVersion), bufPos, bufEnd);
27461 UA_CHECK_STATUS(rv, return rv);
27462 }
27463
27464 // ConfigVersionMinorVersion
27465 if(src->configVersionMinorVersionEnabled) {
27466 rv = UA_UInt32_encodeBinary(&(src->configVersionMinorVersion), bufPos, bufEnd);
27467 UA_CHECK_STATUS(rv, return rv);
27468 }
27469
27470 return UA_STATUSCODE_GOOD;
27471}
27472
27473#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
27474
27475UA_StatusCode
27476UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode,
27477 UA_PubSubSecurityPolicy *policy, void *policyContext,
27478 UA_Byte *messageStart, UA_Byte *encryptStart,
27479 UA_Byte *sigStart) {
27480 UA_StatusCode res = UA_STATUSCODE_GOOD;
27481
27482 /* Encrypt the payload */
27483 if(securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
27484 /* Set the temporary MessageNonce in the SecurityPolicy */
27485 res = policy->setMessageNonce(policyContext, &nm->securityHeader.messageNonce);
27486 UA_CHECK_STATUS(res, return res);
27487
27488 /* The encryption is done in-place, no need to encode again */
27489 UA_ByteString encryptBuf;
27490 encryptBuf.data = encryptStart;
27491 encryptBuf.length = (uintptr_t)sigStart - (uintptr_t)encryptStart;
27492 res = policy->symmetricModule.cryptoModule.encryptionAlgorithm.
27493 encrypt(policyContext, &encryptBuf);
27494 UA_CHECK_STATUS(res, return res);
27495 }
27496
27497 /* Sign the entire message */
27498 if(securityMode == UA_MESSAGESECURITYMODE_SIGN ||
27499 securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
27500 UA_ByteString sigBuf;
27501 sigBuf.length = (uintptr_t)sigStart - (uintptr_t)messageStart;
27502 sigBuf.data = messageStart;
27503 size_t sigSize = policy->symmetricModule.cryptoModule.
27504 signatureAlgorithm.getLocalSignatureSize(policyContext);
27505 UA_ByteString sig = {sigSize, sigStart};
27506 res = policy->symmetricModule.cryptoModule.
27507 signatureAlgorithm.sign(policyContext, &sigBuf, &sig);
27508 }
27509
27510 return res;
27511}
27512#endif
27513
27514UA_StatusCode
27515UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset,
27516 UA_DataSetMessageHeader* dst) {
27517 memset(dst, 0, sizeof(UA_DataSetMessageHeader));
27518 UA_Byte v = 0;
27519 UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, &v);
27520 UA_CHECK_STATUS(rv, return rv);
27521
27522 UA_Byte v2 = v & DS_MESSAGEHEADER_FIELD_ENCODING_MASK;
27523 v2 = (UA_Byte)(v2 >> DS_MH_SHIFT_LEN);
27524 dst->fieldEncoding = (UA_FieldEncoding)v2;
27525
27526 if((v & DS_MESSAGEHEADER_DS_MSG_VALID) != 0)
27527 dst->dataSetMessageValid = true;
27528
27529 if((v & DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK) != 0)
27530 dst->dataSetMessageSequenceNrEnabled = true;
27531
27532 if((v & DS_MESSAGEHEADER_STATUS_ENABLED_MASK) != 0)
27533 dst->statusEnabled = true;
27534
27535 if((v & DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK) != 0)
27536 dst->configVersionMajorVersionEnabled = true;
27537
27538 if((v & DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK) != 0)
27539 dst->configVersionMinorVersionEnabled = true;
27540
27541 if((v & DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK) != 0) {
27542 v = 0;
27543 rv = UA_Byte_decodeBinary(src, offset, &v);
27544 UA_CHECK_STATUS(rv, return rv);
27545
27546 dst->dataSetMessageType = (UA_DataSetMessageType)(v & DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK);
27547
27548 if((v & DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK) != 0)
27549 dst->timestampEnabled = true;
27550
27551 if((v & DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK) != 0)
27552 dst->picoSecondsIncluded = true;
27553 } else {
27554 dst->dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
27555 dst->picoSecondsIncluded = false;
27556 }
27557
27558 if(dst->dataSetMessageSequenceNrEnabled) {
27559 rv = UA_UInt16_decodeBinary(src, offset, &dst->dataSetMessageSequenceNr);
27560 UA_CHECK_STATUS(rv, return rv);
27561 } else {
27562 dst->dataSetMessageSequenceNr = 0;
27563 }
27564
27565 if(dst->timestampEnabled) {
27566 rv = UA_DateTime_decodeBinary(src, offset, &dst->timestamp); /* UtcTime */
27567 UA_CHECK_STATUS(rv, return rv);
27568 } else {
27569 dst->timestamp = 0;
27570 }
27571
27572 if(dst->picoSecondsIncluded) {
27573 rv = UA_UInt16_decodeBinary(src, offset, &dst->picoSeconds);
27574 UA_CHECK_STATUS(rv, return rv);
27575 } else {
27576 dst->picoSeconds = 0;
27577 }
27578
27579 if(dst->statusEnabled) {
27580 rv = UA_UInt16_decodeBinary(src, offset, &dst->status);
27581 UA_CHECK_STATUS(rv, return rv);
27582 } else {
27583 dst->status = 0;
27584 }
27585
27586 if(dst->configVersionMajorVersionEnabled) {
27587 rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMajorVersion);
27588 UA_CHECK_STATUS(rv, return rv);
27589 } else {
27590 dst->configVersionMajorVersion = 0;
27591 }
27592
27593 if(dst->configVersionMinorVersionEnabled) {
27594 rv = UA_UInt32_decodeBinary(src, offset, &dst->configVersionMinorVersion);
27595 UA_CHECK_STATUS(rv, return rv);
27596 } else {
27597 dst->configVersionMinorVersion = 0;
27598 }
27599
27600 return UA_STATUSCODE_GOOD;
27601}
27602
27603size_t
27604UA_DataSetMessageHeader_calcSizeBinary(const UA_DataSetMessageHeader* p) {
27605 UA_Byte byte = 0;
27606 size_t size = UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
27607 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(p))
27608 size += UA_Byte_calcSizeBinary(&byte);
27609
27610 if(p->dataSetMessageSequenceNrEnabled)
27611 size += UA_UInt16_calcSizeBinary(&p->dataSetMessageSequenceNr);
27612
27613 if(p->timestampEnabled)
27614 size += UA_DateTime_calcSizeBinary(&p->timestamp); /* UtcTime */
27615
27616 if(p->picoSecondsIncluded)
27617 size += UA_UInt16_calcSizeBinary(&p->picoSeconds);
27618
27619 if(p->statusEnabled)
27620 size += UA_UInt16_calcSizeBinary(&p->status);
27621
27622 if(p->configVersionMajorVersionEnabled)
27623 size += UA_UInt32_calcSizeBinary(&p->configVersionMajorVersion);
27624
27625 if(p->configVersionMinorVersionEnabled)
27626 size += UA_UInt32_calcSizeBinary(&p->configVersionMinorVersion);
27627
27628 return size;
27629}
27630
27631UA_StatusCode
27632UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos,
27633 const UA_Byte *bufEnd) {
27634 UA_StatusCode rv = UA_DataSetMessageHeader_encodeBinary(&src->header, bufPos, bufEnd);
27635 UA_CHECK_STATUS(rv, return rv);
27636
27637 if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27638 if(src->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) {
27639 rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
27640 UA_CHECK_STATUS(rv, return rv);
27641 }
27642 if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27643 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27644 rv = UA_Variant_encodeBinary(&(src->data.keyFrameData.dataSetFields[i].value), bufPos, bufEnd);
27645 UA_CHECK_STATUS(rv, return rv);
27646 }
27647 } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27648 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27649 rv = UA_encodeBinaryInternal(src->data.keyFrameData.dataSetFields[i].value.data,
27650 src->data.keyFrameData.dataSetFields[i].value.type,
27651 bufPos, &bufEnd, NULL, NULL);
27652 UA_CHECK_STATUS(rv, return rv);
27653 }
27654 } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27655 for (UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) {
27656 rv = UA_DataValue_encodeBinary(&(src->data.keyFrameData.dataSetFields[i]), bufPos, bufEnd);
27657 UA_CHECK_STATUS(rv, return rv);
27658 }
27659 }
27660 } else if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27661 // Encode Delta Frame
27662 // Here the FieldCount is always present
27663 rv = UA_UInt16_encodeBinary(&(src->data.keyFrameData.fieldCount), bufPos, bufEnd);
27664 UA_CHECK_STATUS(rv, return rv);
27665
27666 if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27667 for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
27668 rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
27669 UA_CHECK_STATUS(rv, return rv);
27670
27671 rv = UA_Variant_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue.value), bufPos, bufEnd);
27672 UA_CHECK_STATUS(rv, return rv);
27673 }
27674 } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27675 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27676 } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27677 for (UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) {
27678 rv = UA_UInt16_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldIndex), bufPos, bufEnd);
27679 UA_CHECK_STATUS(rv, return rv);
27680
27681 rv = UA_DataValue_encodeBinary(&(src->data.deltaFrameData.deltaFrameFields[i].fieldValue), bufPos, bufEnd);
27682 UA_CHECK_STATUS(rv, return rv);
27683 }
27684 }
27685 } else if(src->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
27686 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27687 }
27688
27689 /* Keep-Alive Message contains no Payload Data */
27690 return UA_STATUSCODE_GOOD;
27691}
27692
27693UA_StatusCode
27694UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataSetMessage* dst, UA_UInt16 dsmSize) {
27695 size_t initialOffset = *offset;
27696 memset(dst, 0, sizeof(UA_DataSetMessage));
27697 UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(src, offset, &dst->header);
27698 UA_CHECK_STATUS(rv, return rv);
27699
27700 if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27701 switch(dst->header.fieldEncoding) {
27702 case UA_FIELDENCODING_VARIANT:
27703 {
27704 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
27705 UA_CHECK_STATUS(rv, return rv);
27706 dst->data.keyFrameData.dataSetFields =
27707 (UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
27708 for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
27709 UA_DataValue_init(&dst->data.keyFrameData.dataSetFields[i]);
27710 rv = UA_Variant_decodeBinary(src, offset, &dst->data.keyFrameData.dataSetFields[i].value);
27711 UA_CHECK_STATUS(rv, return rv);
27712
27713 dst->data.keyFrameData.dataSetFields[i].hasValue = true;
27714 }
27715 break;
27716 }
27717 case UA_FIELDENCODING_DATAVALUE:
27718 {
27719 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.keyFrameData.fieldCount);
27720 UA_CHECK_STATUS(rv, return rv);
27721 dst->data.keyFrameData.dataSetFields =
27722 (UA_DataValue *)UA_Array_new(dst->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_DATAVALUE]);
27723 for (UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) {
27724 rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.keyFrameData.dataSetFields[i]));
27725 UA_CHECK_STATUS(rv, return rv);
27726 }
27727 break;
27728 }
27729 case UA_FIELDENCODING_RAWDATA:
27730 {
27731 dst->data.keyFrameData.rawFields.data = &src->data[*offset];
27732 dst->data.keyFrameData.rawFields.length = dsmSize;
27733 if(dsmSize == 0){
27734 //TODO calculate the length of the DSM-Payload for a single DSM
27735 //Problem: Size is not set and MetaData information are needed.
27736 //Increase offset to avoid endless chunk loop. Needs to be fixed when
27737 //pubsub security footer and signatur is enabled.
27738 *offset += 1500;
27739 } else {
27740 *offset += (dsmSize - (*offset - initialOffset));
27741 }
27742 break;
27743 }
27744 default:
27745 return UA_STATUSCODE_BADINTERNALERROR;
27746 }
27747 } else if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27748 switch(dst->header.fieldEncoding) {
27749 case UA_FIELDENCODING_VARIANT: {
27750 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
27751 UA_CHECK_STATUS(rv, return rv);
27752 size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
27753 dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
27754 for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
27755 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
27756 UA_CHECK_STATUS(rv, return rv);
27757
27758 UA_DataValue_init(&dst->data.deltaFrameData.deltaFrameFields[i].fieldValue);
27759 rv = UA_Variant_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
27760 UA_CHECK_STATUS(rv, return rv);
27761
27762 dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.hasValue = true;
27763 }
27764 break;
27765 }
27766 case UA_FIELDENCODING_DATAVALUE: {
27767 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.fieldCount);
27768 UA_CHECK_STATUS(rv, return rv);
27769 size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount;
27770 dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(memsize);
27771 for (UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) {
27772 rv = UA_UInt16_decodeBinary(src, offset, &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex);
27773 UA_CHECK_STATUS(rv, return rv);
27774
27775 rv = UA_DataValue_decodeBinary(src, offset, &(dst->data.deltaFrameData.deltaFrameFields[i].fieldValue));
27776 UA_CHECK_STATUS(rv, return rv);
27777 }
27778 break;
27779 }
27780 case UA_FIELDENCODING_RAWDATA: {
27781 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27782 }
27783 default:
27784 return UA_STATUSCODE_BADINTERNALERROR;
27785 }
27786 } else if(dst->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) {
27787 return UA_STATUSCODE_BADNOTIMPLEMENTED;
27788 }
27789
27790 /* Keep-Alive Message contains no Payload Data */
27791 return UA_STATUSCODE_GOOD;
27792}
27793
27794size_t
27795UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, UA_NetworkMessageOffsetBuffer *offsetBuffer, size_t currentOffset) {
27796 size_t size = currentOffset;
27797
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].offsetData.value.value = UA_DataValue_new();
27804 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27805 &p->header.fieldEncoding, &UA_TYPES[UA_TYPES_UINT32]);
27806 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING;
27807 }
27808
27809 UA_Byte byte = 0;
27810 size += UA_Byte_calcSizeBinary(&byte); // DataSetMessage Type + Flags
27811 if(UA_DataSetMessageHeader_DataSetFlags2Enabled(&p->header))
27812 size += UA_Byte_calcSizeBinary(&byte);
27813
27814 if(p->header.dataSetMessageSequenceNrEnabled) {
27815 if (offsetBuffer) {
27816 size_t pos = offsetBuffer->offsetsSize;
27817 if(!increaseOffsetArray(offsetBuffer))
27818 return 0;
27819 offsetBuffer->offsets[pos].offset = size;
27820 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27821 UA_Variant_setScalarCopy(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27822 &p->header.dataSetMessageSequenceNr, &UA_TYPES[UA_TYPES_UINT16]);
27823 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER;
27824 }
27825 size += UA_UInt16_calcSizeBinary(&p->header.dataSetMessageSequenceNr);
27826 }
27827
27828 if(p->header.timestampEnabled)
27829 size += UA_DateTime_calcSizeBinary(&p->header.timestamp); /* UtcTime */
27830
27831 if(p->header.picoSecondsIncluded)
27832 size += UA_UInt16_calcSizeBinary(&p->header.picoSeconds);
27833
27834 if(p->header.statusEnabled)
27835 size += UA_UInt16_calcSizeBinary(&p->header.status);
27836
27837 if(p->header.configVersionMajorVersionEnabled)
27838 size += UA_UInt32_calcSizeBinary(&p->header.configVersionMajorVersion);
27839
27840 if(p->header.configVersionMinorVersionEnabled)
27841 size += UA_UInt32_calcSizeBinary(&p->header.configVersionMinorVersion);
27842
27843 if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27844 if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA){
27845 size += UA_calcSizeBinary(&p->data.keyFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
27846 }
27847 if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27848 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
27849 if (offsetBuffer) {
27850 size_t pos = offsetBuffer->offsetsSize;
27851 if(!increaseOffsetArray(offsetBuffer))
27852 return 0;
27853 offsetBuffer->offsets[pos].offset = size;
27854 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT;
27855 //TODO check value source and alloc!
27856 //offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
27857 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27858 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27859 p->data.keyFrameData.dataSetFields[i].value.data,
27860 p->data.keyFrameData.dataSetFields[i].value.type);
27861 offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
27862 }
27863 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i].value, &UA_TYPES[UA_TYPES_VARIANT]);
27864 }
27865 } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27866 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){
27867 if (offsetBuffer) {
27868 size_t pos = offsetBuffer->offsetsSize;
27869 if(!increaseOffsetArray(offsetBuffer))
27870 return 0;
27871 offsetBuffer->offsets[pos].offset = size;
27872 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW;
27873 offsetBuffer->offsets[pos].offsetData.value.value = UA_DataValue_new();
27874 //init offset buffer with the latest value
27875 UA_Variant_setScalar(&offsetBuffer->offsets[pos].offsetData.value.value->value,
27876 p->data.keyFrameData.dataSetFields[i].value.data,
27877 p->data.keyFrameData.dataSetFields[i].value.type);
27878 offsetBuffer->offsets[pos].offsetData.value.value->value.storageType = UA_VARIANT_DATA_NODELETE;
27879 //count the memory size of the specific field
27880 offsetBuffer->rawMessageLength += p->data.keyFrameData.dataSetFields[i].value.type->memSize;
27881 }
27882 size += UA_calcSizeBinary(p->data.keyFrameData.dataSetFields[i].value.data,
27883 p->data.keyFrameData.dataSetFields[i].value.type);
27884 }
27885 } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27886 for (UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++) {
27887 if (offsetBuffer) {
27888 size_t pos = offsetBuffer->offsetsSize;
27889 if(!increaseOffsetArray(offsetBuffer))
27890 return 0;
27891 offsetBuffer->offsets[pos].offset = size;
27892 offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE;
27893 //TODO check value source, change implementation to 'variant'
27894 offsetBuffer->offsets[pos].offsetData.value.value = p->data.keyFrameData.dataSetFields;
27895 }
27896 size += UA_calcSizeBinary(&p->data.keyFrameData.dataSetFields[i], &UA_TYPES[UA_TYPES_DATAVALUE]);
27897 }
27898 }
27899 } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27900 //TODO clarify how to handle DATADELTAFRAME messages with RT
27901 if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA)
27902 size += UA_calcSizeBinary(&p->data.deltaFrameData.fieldCount, &UA_TYPES[UA_TYPES_UINT16]);
27903
27904 if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27905 for (UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27906 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldIndex, &UA_TYPES[UA_TYPES_UINT16]);
27907 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value, &UA_TYPES[UA_TYPES_VARIANT]);
27908 }
27909 } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
27910 // not implemented
27911 } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27912 for (UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27913 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldIndex, &UA_TYPES[UA_TYPES_UINT16]);
27914 size += UA_calcSizeBinary(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue, &UA_TYPES[UA_TYPES_DATAVALUE]);
27915 }
27916 }
27917 }
27918 /* KeepAlive-Message contains no Payload Data */
27919 return size;
27920}
27921
27922void
27923UA_DataSetMessage_clear(const UA_DataSetMessage* p) {
27924 if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) {
27925 if(p->data.keyFrameData.dataSetFields != NULL) {
27926 UA_Array_delete(p->data.keyFrameData.dataSetFields,
27927 p->data.keyFrameData.fieldCount,
27928 &UA_TYPES[UA_TYPES_DATAVALUE]);
27929 }
27930
27931 /* Json keys */
27932 if(p->data.keyFrameData.fieldNames != NULL){
27933 UA_Array_delete(p->data.keyFrameData.fieldNames,
27934 p->data.keyFrameData.fieldCount,
27935 &UA_TYPES[UA_TYPES_STRING]);
27936 }
27937 } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) {
27938 if(p->data.deltaFrameData.deltaFrameFields != NULL) {
27939 for(UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) {
27940 if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
27941 UA_DataValue_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue);
27942 } else if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
27943 UA_Variant_clear(&p->data.deltaFrameData.deltaFrameFields[i].fieldValue.value);
27944 }
27945 }
27946 UA_free(p->data.deltaFrameData.deltaFrameFields);
27947 }
27948 }
27949}
27950
27951void
27952UA_NetworkMessageOffsetBuffer_clear(UA_NetworkMessageOffsetBuffer *ob) {
27953 UA_ByteString_clear(&ob->buffer);
27954 if(ob->nm) {
27955 UA_NetworkMessage_clear(ob->nm);
27956 UA_free(ob->nm);
27957 }
27958 ob->nm = NULL;
27959 ob->rawMessageLength = 0;
27960
27961 for(size_t i = 0; i < ob->offsetsSize; i++) {
27962 UA_NetworkMessageOffset *nmo = &ob->offsets[i];
27963 if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT ||
27964 nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW ||
27965 nmo->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE) {
27966 UA_DataValue_delete(nmo->offsetData.value.value);
27967 } else if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER ||
27968 nmo->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER) {
27969 UA_DataValue_delete(nmo->offsetData.value.value);
27970 } else if(nmo->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING) {
27971 nmo->offsetData.value.value->value.data = NULL;
27972 UA_DataValue_delete(nmo->offsetData.value.value);
27973 }
27974 }
27975
27976 UA_free(ob->offsets);
27977 ob->offsets = NULL;
27978 ob->offsetsSize = 0;
27979
27980 ob->RTsubscriberEnabled = false;
27981
27982}
27983
27984#endif /* UA_ENABLE_PUBSUB */
27985
27986/**** amalgamated original file "/src/pubsub/ua_pubsub_writer.c" ****/
27987
27988/* This Source Code Form is subject to the terms of the Mozilla Public
27989 * License, v. 2.0. If a copy of the MPL was not distributed with this
27990 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
27991 *
27992 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
27993 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
27994 * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
27995 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
27996 * Copyright (c) 2020 Thomas Fischer, Siemens AG
27997 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
27998 */
27999
28000
28001#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
28002
28003
28004#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
28005#endif
28006
28007#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28008#endif
28009
28010/* Forward declaration */
28011static void
28012UA_DataSetField_clear(UA_DataSetField *field);
28013
28014/**********************************************/
28015/* Connection */
28016/**********************************************/
28017
28018UA_StatusCode
28019UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src,
28020 UA_PubSubConnectionConfig *dst) {
28021 UA_StatusCode res = UA_STATUSCODE_GOOD;
28022 memcpy(dst, src, sizeof(UA_PubSubConnectionConfig));
28023 res |= UA_String_copy(&src->name, &dst->name);
28024 res |= UA_Variant_copy(&src->address, &dst->address);
28025 res |= UA_String_copy(&src->transportProfileUri, &dst->transportProfileUri);
28026 res |= UA_Variant_copy(&src->connectionTransportSettings,
28027 &dst->connectionTransportSettings);
28028 if(src->connectionPropertiesSize > 0) {
28029 dst->connectionProperties = (UA_KeyValuePair *)
28030 UA_calloc(src->connectionPropertiesSize, sizeof(UA_KeyValuePair));
28031 if(!dst->connectionProperties) {
28032 UA_PubSubConnectionConfig_clear(dst);
28033 return UA_STATUSCODE_BADOUTOFMEMORY;
28034 }
28035 for(size_t i = 0; i < src->connectionPropertiesSize; i++){
28036 res |= UA_QualifiedName_copy(&src->connectionProperties[i].key,
28037 &dst->connectionProperties[i].key);
28038 res |= UA_Variant_copy(&src->connectionProperties[i].value,
28039 &dst->connectionProperties[i].value);
28040 }
28041 }
28042 if(res != UA_STATUSCODE_GOOD)
28043 UA_PubSubConnectionConfig_clear(dst);
28044 return res;
28045}
28046
28047UA_StatusCode
28048UA_Server_getPubSubConnectionConfig(UA_Server *server, const UA_NodeId connection,
28049 UA_PubSubConnectionConfig *config) {
28050 if(!config)
28051 return UA_STATUSCODE_BADINVALIDARGUMENT;
28052 UA_PubSubConnection *currentPubSubConnection =
28053 UA_PubSubConnection_findConnectionbyId(server, connection);
28054 if(!currentPubSubConnection)
28055 return UA_STATUSCODE_BADNOTFOUND;
28056 return UA_PubSubConnectionConfig_copy(currentPubSubConnection->config, config);
28057}
28058
28059UA_PubSubConnection *
28060UA_PubSubConnection_findConnectionbyId(UA_Server *server, UA_NodeId connectionIdentifier) {
28061 UA_PubSubConnection *pubSubConnection;
28062 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
28063 if(UA_NodeId_equal(&connectionIdentifier, &pubSubConnection->identifier))
28064 break;
28065 }
28066 return pubSubConnection;
28067}
28068
28069void
28070UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig) {
28071 UA_String_clear(&connectionConfig->name);
28072 UA_String_clear(&connectionConfig->transportProfileUri);
28073 UA_Variant_clear(&connectionConfig->connectionTransportSettings);
28074 UA_Variant_clear(&connectionConfig->address);
28075 for(size_t i = 0; i < connectionConfig->connectionPropertiesSize; i++){
28076 UA_QualifiedName_clear(&connectionConfig->connectionProperties[i].key);
28077 UA_Variant_clear(&connectionConfig->connectionProperties[i].value);
28078 }
28079 UA_free(connectionConfig->connectionProperties);
28080}
28081
28082void
28083UA_PubSubConnection_clear(UA_Server *server, UA_PubSubConnection *connection) {
28084 /* Remove WriterGroups */
28085 UA_WriterGroup *writerGroup, *tmpWriterGroup;
28086 LIST_FOREACH_SAFE(writerGroup, &connection->writerGroups, listEntry, tmpWriterGroup)
28087 UA_Server_removeWriterGroup(server, writerGroup->identifier);
28088
28089 /* Remove ReaderGroups */
28090 UA_ReaderGroup *readerGroups, *tmpReaderGroup;
28091 LIST_FOREACH_SAFE(readerGroups, &connection->readerGroups, listEntry, tmpReaderGroup)
28092 UA_Server_removeReaderGroup(server, readerGroups->identifier);
28093
28094 UA_NodeId_clear(&connection->identifier);
28095 if(connection->channel)
28096 connection->channel->close(connection->channel);
28097
28098 UA_PubSubConnectionConfig_clear(connection->config);
28099 UA_free(connection->config);
28100}
28101
28102/**********************************************/
28103/* PublishedDataSet */
28104/**********************************************/
28105
28106UA_StatusCode
28107UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src,
28108 UA_PublishedDataSetConfig *dst) {
28109 UA_StatusCode res = UA_STATUSCODE_GOOD;
28110 memcpy(dst, src, sizeof(UA_PublishedDataSetConfig));
28111 res |= UA_String_copy(&src->name, &dst->name);
28112 switch(src->publishedDataSetType) {
28113 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
28114 //no additional items
28115 break;
28116
28117 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
28118 if(src->config.itemsTemplate.variablesToAddSize > 0) {
28119 dst->config.itemsTemplate.variablesToAdd = (UA_PublishedVariableDataType *)
28120 UA_calloc(src->config.itemsTemplate.variablesToAddSize,
28121 sizeof(UA_PublishedVariableDataType));
28122 if(!dst->config.itemsTemplate.variablesToAdd) {
28123 res = UA_STATUSCODE_BADOUTOFMEMORY;
28124 break;
28125 }
28126 dst->config.itemsTemplate.variablesToAddSize =
28127 src->config.itemsTemplate.variablesToAddSize;
28128 }
28129
28130 for(size_t i = 0; i < src->config.itemsTemplate.variablesToAddSize; i++) {
28131 res |= UA_PublishedVariableDataType_copy(&src->config.itemsTemplate.variablesToAdd[i],
28132 &dst->config.itemsTemplate.variablesToAdd[i]);
28133 }
28134 res |= UA_DataSetMetaDataType_copy(&src->config.itemsTemplate.metaData,
28135 &dst->config.itemsTemplate.metaData);
28136 break;
28137
28138 default:
28139 res = UA_STATUSCODE_BADINVALIDARGUMENT;
28140 break;
28141 }
28142
28143 if(res != UA_STATUSCODE_GOOD)
28144 UA_PublishedDataSetConfig_clear(dst);
28145 return res;
28146}
28147
28148UA_StatusCode
28149UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds,
28150 UA_PublishedDataSetConfig *config) {
28151 if(!config)
28152 return UA_STATUSCODE_BADINVALIDARGUMENT;
28153 UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
28154 if(!currentPDS)
28155 return UA_STATUSCODE_BADNOTFOUND;
28156 return UA_PublishedDataSetConfig_copy(&currentPDS->config, config);
28157}
28158
28159UA_StatusCode
28160UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds,
28161 UA_DataSetMetaDataType *metaData) {
28162 if(!metaData)
28163 return UA_STATUSCODE_BADINVALIDARGUMENT;
28164 UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, pds);
28165 if(!currentPDS)
28166 return UA_STATUSCODE_BADNOTFOUND;
28167 return UA_DataSetMetaDataType_copy(&currentPDS->dataSetMetaData, metaData);
28168}
28169
28170UA_PublishedDataSet *
28171UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier) {
28172 UA_PublishedDataSet *tmpPDS = NULL;
28173 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
28174 if(UA_NodeId_equal(&tmpPDS->identifier, &identifier))
28175 break;
28176 }
28177 return tmpPDS;
28178}
28179
28180void
28181UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig) {
28182 //delete pds config
28183 UA_String_clear(&pdsConfig->name);
28184 switch (pdsConfig->publishedDataSetType){
28185 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
28186 //no additional items
28187 break;
28188 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
28189 if(pdsConfig->config.itemsTemplate.variablesToAddSize > 0){
28190 for(size_t i = 0; i < pdsConfig->config.itemsTemplate.variablesToAddSize; i++){
28191 UA_PublishedVariableDataType_clear(&pdsConfig->config.itemsTemplate.variablesToAdd[i]);
28192 }
28193 UA_free(pdsConfig->config.itemsTemplate.variablesToAdd);
28194 }
28195 UA_DataSetMetaDataType_clear(&pdsConfig->config.itemsTemplate.metaData);
28196 break;
28197 default:
28198 break;
28199 }
28200}
28201
28202void
28203UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet) {
28204 UA_DataSetField *field, *tmpField;
28205 TAILQ_FOREACH_SAFE(field, &publishedDataSet->fields, listEntry, tmpField) {
28206 UA_Server_removeDataSetField(server, field->identifier);
28207 }
28208 UA_PublishedDataSetConfig_clear(&publishedDataSet->config);
28209 UA_DataSetMetaDataType_clear(&publishedDataSet->dataSetMetaData);
28210 UA_NodeId_clear(&publishedDataSet->identifier);
28211}
28212
28213/* The fieldMetaData variable has to be cleaned up external in case of an error */
28214static UA_StatusCode
28215generateFieldMetaData(UA_Server *server, UA_DataSetField *field,
28216 UA_FieldMetaData *fieldMetaData) {
28217 if(field->config.dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
28218 return UA_STATUSCODE_BADNOTSUPPORTED;
28219
28220 /* Set the field identifier */
28221 fieldMetaData->dataSetFieldId = UA_PubSubManager_generateUniqueGuid(server);
28222
28223 /* Set the description */
28224 fieldMetaData->description = UA_LOCALIZEDTEXT_ALLOC("", "");
28225
28226 /* Set the name */
28227 const UA_DataSetVariableConfig *var = &field->config.field.variable;
28228 UA_StatusCode res = UA_String_copy(&var->fieldNameAlias, &fieldMetaData->name);
28229 UA_CHECK_STATUS(res, return res);
28230
28231 /* Static value source. ToDo after freeze PR, the value source must be
28232 * checked (other behavior for static value source) */
28233 if(var->rtValueSource.rtFieldSourceEnabled &&
28234 !var->rtValueSource.rtInformationModelNode) {
28235 const UA_DataValue *svs = *var->rtValueSource.staticValueSource;
28236 if(svs->value.arrayDimensionsSize > 0) {
28237 fieldMetaData->arrayDimensions = (UA_UInt32 *)
28238 UA_calloc(svs->value.arrayDimensionsSize, sizeof(UA_UInt32));
28239 if(fieldMetaData->arrayDimensions == NULL)
28240 return UA_STATUSCODE_BADOUTOFMEMORY;
28241 memcpy(fieldMetaData->arrayDimensions, svs->value.arrayDimensions,
28242 sizeof(UA_UInt32) * svs->value.arrayDimensionsSize);
28243 }
28244 fieldMetaData->arrayDimensionsSize = svs->value.arrayDimensionsSize;
28245
28246 res = UA_NodeId_copy(&svs->value.type->typeId, &fieldMetaData->dataType);
28247 UA_CHECK_STATUS(res, return res);
28248
28249 //TODO collect value rank for the static field source
28250 fieldMetaData->properties = NULL;
28251 fieldMetaData->propertiesSize = 0;
28252 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
28253 return UA_STATUSCODE_GOOD;
28254 }
28255
28256 /* Set the Array Dimensions */
28257 const UA_PublishedVariableDataType *pp = &var->publishParameters;
28258 UA_Variant value;
28259 UA_Variant_init(&value);
28260 res = UA_Server_readArrayDimensions(server, pp->publishedVariable, &value);
28261 UA_CHECK_STATUS_LOG(res, return res,
28262 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28263 "PubSub meta data generation. Reading the array dimensions failed.");
28264
28265 if(value.arrayDimensionsSize > 0) {
28266 fieldMetaData->arrayDimensions = (UA_UInt32 *)
28267 UA_calloc(value.arrayDimensionsSize, sizeof(UA_UInt32));
28268 if(!fieldMetaData->arrayDimensions)
28269 return UA_STATUSCODE_BADOUTOFMEMORY;
28270 memcpy(fieldMetaData->arrayDimensions, value.arrayDimensions,
28271 sizeof(UA_UInt32)*value.arrayDimensionsSize);
28272 }
28273 fieldMetaData->arrayDimensionsSize = value.arrayDimensionsSize;
28274 UA_Variant_clear(&value);
28275
28276 /* Set the DataType */
28277 res = UA_Server_readDataType(server, pp->publishedVariable,
28278 &fieldMetaData->dataType);
28279 UA_CHECK_STATUS_LOG(res, return res,
28280 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28281 "PubSub meta data generation. Reading the datatype failed.");
28282
28283 if(!UA_NodeId_isNull(&fieldMetaData->dataType)) {
28284 const UA_DataType *currentDataType =
28285 UA_findDataTypeWithCustom(&fieldMetaData->dataType,
28286 server->config.customDataTypes);
28287#ifdef UA_ENABLE_TYPEDESCRIPTION
28288 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
28289 "MetaData creation. Found DataType %s.", currentDataType->typeName);
28290#endif
28291 /* Check if the datatype is a builtInType, if yes set the builtinType.
28292 * TODO: Remove the magic number */
28293 if(currentDataType->typeKind <= UA_DATATYPEKIND_ENUM)
28294 fieldMetaData->builtInType = (UA_Byte)currentDataType->typeKind;
28295 } else {
28296 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28297 "PubSub meta data generation. DataType is UA_NODEID_NULL.");
28298 }
28299
28300 /* Set the ValueRank */
28301 UA_Int32 valueRank;
28302 res = UA_Server_readValueRank(server, pp->publishedVariable, &valueRank);
28303 UA_CHECK_STATUS_LOG(res, return res,
28304 WARNING, &server->config.logger, UA_LOGCATEGORY_SERVER,
28305 "PubSub meta data generation. Reading the value rank failed.");
28306 fieldMetaData->valueRank = valueRank;
28307
28308 /* PromotedField? */
28309 if(var->promotedField)
28310 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_PROMOTEDFIELD;
28311 else
28312 fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE;
28313
28314 /* Properties */
28315 fieldMetaData->properties = NULL;
28316 fieldMetaData->propertiesSize = 0;
28317
28318 //TODO collect the following fields*/
28319 //fieldMetaData.builtInType
28320 //fieldMetaData.maxStringLength
28321
28322 return UA_STATUSCODE_GOOD;
28323}
28324
28325UA_DataSetFieldResult
28326UA_Server_addDataSetField(UA_Server *server, const UA_NodeId publishedDataSet,
28327 const UA_DataSetFieldConfig *fieldConfig,
28328 UA_NodeId *fieldIdentifier) {
28329 UA_DataSetFieldResult result = {0};
28330 if(!fieldConfig) {
28331 result.result = UA_STATUSCODE_BADINVALIDARGUMENT;
28332 return result;
28333 }
28334
28335 UA_PublishedDataSet *currDS =
28336 UA_PublishedDataSet_findPDSbyId(server, publishedDataSet);
28337 if(!currDS) {
28338 result.result = UA_STATUSCODE_BADNOTFOUND;
28339 return result;
28340 }
28341
28342 if(currDS->configurationFrozen) {
28343 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28344 "Adding DataSetField failed. PublishedDataSet is frozen.");
28345 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28346 return result;
28347 }
28348
28349 if(currDS->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS) {
28350 result.result = UA_STATUSCODE_BADNOTIMPLEMENTED;
28351 return result;
28352 }
28353
28354 UA_DataSetField *newField = (UA_DataSetField*)UA_calloc(1, sizeof(UA_DataSetField));
28355 if(!newField) {
28356 result.result = UA_STATUSCODE_BADINTERNALERROR;
28357 return result;
28358 }
28359
28360 UA_StatusCode retVal = UA_DataSetFieldConfig_copy(fieldConfig, &newField->config);
28361 if(retVal != UA_STATUSCODE_GOOD) {
28362 UA_free(newField);
28363 result.result = retVal;
28364 return result;
28365 }
28366
28367 newField->publishedDataSet = currDS->identifier;
28368
28369 /* Initialize the field metadata. Also generates a FieldId */
28370 UA_FieldMetaData fmd;
28371 UA_FieldMetaData_init(&fmd);
28372 result.result = generateFieldMetaData(server, newField, &fmd);
28373 if(result.result != UA_STATUSCODE_GOOD) {
28374 UA_FieldMetaData_clear(&fmd);
28375 UA_DataSetFieldConfig_clear(&newField->config);
28376 UA_free(newField);
28377 return result;
28378 }
28379
28380 /* Append to the metadata fields array. Point of last return. */
28381 result.result = UA_Array_append((void**)&currDS->dataSetMetaData.fields,
28382 &currDS->dataSetMetaData.fieldsSize,
28383 &fmd, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
28384 if(result.result != UA_STATUSCODE_GOOD) {
28385 UA_FieldMetaData_clear(&fmd);
28386 UA_DataSetFieldConfig_clear(&newField->config);
28387 UA_free(newField);
28388 return result;
28389 }
28390
28391 /* Copy the identifier from the metadata. Cannot fail with a guid NodeId. */
28392 newField->identifier = UA_NODEID_GUID(1, fmd.dataSetFieldId);
28393 if(fieldIdentifier)
28394 UA_NodeId_copy(&newField->identifier, fieldIdentifier);
28395
28396 /* Register the field. The order of DataSetFields should be the same in both
28397 * creating and publishing. So adding DataSetFields at the the end of the
28398 * DataSets using the TAILQ structure. */
28399 TAILQ_INSERT_TAIL(&currDS->fields, newField, listEntry);
28400 currDS->fieldSize++;
28401
28402 if(newField->config.field.variable.promotedField)
28403 currDS->promotedFieldsCount++;
28404
28405 /* The values of the metadata are "borrowed" in a mirrored structure in the
28406 * pds. Reset them after resizing the array. */
28407 size_t counter = 0;
28408 UA_DataSetField *dsf;
28409 TAILQ_FOREACH(dsf, &currDS->fields, listEntry) {
28410 dsf->fieldMetaData = currDS->dataSetMetaData.fields[counter++];
28411 }
28412
28413 /* Update major version of parent published data set */
28414 currDS->dataSetMetaData.configurationVersion.majorVersion =
28415 UA_PubSubConfigurationVersionTimeDifference();
28416
28417 result.configurationVersion.majorVersion =
28418 currDS->dataSetMetaData.configurationVersion.majorVersion;
28419 result.configurationVersion.minorVersion =
28420 currDS->dataSetMetaData.configurationVersion.minorVersion;
28421 return result;
28422}
28423
28424UA_DataSetFieldResult
28425UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf) {
28426 UA_DataSetFieldResult result = {0};
28427
28428 UA_DataSetField *currentField = UA_DataSetField_findDSFbyId(server, dsf);
28429 if(!currentField) {
28430 result.result = UA_STATUSCODE_BADNOTFOUND;
28431 return result;
28432 }
28433
28434 if(currentField->configurationFrozen) {
28435 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28436 "Remove DataSetField failed. DataSetField is frozen.");
28437 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28438 return result;
28439 }
28440
28441 UA_PublishedDataSet *pds =
28442 UA_PublishedDataSet_findPDSbyId(server, currentField->publishedDataSet);
28443 if(!pds) {
28444 result.result = UA_STATUSCODE_BADNOTFOUND;
28445 return result;
28446 }
28447
28448 if(pds->configurationFrozen) {
28449 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28450 "Remove DataSetField failed. PublishedDataSet is frozen.");
28451 result.result = UA_STATUSCODE_BADCONFIGURATIONERROR;
28452 return result;
28453 }
28454
28455 /* Reduce the counters before the config is cleaned up */
28456 if(currentField->config.field.variable.promotedField)
28457 pds->promotedFieldsCount--;
28458 pds->fieldSize--;
28459
28460 /* Update major version of PublishedDataSet */
28461 pds->dataSetMetaData.configurationVersion.majorVersion =
28462 UA_PubSubConfigurationVersionTimeDifference();
28463
28464 /* Clean up */
28465 currentField->fieldMetaData.arrayDimensions = NULL;
28466 currentField->fieldMetaData.properties = NULL;
28467 currentField->fieldMetaData.name = UA_STRING_NULL;
28468 currentField->fieldMetaData.description.locale = UA_STRING_NULL;
28469 currentField->fieldMetaData.description.text = UA_STRING_NULL;
28470 UA_DataSetField_clear(currentField);
28471
28472 /* Remove */
28473 TAILQ_REMOVE(&pds->fields, currentField, listEntry);
28474 UA_free(currentField);
28475
28476 /* Regenerate DataSetMetaData */
28477 pds->dataSetMetaData.fieldsSize--;
28478 if(pds->dataSetMetaData.fieldsSize > 0) {
28479 for(size_t i = 0; i < pds->dataSetMetaData.fieldsSize+1; i++) {
28480 UA_FieldMetaData_clear(&pds->dataSetMetaData.fields[i]);
28481 }
28482 UA_free(pds->dataSetMetaData.fields);
28483 UA_FieldMetaData *fieldMetaData = (UA_FieldMetaData *)
28484 UA_calloc(pds->dataSetMetaData.fieldsSize, sizeof(UA_FieldMetaData));
28485 if(!fieldMetaData) {
28486 result.result = UA_STATUSCODE_BADOUTOFMEMORY;
28487 return result;
28488 }
28489 UA_DataSetField *tmpDSF;
28490 size_t counter = 0;
28491 TAILQ_FOREACH(tmpDSF, &pds->fields, listEntry){
28492 result.result = generateFieldMetaData(server, tmpDSF, &fieldMetaData[counter]);
28493 if(result.result != UA_STATUSCODE_GOOD) {
28494 UA_FieldMetaData_clear(&fieldMetaData[counter]);
28495 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28496 "PubSub MetaData generation failed!");
28497 break;
28498 }
28499 counter++;
28500 }
28501 pds->dataSetMetaData.fields = fieldMetaData;
28502 } else {
28503 UA_FieldMetaData_delete(pds->dataSetMetaData.fields);
28504 pds->dataSetMetaData.fields = NULL;
28505 }
28506
28507 result.configurationVersion.majorVersion =
28508 pds->dataSetMetaData.configurationVersion.majorVersion;
28509 result.configurationVersion.minorVersion =
28510 pds->dataSetMetaData.configurationVersion.minorVersion;
28511 return result;
28512}
28513
28514/**********************************************/
28515/* DataSetWriter */
28516/**********************************************/
28517
28518UA_StatusCode
28519UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src,
28520 UA_DataSetWriterConfig *dst){
28521 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
28522 memcpy(dst, src, sizeof(UA_DataSetWriterConfig));
28523 retVal |= UA_String_copy(&src->name, &dst->name);
28524 retVal |= UA_String_copy(&src->dataSetName, &dst->dataSetName);
28525 retVal |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
28526 if(src->dataSetWriterPropertiesSize > 0) {
28527 dst->dataSetWriterProperties = (UA_KeyValuePair *)
28528 UA_calloc(src->dataSetWriterPropertiesSize, sizeof(UA_KeyValuePair));
28529 if(!dst->dataSetWriterProperties)
28530 return UA_STATUSCODE_BADOUTOFMEMORY;
28531 for(size_t i = 0; i < src->dataSetWriterPropertiesSize; i++){
28532 retVal |= UA_KeyValuePair_copy(&src->dataSetWriterProperties[i],
28533 &dst->dataSetWriterProperties[i]);
28534 }
28535 }
28536 return retVal;
28537}
28538
28539UA_StatusCode
28540UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw,
28541 UA_DataSetWriterConfig *config) {
28542 if(!config)
28543 return UA_STATUSCODE_BADINVALIDARGUMENT;
28544 UA_DataSetWriter *currentDataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
28545 if(!currentDataSetWriter)
28546 return UA_STATUSCODE_BADNOTFOUND;
28547 return UA_DataSetWriterConfig_copy(&currentDataSetWriter->config, config);
28548}
28549
28550UA_StatusCode
28551UA_Server_DataSetWriter_getState(UA_Server *server, UA_NodeId dataSetWriterIdentifier,
28552 UA_PubSubState *state) {
28553 if((server == NULL) || (state == NULL))
28554 return UA_STATUSCODE_BADINVALIDARGUMENT;
28555 UA_DataSetWriter *currentDataSetWriter =
28556 UA_DataSetWriter_findDSWbyId(server, dataSetWriterIdentifier);
28557 if(currentDataSetWriter == NULL)
28558 return UA_STATUSCODE_BADNOTFOUND;
28559 *state = currentDataSetWriter->state;
28560 return UA_STATUSCODE_GOOD;
28561}
28562
28563UA_DataSetWriter *
28564UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier) {
28565 UA_PubSubConnection *pubSubConnection;
28566 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
28567 UA_WriterGroup *tmpWriterGroup;
28568 LIST_FOREACH(tmpWriterGroup, &pubSubConnection->writerGroups, listEntry){
28569 UA_DataSetWriter *tmpWriter;
28570 LIST_FOREACH(tmpWriter, &tmpWriterGroup->writers, listEntry){
28571 if(UA_NodeId_equal(&tmpWriter->identifier, &identifier)){
28572 return tmpWriter;
28573 }
28574 }
28575 }
28576 }
28577 return NULL;
28578}
28579
28580void
28581UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig) {
28582 UA_String_clear(&pdsConfig->name);
28583 UA_String_clear(&pdsConfig->dataSetName);
28584 for(size_t i = 0; i < pdsConfig->dataSetWriterPropertiesSize; i++) {
28585 UA_KeyValuePair_clear(&pdsConfig->dataSetWriterProperties[i]);
28586 }
28587 UA_free(pdsConfig->dataSetWriterProperties);
28588 UA_ExtensionObject_clear(&pdsConfig->messageSettings);
28589}
28590
28591static void
28592UA_DataSetWriter_clear(UA_Server *server, UA_DataSetWriter *dataSetWriter) {
28593 UA_DataSetWriterConfig_clear(&dataSetWriter->config);
28594 UA_NodeId_clear(&dataSetWriter->identifier);
28595 UA_NodeId_clear(&dataSetWriter->linkedWriterGroup);
28596 UA_NodeId_clear(&dataSetWriter->connectedDataSet);
28597
28598 /* Delete lastSamples store */
28599#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28600 for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++) {
28601 UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
28602 }
28603 UA_free(dataSetWriter->lastSamples);
28604 dataSetWriter->lastSamples = NULL;
28605 dataSetWriter->lastSamplesCount = 0;
28606#endif
28607}
28608
28609//state machine methods not part of the open62541 state machine API
28610UA_StatusCode
28611UA_DataSetWriter_setPubSubState(UA_Server *server, UA_PubSubState state,
28612 UA_DataSetWriter *dataSetWriter) {
28613 switch(state){
28614 case UA_PUBSUBSTATE_DISABLED:
28615 switch (dataSetWriter->state){
28616 case UA_PUBSUBSTATE_DISABLED:
28617 return UA_STATUSCODE_GOOD;
28618 case UA_PUBSUBSTATE_PAUSED:
28619 dataSetWriter->state = UA_PUBSUBSTATE_DISABLED;
28620 //no further action is required
28621 break;
28622 case UA_PUBSUBSTATE_OPERATIONAL:
28623 dataSetWriter->state = UA_PUBSUBSTATE_DISABLED;
28624 break;
28625 case UA_PUBSUBSTATE_ERROR:
28626 break;
28627 default:
28628 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28629 "Received unknown PubSub state!");
28630 }
28631 break;
28632 case UA_PUBSUBSTATE_PAUSED:
28633 switch (dataSetWriter->state){
28634 case UA_PUBSUBSTATE_DISABLED:
28635 break;
28636 case UA_PUBSUBSTATE_PAUSED:
28637 return UA_STATUSCODE_GOOD;
28638 case UA_PUBSUBSTATE_OPERATIONAL:
28639 break;
28640 case UA_PUBSUBSTATE_ERROR:
28641 break;
28642 default:
28643 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28644 "Received unknown PubSub state!");
28645 }
28646 break;
28647 case UA_PUBSUBSTATE_OPERATIONAL:
28648 switch (dataSetWriter->state){
28649 case UA_PUBSUBSTATE_DISABLED:
28650 dataSetWriter->state = UA_PUBSUBSTATE_OPERATIONAL;
28651 break;
28652 case UA_PUBSUBSTATE_PAUSED:
28653 break;
28654 case UA_PUBSUBSTATE_OPERATIONAL:
28655 return UA_STATUSCODE_GOOD;
28656 case UA_PUBSUBSTATE_ERROR:
28657 break;
28658 default:
28659 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28660 "Received unknown PubSub state!");
28661 }
28662 break;
28663 case UA_PUBSUBSTATE_ERROR:
28664 switch (dataSetWriter->state){
28665 case UA_PUBSUBSTATE_DISABLED:
28666 break;
28667 case UA_PUBSUBSTATE_PAUSED:
28668 break;
28669 case UA_PUBSUBSTATE_OPERATIONAL:
28670 break;
28671 case UA_PUBSUBSTATE_ERROR:
28672 return UA_STATUSCODE_GOOD;
28673 default:
28674 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28675 "Received unknown PubSub state!");
28676 }
28677 break;
28678 default:
28679 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28680 "Received unknown PubSub state!");
28681 }
28682 return UA_STATUSCODE_GOOD;
28683}
28684
28685UA_StatusCode
28686UA_Server_addDataSetWriter(UA_Server *server,
28687 const UA_NodeId writerGroup, const UA_NodeId dataSet,
28688 const UA_DataSetWriterConfig *dataSetWriterConfig,
28689 UA_NodeId *writerIdentifier) {
28690 if(!dataSetWriterConfig)
28691 return UA_STATUSCODE_BADINVALIDARGUMENT;
28692
28693 UA_PublishedDataSet *currentDataSetContext =
28694 UA_PublishedDataSet_findPDSbyId(server, dataSet);
28695 if(!currentDataSetContext)
28696 return UA_STATUSCODE_BADNOTFOUND;
28697
28698 if(currentDataSetContext->configurationFrozen){
28699 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28700 "Adding DataSetWriter failed. PublishedDataSet is frozen.");
28701 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28702 }
28703
28704 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
28705 if(!wg)
28706 return UA_STATUSCODE_BADNOTFOUND;
28707
28708 if(wg->configurationFrozen) {
28709 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28710 "Adding DataSetWriter failed. WriterGroup is frozen.");
28711 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28712 }
28713
28714 if(wg->config.rtLevel != UA_PUBSUB_RT_NONE) {
28715 UA_DataSetField *tmpDSF;
28716 TAILQ_FOREACH(tmpDSF, &currentDataSetContext->fields, listEntry) {
28717 if(!tmpDSF->config.field.variable.rtValueSource.rtFieldSourceEnabled &&
28718 !tmpDSF->config.field.variable.rtValueSource.rtInformationModelNode) {
28719 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28720 "Adding DataSetWriter failed. Fields in PDS are not RT capable.");
28721 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28722 }
28723 }
28724 }
28725
28726 UA_DataSetWriter *newDataSetWriter = (UA_DataSetWriter *)
28727 UA_calloc(1, sizeof(UA_DataSetWriter));
28728 if(!newDataSetWriter)
28729 return UA_STATUSCODE_BADOUTOFMEMORY;
28730
28731 newDataSetWriter->componentType = UA_PUBSUB_COMPONENT_DATASETWRITER;
28732
28733 UA_StatusCode res = UA_STATUSCODE_GOOD;
28734 if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
28735 res = UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
28736 newDataSetWriter);
28737 if(res != UA_STATUSCODE_GOOD) {
28738 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
28739 "Add DataSetWriter failed. setPubSubState failed.");
28740 UA_free(newDataSetWriter);
28741 return res;
28742 }
28743 }
28744
28745 /* Copy the config into the new dataSetWriter */
28746 res = UA_DataSetWriterConfig_copy(dataSetWriterConfig, &newDataSetWriter->config);
28747 UA_CHECK_STATUS(res, UA_free(newDataSetWriter); return res);
28748
28749 /* Save the current version of the connected PublishedDataSet */
28750 newDataSetWriter->connectedDataSetVersion =
28751 currentDataSetContext->dataSetMetaData.configurationVersion;
28752
28753#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28754 /* Initialize the queue for the last values */
28755 if(currentDataSetContext->fieldSize > 0) {
28756 newDataSetWriter->lastSamples = (UA_DataSetWriterSample*)
28757 UA_calloc(currentDataSetContext->fieldSize, sizeof(UA_DataSetWriterSample));
28758 if(!newDataSetWriter->lastSamples) {
28759 UA_DataSetWriterConfig_clear(&newDataSetWriter->config);
28760 UA_free(newDataSetWriter);
28761 return UA_STATUSCODE_BADOUTOFMEMORY;
28762 }
28763 newDataSetWriter->lastSamplesCount = currentDataSetContext->fieldSize;
28764 for(size_t i = 0; i < newDataSetWriter->lastSamplesCount; i++) {
28765 UA_DataValue_init(&newDataSetWriter->lastSamples[i].value);
28766 newDataSetWriter->lastSamples[i].valueChanged = false;
28767 }
28768 }
28769#endif
28770
28771 /* Connect PublishedDataSet with DataSetWriter */
28772 newDataSetWriter->connectedDataSet = currentDataSetContext->identifier;
28773 newDataSetWriter->linkedWriterGroup = wg->identifier;
28774
28775 /* Add the new writer to the group */
28776 LIST_INSERT_HEAD(&wg->writers, newDataSetWriter, listEntry);
28777 wg->writersCount++;
28778
28779#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
28780 res |= addDataSetWriterRepresentation(server, newDataSetWriter);
28781#else
28782 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
28783 &newDataSetWriter->identifier);
28784#endif
28785 if(writerIdentifier)
28786 UA_NodeId_copy(&newDataSetWriter->identifier, writerIdentifier);
28787 return res;
28788}
28789
28790UA_StatusCode
28791UA_DataSetWriter_remove(UA_Server *server, UA_WriterGroup *linkedWriterGroup,
28792 UA_DataSetWriter *dataSetWriter) {
28793 /* Frozen? */
28794 if(linkedWriterGroup->configurationFrozen) {
28795 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28796 "Remove DataSetWriter failed. WriterGroup is frozen.");
28797 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28798 }
28799
28800 /* Remove from information model */
28801#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
28802 removeDataSetWriterRepresentation(server, dataSetWriter);
28803#endif
28804
28805 /* Remove DataSetWriter from group */
28806 UA_DataSetWriter_clear(server, dataSetWriter);
28807 LIST_REMOVE(dataSetWriter, listEntry);
28808 linkedWriterGroup->writersCount--;
28809 UA_free(dataSetWriter);
28810 return UA_STATUSCODE_GOOD;
28811}
28812
28813UA_StatusCode
28814UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw) {
28815 UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, dsw);
28816 if(!dataSetWriter)
28817 return UA_STATUSCODE_BADNOTFOUND;
28818
28819 if(dataSetWriter->configurationFrozen) {
28820 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
28821 "Remove DataSetWriter failed. DataSetWriter is frozen.");
28822 return UA_STATUSCODE_BADCONFIGURATIONERROR;
28823 }
28824
28825 UA_WriterGroup *linkedWriterGroup =
28826 UA_WriterGroup_findWGbyId(server, dataSetWriter->linkedWriterGroup);
28827 if(!linkedWriterGroup)
28828 return UA_STATUSCODE_BADNOTFOUND;
28829
28830 return UA_DataSetWriter_remove(server, linkedWriterGroup, dataSetWriter);
28831}
28832
28833/**********************************************/
28834/* DataSetField */
28835/**********************************************/
28836
28837static void
28838UA_DataSetField_clear(UA_DataSetField *field) {
28839 UA_DataSetFieldConfig_clear(&field->config);
28840 UA_NodeId_clear(&field->identifier);
28841 UA_NodeId_clear(&field->publishedDataSet);
28842 UA_FieldMetaData_clear(&field->fieldMetaData);
28843}
28844
28845UA_StatusCode
28846UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src,
28847 UA_DataSetFieldConfig *dst) {
28848 if(src->dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE)
28849 return UA_STATUSCODE_BADNOTSUPPORTED;
28850 memcpy(dst, src, sizeof(UA_DataSetFieldConfig));
28851 UA_StatusCode res = UA_STATUSCODE_GOOD;
28852 res |= UA_String_copy(&src->field.variable.fieldNameAlias,
28853 &dst->field.variable.fieldNameAlias);
28854 res |= UA_PublishedVariableDataType_copy(&src->field.variable.publishParameters,
28855 &dst->field.variable.publishParameters);
28856 if(res != UA_STATUSCODE_GOOD)
28857 UA_DataSetFieldConfig_clear(dst);
28858 return res;
28859}
28860
28861UA_StatusCode
28862UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf,
28863 UA_DataSetFieldConfig *config) {
28864 if(!config)
28865 return UA_STATUSCODE_BADINVALIDARGUMENT;
28866 UA_DataSetField *currentDataSetField = UA_DataSetField_findDSFbyId(server, dsf);
28867 if(!currentDataSetField)
28868 return UA_STATUSCODE_BADNOTFOUND;
28869 return UA_DataSetFieldConfig_copy(&currentDataSetField->config, config);
28870}
28871
28872UA_DataSetField *
28873UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier) {
28874 UA_PublishedDataSet *tmpPDS;
28875 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) {
28876 UA_DataSetField *tmpField;
28877 TAILQ_FOREACH(tmpField, &tmpPDS->fields, listEntry) {
28878 if(UA_NodeId_equal(&tmpField->identifier, &identifier))
28879 return tmpField;
28880 }
28881 }
28882 return NULL;
28883}
28884
28885void
28886UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig) {
28887 if(dataSetFieldConfig->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE) {
28888 UA_String_clear(&dataSetFieldConfig->field.variable.fieldNameAlias);
28889 UA_PublishedVariableDataType_clear(&dataSetFieldConfig->field.variable.publishParameters);
28890 }
28891}
28892
28893/*********************************************************/
28894/* PublishValues handling */
28895/*********************************************************/
28896
28897/* Compare two variants. Internally used for value change detection. */
28898#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
28899static UA_Boolean
28900valueChangedVariant(UA_Variant *oldValue, UA_Variant *newValue) {
28901 if(!oldValue || !newValue)
28902 return false;
28903
28904 size_t oldValueEncodingSize = UA_calcSizeBinary(oldValue, &UA_TYPES[UA_TYPES_VARIANT]);
28905 size_t newValueEncodingSize = UA_calcSizeBinary(newValue, &UA_TYPES[UA_TYPES_VARIANT]);
28906 if(oldValueEncodingSize == 0 || newValueEncodingSize == 0)
28907 return false;
28908
28909 if(oldValueEncodingSize != newValueEncodingSize)
28910 return true;
28911
28912 UA_ByteString oldValueEncoding = {0};
28913 UA_StatusCode res = UA_ByteString_allocBuffer(&oldValueEncoding, oldValueEncodingSize);
28914 if(res != UA_STATUSCODE_GOOD)
28915 return false;
28916
28917 UA_ByteString newValueEncoding = {0};
28918 res = UA_ByteString_allocBuffer(&newValueEncoding, newValueEncodingSize);
28919 if(res != UA_STATUSCODE_GOOD) {
28920 UA_ByteString_clear(&oldValueEncoding);
28921 return false;
28922 }
28923
28924 UA_Byte *bufPosOldValue = oldValueEncoding.data;
28925 const UA_Byte *bufEndOldValue = &oldValueEncoding.data[oldValueEncoding.length];
28926 UA_Byte *bufPosNewValue = newValueEncoding.data;
28927 const UA_Byte *bufEndNewValue = &newValueEncoding.data[newValueEncoding.length];
28928
28929 UA_Boolean compareResult = false; /* default */
28930
28931 res = UA_encodeBinaryInternal(oldValue, &UA_TYPES[UA_TYPES_VARIANT],
28932 &bufPosOldValue, &bufEndOldValue, NULL, NULL);
28933 if(res != UA_STATUSCODE_GOOD)
28934 goto cleanup;
28935
28936 res = UA_encodeBinaryInternal(newValue, &UA_TYPES[UA_TYPES_VARIANT],
28937 &bufPosNewValue, &bufEndNewValue, NULL, NULL);
28938 if(res != UA_STATUSCODE_GOOD)
28939 goto cleanup;
28940
28941 oldValueEncoding.length = (uintptr_t)bufPosOldValue - (uintptr_t)oldValueEncoding.data;
28942 newValueEncoding.length = (uintptr_t)bufPosNewValue - (uintptr_t)newValueEncoding.data;
28943 compareResult = !UA_ByteString_equal(&oldValueEncoding, &newValueEncoding);
28944
28945 cleanup:
28946 UA_ByteString_clear(&oldValueEncoding);
28947 UA_ByteString_clear(&newValueEncoding);
28948 return compareResult;
28949}
28950#endif
28951
28952/* Obtain the latest value for a specific DataSetField. This method is currently
28953 * called inside the DataSetMessage generation process. */
28954static void
28955UA_PubSubDataSetField_sampleValue(UA_Server *server, UA_DataSetField *field,
28956 UA_DataValue *value) {
28957 UA_PublishedVariableDataType *params = &field->config.field.variable.publishParameters;
28958
28959 /* Read the value */
28960 if(field->config.field.variable.rtValueSource.rtInformationModelNode) {
28961 const UA_VariableNode *rtNode = (const UA_VariableNode *)
28962 UA_NODESTORE_GET(server, &params->publishedVariable);
28963 *value = **rtNode->valueBackend.backend.external.value;
28964 value->value.storageType = UA_VARIANT_DATA_NODELETE;
28965 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
28966 } else if(field->config.field.variable.rtValueSource.rtFieldSourceEnabled == UA_FALSE){
28967 UA_ReadValueId rvid;
28968 UA_ReadValueId_init(&rvid);
28969 rvid.nodeId = params->publishedVariable;
28970 rvid.attributeId = params->attributeId;
28971 rvid.indexRange = params->indexRange;
28972 *value = UA_Server_read(server, &rvid, UA_TIMESTAMPSTORETURN_BOTH);
28973 } else {
28974 *value = **field->config.field.variable.rtValueSource.staticValueSource;
28975 value->value.storageType = UA_VARIANT_DATA_NODELETE;
28976 }
28977}
28978
28979static UA_StatusCode
28980UA_PubSubDataSetWriter_generateKeyFrameMessage(UA_Server *server,
28981 UA_DataSetMessage *dataSetMessage,
28982 UA_DataSetWriter *dataSetWriter) {
28983 UA_PublishedDataSet *currentDataSet =
28984 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
28985 if(!currentDataSet)
28986 return UA_STATUSCODE_BADNOTFOUND;
28987
28988 /* Prepare DataSetMessageContent */
28989 dataSetMessage->header.dataSetMessageValid = true;
28990 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
28991 dataSetMessage->data.keyFrameData.fieldCount = currentDataSet->fieldSize;
28992 dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
28993 UA_Array_new(currentDataSet->fieldSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
28994 if(!dataSetMessage->data.keyFrameData.dataSetFields)
28995 return UA_STATUSCODE_BADOUTOFMEMORY;
28996
28997#ifdef UA_ENABLE_JSON_ENCODING
28998 dataSetMessage->data.keyFrameData.fieldNames = (UA_String *)
28999 UA_Array_new(currentDataSet->fieldSize, &UA_TYPES[UA_TYPES_STRING]);
29000 if(!dataSetMessage->data.keyFrameData.fieldNames) {
29001 UA_DataSetMessage_clear(dataSetMessage);
29002 return UA_STATUSCODE_BADOUTOFMEMORY;
29003 }
29004#endif
29005
29006 /* Loop over the fields */
29007 size_t counter = 0;
29008 UA_DataSetField *dsf;
29009 TAILQ_FOREACH(dsf, &currentDataSet->fields, listEntry) {
29010#ifdef UA_ENABLE_JSON_ENCODING
29011 /* Set the field name alias */
29012 UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
29013 &dataSetMessage->data.keyFrameData.fieldNames[counter]);
29014#endif
29015
29016 /* Sample the value */
29017 UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
29018 UA_PubSubDataSetField_sampleValue(server, dsf, dfv);
29019
29020 /* Deactivate statuscode? */
29021 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29022 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
29023 dfv->hasStatus = false;
29024
29025 /* Deactivate timestamps */
29026 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29027 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
29028 dfv->hasSourceTimestamp = false;
29029 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29030 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
29031 dfv->hasSourcePicoseconds = false;
29032 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29033 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
29034 dfv->hasServerTimestamp = false;
29035 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29036 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
29037 dfv->hasServerPicoseconds = false;
29038
29039#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
29040 /* Update lastValue store */
29041 UA_DataValue_clear(&dataSetWriter->lastSamples[counter].value);
29042 UA_DataValue_copy(dfv, &dataSetWriter->lastSamples[counter].value);
29043#endif
29044
29045 counter++;
29046 }
29047 return UA_STATUSCODE_GOOD;
29048}
29049
29050#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
29051static UA_StatusCode
29052UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_Server *server,
29053 UA_DataSetMessage *dataSetMessage,
29054 UA_DataSetWriter *dataSetWriter) {
29055 UA_PublishedDataSet *currentDataSet =
29056 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29057 if(!currentDataSet)
29058 return UA_STATUSCODE_BADNOTFOUND;
29059
29060 /* Prepare DataSetMessageContent */
29061 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
29062 dataSetMessage->header.dataSetMessageValid = true;
29063 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATADELTAFRAME;
29064 if(currentDataSet->fieldSize == 0)
29065 return UA_STATUSCODE_GOOD;
29066
29067 UA_DataSetField *dsf;
29068 size_t counter = 0;
29069 TAILQ_FOREACH(dsf, &currentDataSet->fields, listEntry) {
29070 /* Sample the value */
29071 UA_DataValue value;
29072 UA_DataValue_init(&value);
29073 UA_PubSubDataSetField_sampleValue(server, dsf, &value);
29074
29075 /* Check if the value has changed */
29076 UA_DataSetWriterSample *ls = &dataSetWriter->lastSamples[counter];
29077 if(valueChangedVariant(&ls->value.value, &value.value)) {
29078 /* increase fieldCount for current delta message */
29079 dataSetMessage->data.deltaFrameData.fieldCount++;
29080 ls->valueChanged = true;
29081
29082 /* Update last stored sample */
29083 UA_DataValue_clear(&ls->value);
29084 ls->value = value;
29085 } else {
29086 UA_DataValue_clear(&value);
29087 ls->valueChanged = false;
29088 }
29089
29090 counter++;
29091 }
29092
29093 /* Allocate DeltaFrameFields */
29094 UA_DataSetMessage_DeltaFrameField *deltaFields = (UA_DataSetMessage_DeltaFrameField *)
29095 UA_calloc(dataSetMessage->data.deltaFrameData.fieldCount,
29096 sizeof(UA_DataSetMessage_DeltaFrameField));
29097 if(!deltaFields)
29098 return UA_STATUSCODE_BADOUTOFMEMORY;
29099
29100 dataSetMessage->data.deltaFrameData.deltaFrameFields = deltaFields;
29101 size_t currentDeltaField = 0;
29102 for(size_t i = 0; i < currentDataSet->fieldSize; i++) {
29103 if(!dataSetWriter->lastSamples[i].valueChanged)
29104 continue;
29105
29106 UA_DataSetMessage_DeltaFrameField *dff = &deltaFields[currentDeltaField];
29107
29108 dff->fieldIndex = (UA_UInt16) i;
29109 UA_DataValue_copy(&dataSetWriter->lastSamples[i].value, &dff->fieldValue);
29110 dataSetWriter->lastSamples[i].valueChanged = false;
29111
29112 /* Deactivate statuscode? */
29113 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29114 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
29115 dff->fieldValue.hasStatus = false;
29116
29117 /* Deactivate timestamps? */
29118 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29119 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
29120 dff->fieldValue.hasSourceTimestamp = false;
29121 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29122 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
29123 dff->fieldValue.hasServerPicoseconds = false;
29124 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29125 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
29126 dff->fieldValue.hasServerTimestamp = false;
29127 if(((u64)dataSetWriter->config.dataSetFieldContentMask &
29128 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
29129 dff->fieldValue.hasServerPicoseconds = false;
29130
29131 currentDeltaField++;
29132 }
29133 return UA_STATUSCODE_GOOD;
29134}
29135#endif
29136
29137/* Generate a DataSetMessage for the given writer. */
29138UA_StatusCode
29139UA_DataSetWriter_generateDataSetMessage(UA_Server *server,
29140 UA_DataSetMessage *dataSetMessage,
29141 UA_DataSetWriter *dataSetWriter) {
29142 UA_PublishedDataSet *currentDataSet =
29143 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29144 if(!currentDataSet)
29145 return UA_STATUSCODE_BADNOTFOUND;
29146
29147 /* Reset the message */
29148 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
29149
29150 /* The configuration Flags are included
29151 * inside the std. defined UA_UadpDataSetWriterMessageDataType */
29152 UA_UadpDataSetWriterMessageDataType defaultUadpConfiguration;
29153 UA_UadpDataSetWriterMessageDataType *dsm = NULL;
29154 UA_JsonDataSetWriterMessageDataType *jsonDsm = NULL;
29155 const UA_ExtensionObject *ms = &dataSetWriter->config.messageSettings;
29156 if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
29157 ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
29158 ms->content.decoded.type == &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE]) {
29159 dsm = (UA_UadpDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is UADP */
29160 } else if((ms->encoding == UA_EXTENSIONOBJECT_DECODED ||
29161 ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
29162 ms->content.decoded.type == &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE]) {
29163 jsonDsm = (UA_JsonDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is JSON */
29164 } else {
29165 /* Create default flag configuration if no
29166 * UadpDataSetWriterMessageDataType was passed in */
29167 memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetWriterMessageDataType));
29168 defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
29169 ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
29170 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
29171 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
29172 dsm = &defaultUadpConfiguration; /* type is UADP */
29173 }
29174
29175 /* The field encoding depends on the flags inside the writer config. */
29176 if(dataSetWriter->config.dataSetFieldContentMask &
29177 (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
29178 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
29179 } else if((u64)dataSetWriter->config.dataSetFieldContentMask &
29180 ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP |
29181 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS |
29182 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS |
29183 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) {
29184 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
29185 } else {
29186 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
29187 }
29188
29189 if(dsm) {
29190 /* Sanity-test the configuration */
29191 if(dsm->networkMessageNumber != 0 ||
29192 dsm->dataSetOffset != 0 ||
29193 dsm->configuredSize != 0) {
29194 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29195 "Static DSM configuration not supported. Using defaults");
29196 dsm->networkMessageNumber = 0;
29197 dsm->dataSetOffset = 0;
29198 dsm->configuredSize = 0;
29199 }
29200
29201 /* Std: 'The DataSetMessageContentMask defines the flags for the content
29202 * of the DataSetMessage header.' */
29203 if((u64)dsm->dataSetMessageContentMask &
29204 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
29205 dataSetMessage->header.configVersionMajorVersionEnabled = true;
29206 dataSetMessage->header.configVersionMajorVersion =
29207 currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
29208 }
29209 if((u64)dsm->dataSetMessageContentMask &
29210 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
29211 dataSetMessage->header.configVersionMinorVersionEnabled = true;
29212 dataSetMessage->header.configVersionMinorVersion =
29213 currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
29214 }
29215
29216 if((u64)dsm->dataSetMessageContentMask &
29217 (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
29218 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
29219 dataSetMessage->header.dataSetMessageSequenceNr =
29220 dataSetWriter->actualDataSetMessageSequenceCount;
29221 }
29222
29223 if((u64)dsm->dataSetMessageContentMask &
29224 (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
29225 dataSetMessage->header.timestampEnabled = true;
29226 dataSetMessage->header.timestamp = UA_DateTime_now();
29227 }
29228
29229 /* TODO: Picoseconds resolution not supported atm */
29230 if((u64)dsm->dataSetMessageContentMask &
29231 (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
29232 dataSetMessage->header.picoSecondsIncluded = false;
29233 }
29234
29235 /* TODO: Statuscode not supported yet */
29236 if((u64)dsm->dataSetMessageContentMask &
29237 (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
29238 dataSetMessage->header.statusEnabled = true;
29239 }
29240 } else if(jsonDsm) {
29241 if((u64)jsonDsm->dataSetMessageContentMask &
29242 (u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
29243 dataSetMessage->header.configVersionMajorVersionEnabled = true;
29244 dataSetMessage->header.configVersionMajorVersion =
29245 currentDataSet->dataSetMetaData.configurationVersion.majorVersion;
29246 }
29247 if((u64)jsonDsm->dataSetMessageContentMask &
29248 (u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) {
29249 dataSetMessage->header.configVersionMinorVersionEnabled = true;
29250 dataSetMessage->header.configVersionMinorVersion =
29251 currentDataSet->dataSetMetaData.configurationVersion.minorVersion;
29252 }
29253
29254 if((u64)jsonDsm->dataSetMessageContentMask &
29255 (u64)UA_JSONDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
29256 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
29257 dataSetMessage->header.dataSetMessageSequenceNr =
29258 dataSetWriter->actualDataSetMessageSequenceCount;
29259 }
29260
29261 if((u64)jsonDsm->dataSetMessageContentMask &
29262 (u64)UA_JSONDATASETMESSAGECONTENTMASK_TIMESTAMP) {
29263 dataSetMessage->header.timestampEnabled = true;
29264 dataSetMessage->header.timestamp = UA_DateTime_now();
29265 }
29266
29267 /* TODO: Statuscode not supported yet */
29268 if((u64)jsonDsm->dataSetMessageContentMask &
29269 (u64)UA_JSONDATASETMESSAGECONTENTMASK_STATUS) {
29270 dataSetMessage->header.statusEnabled = true;
29271 }
29272 }
29273
29274 /* Set the sequence count. Automatically rolls over to zero */
29275 dataSetWriter->actualDataSetMessageSequenceCount++;
29276
29277 /* JSON does not differ between deltaframes and keyframes, only keyframes
29278 * are currently used. */
29279 if(dsm) {
29280#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
29281 /* Check if the PublishedDataSet version has changed -> if yes flush the
29282 * lastValue store and send a KeyFrame */
29283 if(dataSetWriter->connectedDataSetVersion.majorVersion !=
29284 currentDataSet->dataSetMetaData.configurationVersion.majorVersion ||
29285 dataSetWriter->connectedDataSetVersion.minorVersion !=
29286 currentDataSet->dataSetMetaData.configurationVersion.minorVersion) {
29287 /* Remove old samples */
29288 for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++)
29289 UA_DataValue_clear(&dataSetWriter->lastSamples[i].value);
29290
29291 /* Realloc PDS dependent memory */
29292 dataSetWriter->lastSamplesCount = currentDataSet->fieldSize;
29293 UA_DataSetWriterSample *newSamplesArray = (UA_DataSetWriterSample * )
29294 UA_realloc(dataSetWriter->lastSamples,
29295 sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount);
29296 if(!newSamplesArray)
29297 return UA_STATUSCODE_BADOUTOFMEMORY;
29298 dataSetWriter->lastSamples = newSamplesArray;
29299 memset(dataSetWriter->lastSamples, 0,
29300 sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount);
29301
29302 dataSetWriter->connectedDataSetVersion =
29303 currentDataSet->dataSetMetaData.configurationVersion;
29304 UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
29305 dataSetWriter);
29306 dataSetWriter->deltaFrameCounter = 0;
29307 return UA_STATUSCODE_GOOD;
29308 }
29309
29310 /* The standard defines: if a PDS contains only one fields no delta messages
29311 * should be generated because they need more memory than a keyframe with 1
29312 * field. */
29313 if(currentDataSet->fieldSize > 1 && dataSetWriter->deltaFrameCounter > 0 &&
29314 dataSetWriter->deltaFrameCounter <= dataSetWriter->config.keyFrameCount) {
29315 UA_PubSubDataSetWriter_generateDeltaFrameMessage(server, dataSetMessage,
29316 dataSetWriter);
29317 dataSetWriter->deltaFrameCounter++;
29318 return UA_STATUSCODE_GOOD;
29319 }
29320
29321 dataSetWriter->deltaFrameCounter = 1;
29322#endif
29323 }
29324
29325 return UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage,
29326 dataSetWriter);
29327}
29328
29329#endif /* UA_ENABLE_PUBSUB */
29330
29331/**** amalgamated original file "/src/pubsub/ua_pubsub_writergroup.c" ****/
29332
29333/* This Source Code Form is subject to the terms of the Mozilla Public
29334 * License, v. 2.0. If a copy of the MPL was not distributed with this
29335 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
29336 *
29337 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
29338 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
29339 * Copyright (c) 2019 Kalycito Infotech Private Limited
29340 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
29341 * Copyright (c) 2020 Thomas Fischer, Siemens AG
29342 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
29343 */
29344
29345
29346#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
29347
29348
29349#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29350#endif
29351
29352#define UA_MAX_STACKBUF 128 /* Max size of network messages on the stack */
29353
29354static void
29355UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup);
29356
29357static UA_StatusCode
29358generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
29359 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
29360 UA_ExtensionObject *messageSettings,
29361 UA_ExtensionObject *transportSettings,
29362 UA_NetworkMessage *networkMessage);
29363
29364UA_StatusCode
29365UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection,
29366 const UA_WriterGroupConfig *writerGroupConfig,
29367 UA_NodeId *writerGroupIdentifier) {
29368 if(!writerGroupConfig)
29369 return UA_STATUSCODE_BADINVALIDARGUMENT;
29370
29371 /* Search the connection by the given connectionIdentifier */
29372 UA_PubSubConnection *currentConnectionContext =
29373 UA_PubSubConnection_findConnectionbyId(server, connection);
29374 if(!currentConnectionContext)
29375 return UA_STATUSCODE_BADNOTFOUND;
29376
29377 if(currentConnectionContext->configurationFrozen){
29378 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29379 "Adding WriterGroup failed. PubSubConnection is frozen.");
29380 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29381 }
29382
29383 /* Validate messageSettings type */
29384 const UA_ExtensionObject *ms = &writerGroupConfig->messageSettings;
29385 if(ms->content.decoded.type) {
29386 if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_JSON &&
29387 (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
29388 ms->content.decoded.type != &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE])) {
29389 return UA_STATUSCODE_BADTYPEMISMATCH;
29390 }
29391
29392 if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_UADP &&
29393 (ms->encoding != UA_EXTENSIONOBJECT_DECODED ||
29394 ms->content.decoded.type != &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])) {
29395 return UA_STATUSCODE_BADTYPEMISMATCH;
29396 }
29397 }
29398
29399 /* Allocate new WriterGroup */
29400 UA_WriterGroup *newWriterGroup = (UA_WriterGroup*)UA_calloc(1, sizeof(UA_WriterGroup));
29401 if(!newWriterGroup)
29402 return UA_STATUSCODE_BADOUTOFMEMORY;
29403
29404 newWriterGroup->componentType = UA_PUBSUB_COMPONENT_WRITERGROUP;
29405 newWriterGroup->linkedConnection = currentConnectionContext;
29406
29407 /* Deep copy of the config */
29408 UA_WriterGroupConfig *newConfig = &newWriterGroup->config;
29409 UA_StatusCode res = UA_WriterGroupConfig_copy(writerGroupConfig, newConfig);
29410 if(res != UA_STATUSCODE_GOOD) {
29411 UA_free(newWriterGroup);
29412 return res;
29413 }
29414
29415 /* Create the datatype value if not present */
29416 if(!newConfig->messageSettings.content.decoded.type) {
29417 UA_UadpWriterGroupMessageDataType *wgm = UA_UadpWriterGroupMessageDataType_new();
29418 newConfig->messageSettings.content.decoded.data = wgm;
29419 newConfig->messageSettings.content.decoded.type =
29420 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
29421 newConfig->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
29422 }
29423
29424 /* Attach to the connection */
29425 LIST_INSERT_HEAD(&currentConnectionContext->writerGroups, newWriterGroup, listEntry);
29426 currentConnectionContext->writerGroupsSize++;
29427
29428 /* Add representation / create unique identifier */
29429#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29430 res = addWriterGroupRepresentation(server, newWriterGroup);
29431#else
29432 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
29433 &newWriterGroup->identifier);
29434#endif
29435 if(writerGroupIdentifier)
29436 UA_NodeId_copy(&newWriterGroup->identifier, writerGroupIdentifier);
29437 return res;
29438}
29439
29440UA_StatusCode
29441UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup) {
29442 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29443 if(!wg)
29444 return UA_STATUSCODE_BADNOTFOUND;
29445
29446 if(wg->configurationFrozen) {
29447 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29448 "Delete WriterGroup failed. WriterGroup is frozen.");
29449 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29450 }
29451
29452 UA_PubSubConnection *connection = wg->linkedConnection;
29453 if(!connection)
29454 return UA_STATUSCODE_BADNOTFOUND;
29455
29456 if(connection->configurationFrozen) {
29457 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29458 "Delete WriterGroup failed. PubSubConnection is frozen.");
29459 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29460 }
29461
29462 if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) {
29463 /* Unregister the publish callback */
29464 if(wg->config.pubsubManagerCallback.removeCustomCallback)
29465 wg->config.pubsubManagerCallback.
29466 removeCustomCallback(server, wg->identifier, wg->publishCallbackId);
29467 else
29468 UA_PubSubManager_removeRepeatedPubSubCallback(server, wg->publishCallbackId);
29469
29470 }
29471
29472 UA_DataSetWriter *dsw, *dsw_tmp;
29473 LIST_FOREACH_SAFE(dsw, &wg->writers, listEntry, dsw_tmp) {
29474 UA_DataSetWriter_remove(server, wg, dsw);
29475 }
29476
29477 connection->writerGroupsSize--;
29478#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
29479 removeGroupRepresentation(server, wg);
29480#endif
29481
29482 UA_WriterGroup_clear(server, wg);
29483 LIST_REMOVE(wg, listEntry);
29484 UA_free(wg);
29485 return UA_STATUSCODE_GOOD;
29486}
29487
29488UA_StatusCode
29489UA_Server_freezeWriterGroupConfiguration(UA_Server *server,
29490 const UA_NodeId writerGroup) {
29491 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29492 if(!wg)
29493 return UA_STATUSCODE_BADNOTFOUND;
29494
29495 /* PubSubConnection freezeCounter++ */
29496 UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
29497 pubSubConnection->configurationFreezeCounter++;
29498 pubSubConnection->configurationFrozen = true;
29499
29500 /* WriterGroup freeze */
29501 wg->configurationFrozen = true;
29502
29503 /* DataSetWriter freeze */
29504 UA_DataSetWriter *dataSetWriter;
29505 LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
29506 dataSetWriter->configurationFrozen = true;
29507 /* PublishedDataSet freezeCounter++ */
29508 UA_PublishedDataSet *publishedDataSet =
29509 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29510 publishedDataSet->configurationFreezeCounter++;
29511 publishedDataSet->configurationFrozen = true;
29512 /* DataSetFields freeze */
29513 UA_DataSetField *dataSetField;
29514 TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry) {
29515 dataSetField->configurationFrozen = true;
29516 }
29517 }
29518
29519 if(wg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
29520 return UA_STATUSCODE_GOOD;
29521
29522 /* Freeze the RT writer configuration */
29523 size_t dsmCount = 0;
29524 if(wg->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP) {
29525 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29526 "PubSub-RT configuration fail: Non-RT capable encoding.");
29527 return UA_STATUSCODE_BADNOTSUPPORTED;
29528 }
29529
29530 //TODO Clarify: should we only allow = maxEncapsulatedDataSetMessageCount == 1 with RT?
29531 //TODO Clarify: Behaviour if the finale size is more than MTU
29532
29533 /* Generate data set messages */
29534 UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount);
29535 UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount);
29536 UA_StatusCode res = UA_STATUSCODE_GOOD;
29537 UA_DataSetWriter *dsw;
29538 LIST_FOREACH(dsw, &wg->writers, listEntry) {
29539 /* Find the dataset */
29540 UA_PublishedDataSet *pds =
29541 UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
29542 if(!pds) {
29543 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29544 "PubSub Publish: PublishedDataSet not found");
29545 continue;
29546 }
29547 if(pds->promotedFieldsCount > 0) {
29548 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29549 "PubSub-RT configuration fail: PDS contains promoted fields.");
29550 return UA_STATUSCODE_BADNOTSUPPORTED;
29551 }
29552
29553 /* Test the DataSetFields */
29554 UA_DataSetField *dsf;
29555 TAILQ_FOREACH(dsf, &pds->fields, listEntry) {
29556 const UA_VariableNode *rtNode = (const UA_VariableNode *)
29557 UA_NODESTORE_GET(server, &dsf->config.field.variable.publishParameters.publishedVariable);
29558 if(rtNode != NULL && rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
29559 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29560 "PubSub-RT configuration fail: PDS contains field without external data source.");
29561 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
29562 return UA_STATUSCODE_BADNOTSUPPORTED;
29563 }
29564 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
29565 if((UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
29566 UA_NodeId_equal(&dsf->fieldMetaData.dataType,
29567 &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
29568 dsf->fieldMetaData.maxStringLength == 0) {
29569 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29570 "PubSub-RT configuration fail: "
29571 "PDS contains String/ByteString with dynamic length.");
29572 return UA_STATUSCODE_BADNOTSUPPORTED;
29573 } else if(!UA_DataType_isNumeric(UA_findDataType(&dsf->fieldMetaData.dataType)) &&
29574 !UA_NodeId_equal(&dsf->fieldMetaData.dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
29575 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29576 "PubSub-RT configuration fail: "
29577 "PDS contains variable with dynamic size.");
29578 return UA_STATUSCODE_BADNOTSUPPORTED;
29579 }
29580 }
29581
29582 /* Generate the DSM */
29583 res = UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
29584 if(res != UA_STATUSCODE_GOOD) {
29585 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29586 "PubSub RT Offset calculation: DataSetMessage buffering failed");
29587 continue;
29588 }
29589
29590 dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
29591 dsmCount++;
29592 }
29593
29594 /* Define variables here for goto */
29595 size_t msgSize;
29596 UA_ByteString buf;
29597 UA_NetworkMessage networkMessage;
29598 const UA_Byte *bufEnd;
29599 UA_Byte *bufPos;
29600
29601 if(res != UA_STATUSCODE_GOOD)
29602 goto cleanup_dsm;
29603
29604 memset(&networkMessage, 0, sizeof(networkMessage));
29605 res = generateNetworkMessage(pubSubConnection, wg, dsmStore, dsWriterIds,
29606 (UA_Byte) dsmCount, &wg->config.messageSettings,
29607 &wg->config.transportSettings, &networkMessage);
29608 if(res != UA_STATUSCODE_GOOD)
29609 goto cleanup_dsm;
29610
29611 /* Generate the offset-buffer (done inside calcSizeBinary) */
29612 memset(&wg->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
29613 UA_NetworkMessage_calcSizeBinary(&networkMessage, &wg->bufferedMessage);
29614
29615 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
29616 msgSize = UA_NetworkMessage_calcSizeBinary(&networkMessage, NULL);
29617 res = UA_ByteString_allocBuffer(&buf, msgSize);
29618 if(res != UA_STATUSCODE_GOOD)
29619 goto cleanup;
29620 wg->bufferedMessage.buffer = buf;
29621
29622 /* Encode the NetworkMessage */
29623 bufEnd = &wg->bufferedMessage.buffer.data[wg->bufferedMessage.buffer.length];
29624 bufPos = wg->bufferedMessage.buffer.data;
29625 UA_NetworkMessage_encodeBinary(&networkMessage, &bufPos, bufEnd, NULL);
29626
29627 cleanup:
29628 UA_free(networkMessage.payload.dataSetPayload.sizes);
29629
29630 /* Clean up DSM */
29631 cleanup_dsm:
29632 for(size_t i = 0; i < dsmCount; i++){
29633 UA_free(dsmStore[i].data.keyFrameData.dataSetFields);
29634#ifdef UA_ENABLE_JSON_ENCODING
29635 UA_Array_delete(dsmStore[i].data.keyFrameData.fieldNames,
29636 dsmStore[i].data.keyFrameData.fieldCount,
29637 &UA_TYPES[UA_TYPES_STRING]);
29638#endif
29639 }
29640
29641 return res;
29642}
29643
29644UA_StatusCode
29645UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server,
29646 const UA_NodeId writerGroup) {
29647 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29648 if(!wg)
29649 return UA_STATUSCODE_BADNOTFOUND;
29650 //if(wg->config.rtLevel == UA_PUBSUB_RT_NONE){
29651 // UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29652 // "PubSub configuration freeze without RT configuration has no effect.");
29653 // return UA_STATUSCODE_BADCONFIGURATIONERROR;
29654 //}
29655 //PubSubConnection freezeCounter--
29656 UA_PubSubConnection *pubSubConnection = wg->linkedConnection;
29657 pubSubConnection->configurationFreezeCounter--;
29658 if(pubSubConnection->configurationFreezeCounter == 0){
29659 pubSubConnection->configurationFrozen = UA_FALSE;
29660 }
29661 //WriterGroup unfreeze
29662 wg->configurationFrozen = UA_FALSE;
29663 //DataSetWriter unfreeze
29664 UA_DataSetWriter *dataSetWriter;
29665 LIST_FOREACH(dataSetWriter, &wg->writers, listEntry) {
29666 UA_PublishedDataSet *publishedDataSet =
29667 UA_PublishedDataSet_findPDSbyId(server, dataSetWriter->connectedDataSet);
29668 //PublishedDataSet freezeCounter--
29669 publishedDataSet->configurationFreezeCounter--;
29670 if(publishedDataSet->configurationFreezeCounter == 0){
29671 publishedDataSet->configurationFrozen = UA_FALSE;
29672 UA_DataSetField *dataSetField;
29673 TAILQ_FOREACH(dataSetField, &publishedDataSet->fields, listEntry){
29674 dataSetField->configurationFrozen = UA_FALSE;
29675 }
29676 }
29677 dataSetWriter->configurationFrozen = UA_FALSE;
29678 }
29679
29680 UA_NetworkMessageOffsetBuffer_clear(&wg->bufferedMessage);
29681
29682 return UA_STATUSCODE_GOOD;
29683}
29684
29685UA_StatusCode
29686UA_Server_setWriterGroupOperational(UA_Server *server,
29687 const UA_NodeId writerGroup) {
29688 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29689 if(!wg)
29690 return UA_STATUSCODE_BADNOTFOUND;
29691 return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, wg);
29692}
29693
29694UA_StatusCode
29695UA_Server_setWriterGroupDisabled(UA_Server *server,
29696 const UA_NodeId writerGroup) {
29697 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29698 if(!wg)
29699 return UA_STATUSCODE_BADNOTFOUND;
29700 return UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, wg);
29701}
29702
29703UA_StatusCode
29704UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src,
29705 UA_WriterGroupConfig *dst){
29706 UA_StatusCode res = UA_STATUSCODE_GOOD;
29707 memcpy(dst, src, sizeof(UA_WriterGroupConfig));
29708 res |= UA_String_copy(&src->name, &dst->name);
29709 res |= UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
29710 res |= UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
29711 if(src->groupPropertiesSize > 0) {
29712 dst->groupProperties = (UA_KeyValuePair*)
29713 UA_calloc(src->groupPropertiesSize, sizeof(UA_KeyValuePair));
29714 if(!dst->groupProperties)
29715 return UA_STATUSCODE_BADOUTOFMEMORY;
29716 for(size_t i = 0; i < src->groupPropertiesSize; i++) {
29717 res |= UA_KeyValuePair_copy(&src->groupProperties[i], &dst->groupProperties[i]);
29718 }
29719 }
29720 if(res != UA_STATUSCODE_GOOD)
29721 UA_WriterGroupConfig_clear(dst);
29722 return res;
29723}
29724
29725UA_StatusCode
29726UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup,
29727 UA_WriterGroupConfig *config) {
29728 if(!config)
29729 return UA_STATUSCODE_BADINVALIDARGUMENT;
29730 UA_WriterGroup *currentWG = UA_WriterGroup_findWGbyId(server, writerGroup);
29731 if(!currentWG)
29732 return UA_STATUSCODE_BADNOTFOUND;
29733 return UA_WriterGroupConfig_copy(&currentWG->config, config);
29734}
29735
29736UA_StatusCode
29737UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier,
29738 const UA_WriterGroupConfig *config){
29739 if(!config)
29740 return UA_STATUSCODE_BADINVALIDARGUMENT;
29741
29742 UA_WriterGroup *currentWriterGroup =
29743 UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
29744 if(!currentWriterGroup)
29745 return UA_STATUSCODE_BADNOTFOUND;
29746
29747 if(currentWriterGroup->configurationFrozen){
29748 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29749 "Modify WriterGroup failed. WriterGroup is frozen.");
29750 return UA_STATUSCODE_BADCONFIGURATIONERROR;
29751 }
29752
29753 //The update functionality will be extended during the next PubSub batches.
29754 //Currently is only a change of the publishing interval possible.
29755 if(currentWriterGroup->config.maxEncapsulatedDataSetMessageCount != config->maxEncapsulatedDataSetMessageCount) {
29756 currentWriterGroup->config.maxEncapsulatedDataSetMessageCount = config->maxEncapsulatedDataSetMessageCount;
29757 if(currentWriterGroup->config.messageSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
29758 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29759 "MaxEncapsulatedDataSetMessag need enabled 'PayloadHeader' within the message settings.");
29760 }
29761 }
29762
29763 if(currentWriterGroup->config.publishingInterval != config->publishingInterval) {
29764 if(currentWriterGroup->config.rtLevel == UA_PUBSUB_RT_NONE &&
29765 currentWriterGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
29766 if(currentWriterGroup->config.pubsubManagerCallback.removeCustomCallback)
29767 currentWriterGroup->config.pubsubManagerCallback.
29768 removeCustomCallback(server, currentWriterGroup->identifier,
29769 currentWriterGroup->publishCallbackId);
29770 else
29771 UA_PubSubManager_removeRepeatedPubSubCallback(server, currentWriterGroup->publishCallbackId);
29772
29773 currentWriterGroup->config.publishingInterval = config->publishingInterval;
29774 UA_WriterGroup_addPublishCallback(server, currentWriterGroup);
29775 } else {
29776 currentWriterGroup->config.publishingInterval = config->publishingInterval;
29777 }
29778 }
29779
29780 if(currentWriterGroup->config.priority != config->priority) {
29781 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29782 "No or unsupported WriterGroup update.");
29783 }
29784
29785 return UA_STATUSCODE_GOOD;
29786}
29787
29788UA_StatusCode
29789UA_Server_WriterGroup_getState(UA_Server *server, UA_NodeId writerGroupIdentifier,
29790 UA_PubSubState *state) {
29791 if((server == NULL) || (state == NULL))
29792 return UA_STATUSCODE_BADINVALIDARGUMENT;
29793 UA_WriterGroup *currentWriterGroup =
29794 UA_WriterGroup_findWGbyId(server, writerGroupIdentifier);
29795 if(currentWriterGroup == NULL)
29796 return UA_STATUSCODE_BADNOTFOUND;
29797 *state = currentWriterGroup->state;
29798 return UA_STATUSCODE_GOOD;
29799}
29800
29801UA_WriterGroup *
29802UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier) {
29803 UA_PubSubConnection *tmpConnection;
29804 TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) {
29805 UA_WriterGroup *tmpWriterGroup;
29806 LIST_FOREACH(tmpWriterGroup, &tmpConnection->writerGroups, listEntry) {
29807 if(UA_NodeId_equal(&identifier, &tmpWriterGroup->identifier))
29808 return tmpWriterGroup;
29809 }
29810 }
29811 return NULL;
29812}
29813
29814#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29815UA_StatusCode
29816UA_Server_setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup,
29817 UA_UInt32 securityTokenId,
29818 const UA_ByteString signingKey,
29819 const UA_ByteString encryptingKey,
29820 const UA_ByteString keyNonce) {
29821 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup);
29822 if(!wg)
29823 return UA_STATUSCODE_BADNOTFOUND;
29824
29825 if(!wg->config.securityPolicy) {
29826 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29827 "No SecurityPolicy configured for the WriterGroup");
29828 return UA_STATUSCODE_BADINTERNALERROR;
29829 }
29830
29831 if(securityTokenId != wg->securityTokenId) {
29832 wg->securityTokenId = securityTokenId;
29833 wg->nonceSequenceNumber = 1;
29834 }
29835
29836 /* Create a new context */
29837 if(!wg->securityPolicyContext) {
29838 return wg->config.securityPolicy->
29839 newContext(wg->config.securityPolicy->policyContext,
29840 &signingKey, &encryptingKey, &keyNonce,
29841 &wg->securityPolicyContext);
29842 }
29843
29844 /* Update the context */
29845 return wg->config.securityPolicy->
29846 setSecurityKeys(wg->securityPolicyContext, &signingKey, &encryptingKey, &keyNonce);
29847}
29848#endif
29849
29850void
29851UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig){
29852 UA_String_clear(&writerGroupConfig->name);
29853 UA_ExtensionObject_clear(&writerGroupConfig->transportSettings);
29854 UA_ExtensionObject_clear(&writerGroupConfig->messageSettings);
29855 UA_Array_delete(writerGroupConfig->groupProperties,
29856 writerGroupConfig->groupPropertiesSize,
29857 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
29858 writerGroupConfig->groupProperties = NULL;
29859}
29860
29861static void
29862UA_WriterGroup_clear(UA_Server *server, UA_WriterGroup *writerGroup) {
29863 UA_WriterGroupConfig_clear(&writerGroup->config);
29864 UA_NodeId_clear(&writerGroup->identifier);
29865
29866 /* Delete all writers */
29867 UA_DataSetWriter *dataSetWriter, *tmpDataSetWriter;
29868 LIST_FOREACH_SAFE(dataSetWriter, &writerGroup->writers, listEntry, tmpDataSetWriter){
29869 UA_Server_removeDataSetWriter(server, dataSetWriter->identifier);
29870 }
29871
29872 UA_NetworkMessageOffsetBuffer_clear(&writerGroup->bufferedMessage);
29873
29874#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29875 if(writerGroup->config.securityPolicy && writerGroup->securityPolicyContext) {
29876 writerGroup->config.securityPolicy->deleteContext(writerGroup->securityPolicyContext);
29877 writerGroup->securityPolicyContext = NULL;
29878 }
29879#endif
29880}
29881
29882UA_StatusCode
29883UA_WriterGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
29884 UA_WriterGroup *writerGroup) {
29885 UA_DataSetWriter *dataSetWriter;
29886 switch(state) {
29887 case UA_PUBSUBSTATE_DISABLED:
29888 switch (writerGroup->state){
29889 case UA_PUBSUBSTATE_DISABLED:
29890 return UA_STATUSCODE_GOOD;
29891 case UA_PUBSUBSTATE_PAUSED:
29892 break;
29893 case UA_PUBSUBSTATE_OPERATIONAL:
29894 if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
29895 writerGroup->config.pubsubManagerCallback.
29896 removeCustomCallback(server, writerGroup->identifier, writerGroup->publishCallbackId);
29897 else
29898 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29899
29900 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29901 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, dataSetWriter);
29902 }
29903 writerGroup->state = UA_PUBSUBSTATE_DISABLED;
29904 break;
29905 case UA_PUBSUBSTATE_ERROR:
29906 break;
29907 default:
29908 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29909 "Received unknown PubSub state!");
29910 }
29911 break;
29912 case UA_PUBSUBSTATE_PAUSED:
29913 switch (writerGroup->state) {
29914 case UA_PUBSUBSTATE_DISABLED:
29915 break;
29916 case UA_PUBSUBSTATE_PAUSED:
29917 return UA_STATUSCODE_GOOD;
29918 case UA_PUBSUBSTATE_OPERATIONAL:
29919 break;
29920 case UA_PUBSUBSTATE_ERROR:
29921 break;
29922 default:
29923 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29924 "Received unknown PubSub state!");
29925 }
29926 break;
29927 case UA_PUBSUBSTATE_OPERATIONAL:
29928 switch (writerGroup->state) {
29929 case UA_PUBSUBSTATE_DISABLED:
29930 writerGroup->state = UA_PUBSUBSTATE_OPERATIONAL;
29931 if(writerGroup->config.pubsubManagerCallback.removeCustomCallback)
29932 writerGroup->config.pubsubManagerCallback.
29933 removeCustomCallback(server, writerGroup->identifier,
29934 writerGroup->publishCallbackId);
29935 else
29936 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29937
29938 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29939 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL,
29940 dataSetWriter);
29941 }
29942 UA_WriterGroup_addPublishCallback(server, writerGroup);
29943 break;
29944 case UA_PUBSUBSTATE_PAUSED:
29945 break;
29946 case UA_PUBSUBSTATE_OPERATIONAL:
29947 return UA_STATUSCODE_GOOD;
29948 case UA_PUBSUBSTATE_ERROR:
29949 break;
29950 default:
29951 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29952 "Received unknown PubSub state!");
29953 }
29954 break;
29955 case UA_PUBSUBSTATE_ERROR: {
29956 switch (writerGroup->state){
29957 case UA_PUBSUBSTATE_DISABLED:
29958 break;
29959 case UA_PUBSUBSTATE_PAUSED:
29960 break;
29961 case UA_PUBSUBSTATE_OPERATIONAL:
29962 UA_PubSubManager_removeRepeatedPubSubCallback(server, writerGroup->publishCallbackId);
29963 LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){
29964 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetWriter);
29965 }
29966 break;
29967 case UA_PUBSUBSTATE_ERROR:
29968 return UA_STATUSCODE_GOOD;
29969 default:
29970 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29971 "Received unknown PubSub state!");
29972 }
29973 writerGroup->state = UA_PUBSUBSTATE_ERROR;
29974 /* TODO: WIP - example usage of pubsubStateChangeCallback -> inform
29975 * application about error state, reason param necessary */
29976 UA_ServerConfig *pConfig = UA_Server_getConfig(server);
29977 if(pConfig->pubSubConfig.stateChangeCallback != 0) {
29978 pConfig->pubSubConfig.
29979 stateChangeCallback(&writerGroup->identifier, UA_PUBSUBSTATE_ERROR,
29980 UA_STATUSCODE_BADINTERNALERROR);
29981 }
29982 break;
29983 }
29984 default:
29985 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
29986 "Received unknown PubSub state!");
29987 }
29988 return UA_STATUSCODE_GOOD;
29989}
29990
29991#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
29992static UA_StatusCode
29993encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm,
29994 UA_Byte *signStart, UA_Byte *encryptStart,
29995 UA_Byte *msgEnd) {
29996 UA_StatusCode rv;
29997 void *channelContext = wg->securityPolicyContext;
29998
29999 if(nm->securityHeader.networkMessageEncrypted) {
30000 /* Set the temporary MessageNonce in the SecurityPolicy */
30001 rv = wg->config.securityPolicy->setMessageNonce(channelContext,
30002 &nm->securityHeader.messageNonce);
30003 UA_CHECK_STATUS(rv, return rv);
30004
30005 /* The encryption is done in-place, no need to encode again */
30006 UA_ByteString toBeEncrypted =
30007 {(uintptr_t)msgEnd - (uintptr_t)encryptStart, encryptStart};
30008 rv = wg->config.securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm.
30009 encrypt(channelContext, &toBeEncrypted);
30010 UA_CHECK_STATUS(rv, return rv);
30011 }
30012
30013 if(nm->securityHeader.networkMessageSigned) {
30014 UA_ByteString toBeSigned = {(uintptr_t)msgEnd - (uintptr_t)signStart,
30015 signStart};
30016
30017 size_t sigSize = wg->config.securityPolicy->symmetricModule.cryptoModule.
30018 signatureAlgorithm.getLocalSignatureSize(channelContext);
30019 UA_ByteString signature = {sigSize, msgEnd};
30020
30021 rv = wg->config.securityPolicy->symmetricModule.cryptoModule.
30022 signatureAlgorithm.sign(channelContext, &toBeSigned, &signature);
30023 UA_CHECK_STATUS(rv, return rv);
30024 }
30025 return UA_STATUSCODE_GOOD;
30026}
30027#endif
30028
30029static UA_StatusCode
30030encodeNetworkMessage(UA_WriterGroup *wg, UA_NetworkMessage *nm,
30031 UA_ByteString *buf) {
30032 UA_Byte *bufPos = buf->data;
30033 UA_Byte *bufEnd = &buf->data[buf->length];
30034
30035#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30036 UA_Byte *networkMessageStart = bufPos;
30037#endif
30038 UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(nm, &bufPos, bufEnd);
30039 UA_CHECK_STATUS(rv, return rv);
30040
30041#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30042 UA_Byte *payloadStart = bufPos;
30043#endif
30044 rv = UA_NetworkMessage_encodePayload(nm, &bufPos, bufEnd);
30045 UA_CHECK_STATUS(rv, return rv);
30046
30047 rv = UA_NetworkMessage_encodeFooters(nm, &bufPos, bufEnd);
30048 UA_CHECK_STATUS(rv, return rv);
30049
30050#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30051 /* Encrypt and Sign the message */
30052 UA_Byte *footerEnd = bufPos;
30053 rv = encryptAndSign(wg, nm, networkMessageStart, payloadStart, footerEnd);
30054 UA_CHECK_STATUS(rv, return rv);
30055#endif
30056
30057 return UA_STATUSCODE_GOOD;
30058}
30059
30060#ifdef UA_ENABLE_JSON_ENCODING
30061static UA_StatusCode
30062sendNetworkMessageJson(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30063 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30064 /* Prepare the NetworkMessage */
30065 UA_NetworkMessage nm;
30066 memset(&nm, 0, sizeof(UA_NetworkMessage));
30067 nm.version = 1;
30068 nm.networkMessageType = UA_NETWORKMESSAGE_DATASET;
30069 nm.payloadHeaderEnabled = true;
30070 nm.payloadHeader.dataSetPayloadHeader.count = dsmCount;
30071 nm.payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds;
30072 nm.payload.dataSetPayload.dataSetMessages = dsm;
30073
30074 /* Compute the message length */
30075 size_t msgSize = UA_NetworkMessage_calcSizeJson(&nm, NULL, 0, NULL, 0, true);
30076
30077 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
30078 UA_ByteString buf;
30079 UA_Byte stackBuf[UA_MAX_STACKBUF];
30080 buf.data = stackBuf;
30081 buf.length = msgSize;
30082 UA_StatusCode res = UA_STATUSCODE_GOOD;
30083 if(msgSize > UA_MAX_STACKBUF) {
30084 res = UA_ByteString_allocBuffer(&buf, msgSize);
30085 if(res != UA_STATUSCODE_GOOD)
30086 return res;
30087 }
30088
30089 /* Encode the message */
30090 UA_Byte *bufPos = buf.data;
30091 const UA_Byte *bufEnd = &buf.data[msgSize];
30092 res = UA_NetworkMessage_encodeJson(&nm, &bufPos, &bufEnd, NULL, 0, NULL, 0, true);
30093 if(res != UA_STATUSCODE_GOOD)
30094 goto cleanup;
30095 UA_assert(bufPos == bufEnd);
30096
30097 /* Send the prepared messages */
30098 res = connection->channel->send(connection->channel,
30099 &wg->config.transportSettings, &buf);
30100
30101 cleanup:
30102 if(msgSize > UA_MAX_STACKBUF)
30103 UA_ByteString_clear(&buf);
30104 return res;
30105}
30106#endif
30107
30108static UA_StatusCode
30109generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30110 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount,
30111 UA_ExtensionObject *messageSettings,
30112 UA_ExtensionObject *transportSettings,
30113 UA_NetworkMessage *networkMessage) {
30114 if(messageSettings->content.decoded.type !=
30115 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
30116 return UA_STATUSCODE_BADINTERNALERROR;
30117 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
30118 messageSettings->content.decoded.data;
30119
30120 networkMessage->publisherIdEnabled =
30121 ((u64)wgm->networkMessageContentMask &
30122 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0;
30123 networkMessage->groupHeaderEnabled =
30124 ((u64)wgm->networkMessageContentMask &
30125 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0;
30126 networkMessage->groupHeader.writerGroupIdEnabled =
30127 ((u64)wgm->networkMessageContentMask &
30128 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0;
30129 networkMessage->groupHeader.groupVersionEnabled =
30130 ((u64)wgm->networkMessageContentMask &
30131 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0;
30132 networkMessage->groupHeader.networkMessageNumberEnabled =
30133 ((u64)wgm->networkMessageContentMask &
30134 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0;
30135 networkMessage->groupHeader.sequenceNumberEnabled =
30136 ((u64)wgm->networkMessageContentMask &
30137 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0;
30138 networkMessage->payloadHeaderEnabled =
30139 ((u64)wgm->networkMessageContentMask &
30140 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0;
30141 networkMessage->timestampEnabled =
30142 ((u64)wgm->networkMessageContentMask &
30143 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0;
30144 networkMessage->picosecondsEnabled =
30145 ((u64)wgm->networkMessageContentMask &
30146 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0;
30147 networkMessage->dataSetClassIdEnabled =
30148 ((u64)wgm->networkMessageContentMask &
30149 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0;
30150 networkMessage->promotedFieldsEnabled =
30151 ((u64)wgm->networkMessageContentMask &
30152 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
30153
30154 /* Set the SecurityHeader */
30155#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30156 if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
30157 networkMessage->securityEnabled = true;
30158 networkMessage->securityHeader.networkMessageSigned = true;
30159 if(wg->config.securityMode >= UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
30160 networkMessage->securityHeader.networkMessageEncrypted = true;
30161 networkMessage->securityHeader.securityTokenId = wg->securityTokenId;
30162
30163 /* Generate the MessageNonce */
30164 UA_ByteString_allocBuffer(&networkMessage->securityHeader.messageNonce, 8);
30165 if(networkMessage->securityHeader.messageNonce.length == 0)
30166 return UA_STATUSCODE_BADOUTOFMEMORY;
30167
30168 networkMessage->securityHeader.messageNonce.length = 4; /* Generate 4 random bytes */
30169 UA_StatusCode rv = wg->config.securityPolicy->symmetricModule.
30170 generateNonce(wg->config.securityPolicy->policyContext,
30171 &networkMessage->securityHeader.messageNonce);
30172 if(rv != UA_STATUSCODE_GOOD)
30173 return rv;
30174 networkMessage->securityHeader.messageNonce.length = 8;
30175 UA_Byte *pos = &networkMessage->securityHeader.messageNonce.data[4];
30176 const UA_Byte *end = &networkMessage->securityHeader.messageNonce.data[8];
30177 UA_UInt32_encodeBinary(&wg->nonceSequenceNumber, &pos, end);
30178 }
30179#endif
30180
30181 networkMessage->version = 1;
30182 networkMessage->networkMessageType = UA_NETWORKMESSAGE_DATASET;
30183 if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
30184 networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
30185 networkMessage->publisherId.publisherIdUInt32 =
30186 connection->config->publisherId.numeric;
30187 } else if(connection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
30188 networkMessage->publisherIdType = UA_PUBLISHERDATATYPE_STRING;
30189 networkMessage->publisherId.publisherIdString =
30190 connection->config->publisherId.string;
30191 }
30192
30193 if(networkMessage->groupHeader.sequenceNumberEnabled)
30194 networkMessage->groupHeader.sequenceNumber = wg->sequenceNumber;
30195
30196 if(networkMessage->groupHeader.groupVersionEnabled)
30197 networkMessage->groupHeader.groupVersion = wgm->groupVersion;
30198
30199 /* Compute the length of the dsm separately for the header */
30200 UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
30201 if(!dsmLengths)
30202 return UA_STATUSCODE_BADOUTOFMEMORY;
30203 for(UA_Byte i = 0; i < dsmCount; i++)
30204 dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
30205
30206 networkMessage->payloadHeader.dataSetPayloadHeader.count = dsmCount;
30207 networkMessage->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds;
30208 networkMessage->groupHeader.writerGroupId = wg->config.writerGroupId;
30209 /* number of the NetworkMessage inside a PublishingInterval */
30210 networkMessage->groupHeader.networkMessageNumber = 1;
30211 networkMessage->payload.dataSetPayload.sizes = dsmLengths;
30212 networkMessage->payload.dataSetPayload.dataSetMessages = dsm;
30213 return UA_STATUSCODE_GOOD;
30214}
30215
30216static UA_StatusCode
30217sendNetworkMessageBinary(UA_PubSubConnection *connection, UA_WriterGroup *wg,
30218 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30219 UA_NetworkMessage nm;
30220 memset(&nm, 0, sizeof(UA_NetworkMessage));
30221
30222 /* Fill the message structure */
30223 UA_StatusCode rv =
30224 generateNetworkMessage(connection, wg, dsm, writerIds, dsmCount,
30225 &wg->config.messageSettings,
30226 &wg->config.transportSettings, &nm);
30227 UA_CHECK_STATUS(rv, return rv);
30228
30229 /* Compute the message size. Add the overhead for the security signature.
30230 * There is no padding and the encryption incurs no size overhead. */
30231 size_t msgSize = UA_NetworkMessage_calcSizeBinary(&nm, NULL);
30232#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
30233 if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) {
30234 UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy;
30235 msgSize += sp->symmetricModule.cryptoModule.
30236 signatureAlgorithm.getLocalSignatureSize(sp->policyContext);
30237 }
30238#endif
30239
30240 /* Allocate the buffer. Allocate on the stack if the buffer is small. */
30241 UA_ByteString buf;
30242 UA_Byte stackBuf[UA_MAX_STACKBUF];
30243 buf.data = stackBuf;
30244 buf.length = msgSize;
30245 if(msgSize > UA_MAX_STACKBUF) {
30246 rv = UA_ByteString_allocBuffer(&buf, msgSize);
30247 UA_CHECK_STATUS(rv, goto cleanup);
30248 }
30249
30250 /* Encode and encrypt the message */
30251 rv = encodeNetworkMessage(wg, &nm, &buf);
30252 UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
30253
30254 /* Send out the message */
30255 rv = connection->channel->send(connection->channel,
30256 &wg->config.transportSettings, &buf);
30257 UA_CHECK_STATUS(rv, goto cleanup_with_msg_size);
30258
30259cleanup_with_msg_size:
30260 if(msgSize > UA_MAX_STACKBUF) {
30261 UA_ByteString_clear(&buf);
30262 }
30263cleanup:
30264 UA_ByteString_clear(&nm.securityHeader.messageNonce);
30265 UA_free(nm.payload.dataSetPayload.sizes);
30266 return rv;
30267}
30268
30269static void
30270sendNetworkMessage(UA_Server *server, UA_WriterGroup *wg, UA_PubSubConnection *connection,
30271 UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) {
30272 UA_StatusCode res = UA_STATUSCODE_GOOD;
30273 switch(wg->config.encodingMimeType) {
30274 case UA_PUBSUB_ENCODING_UADP:
30275 res = sendNetworkMessageBinary(connection, wg, dsm, writerIds, dsmCount);
30276 break;
30277#ifdef UA_ENABLE_JSON_ENCODING
30278 case UA_PUBSUB_ENCODING_JSON:
30279 res = sendNetworkMessageJson(connection, wg, dsm, writerIds, dsmCount);
30280 break;
30281#endif
30282 default:
30283 res = UA_STATUSCODE_BADNOTSUPPORTED;
30284 break;
30285 }
30286
30287 /* If sending failed, disable all writer of the writergroup */
30288 if(res != UA_STATUSCODE_GOOD) {
30289 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30290 "PubSub Publish: Could not send a NetworkMessage "
30291 "with status code %s", UA_StatusCode_name(res));
30292 UA_DataSetWriter *dsw;
30293 LIST_FOREACH(dsw, &wg->writers, listEntry) {
30294 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30295 }
30296 return;
30297 }
30298
30299 /* Increase the sequence number */
30300 wg->sequenceNumber++;
30301}
30302
30303static void
30304sendBufferedNetworkMessage(UA_Server *server, UA_WriterGroup *wg,
30305 UA_PubSubConnection *connection) {
30306 UA_NetworkMessageOffsetBuffer *buf = &wg->bufferedMessage;
30307 UA_StatusCode res = UA_NetworkMessage_updateBufferedMessage(buf);
30308 if(res != UA_STATUSCODE_GOOD) {
30309 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
30310 "PubSub sending failed - could not update the message");
30311 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
30312 return;
30313 }
30314
30315 res = connection->channel->send(connection->channel,
30316 &wg->config.transportSettings, &buf->buffer);
30317 if(res != UA_STATUSCODE_GOOD) {
30318 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30319 "Publish failed. RT fixed size. sendBufferedNetworkMessage failed");
30320 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, wg);
30321 return;
30322 }
30323
30324 /* Sending successful - increase the sequence number */
30325 wg->sequenceNumber++;
30326}
30327
30328/* This callback triggers the collection and publish of NetworkMessages and the
30329 * contained DataSetMessages. */
30330void
30331UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
30332 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "Publish Callback");
30333
30334 // TODO: review if its okay to force correct value from caller side instead
30335 // UA_assert(writerGroup != NULL);
30336 // UA_assert(server != NULL);
30337
30338 if(!writerGroup) {
30339 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30340 "Publish failed. WriterGroup not found");
30341 return;
30342 }
30343
30344 /* Nothing to do? */
30345 if(writerGroup->writersCount == 0)
30346 return;
30347
30348 /* Find the connection associated with the writer */
30349 UA_PubSubConnection *connection = writerGroup->linkedConnection;
30350 if(!connection) {
30351 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30352 "Publish failed. PubSubConnection invalid.");
30353 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, writerGroup);
30354 return;
30355 }
30356
30357 /* Realtime path - update the buffer message and send directly */
30358 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
30359 sendBufferedNetworkMessage(server, writerGroup, connection);
30360 return;
30361 }
30362
30363 /* How many DSM can be sent in one NM? */
30364 UA_Byte maxDSM = (UA_Byte)writerGroup->config.maxEncapsulatedDataSetMessageCount;
30365 if(writerGroup->config.maxEncapsulatedDataSetMessageCount > UA_BYTE_MAX)
30366 maxDSM = UA_BYTE_MAX;
30367
30368 /* If the maxEncapsulatedDataSetMessageCount is set to 0 -> 1 */
30369 if(maxDSM == 0)
30370 maxDSM = 1;
30371
30372 /* It is possible to put several DataSetMessages into one NetworkMessage.
30373 * But only if they do not contain promoted fields. NM with promoted fields
30374 * are sent out right away. The others are kept in a buffer for
30375 * "batching". */
30376 size_t dsmCount = 0;
30377 UA_STACKARRAY(UA_UInt16, dsWriterIds, writerGroup->writersCount);
30378 UA_STACKARRAY(UA_DataSetMessage, dsmStore, writerGroup->writersCount);
30379
30380 UA_DataSetWriter *dsw;
30381 LIST_FOREACH(dsw, &writerGroup->writers, listEntry) {
30382 if(dsw->state != UA_PUBSUBSTATE_OPERATIONAL)
30383 continue;
30384
30385 /* Find the dataset */
30386 UA_PublishedDataSet *pds =
30387 UA_PublishedDataSet_findPDSbyId(server, dsw->connectedDataSet);
30388 if(!pds) {
30389 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30390 "PubSub Publish: PublishedDataSet not found");
30391 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30392 continue;
30393 }
30394
30395 /* Generate the DSM */
30396 dsWriterIds[dsmCount] = dsw->config.dataSetWriterId;
30397 UA_StatusCode res =
30398 UA_DataSetWriter_generateDataSetMessage(server, &dsmStore[dsmCount], dsw);
30399 if(res != UA_STATUSCODE_GOOD) {
30400 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30401 "PubSub Publish: DataSetMessage creation failed");
30402 UA_DataSetWriter_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsw);
30403 continue;
30404 }
30405
30406 /* There is no promoted field -> send right away */
30407 if(pds->promotedFieldsCount > 0) {
30408 sendNetworkMessage(server, writerGroup, connection, &dsmStore[dsmCount],
30409 &dsWriterIds[dsmCount], 1);
30410
30411 /* Clean up the current store entry */
30412 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
30413 for(size_t i = 0; i < dsmStore[dsmCount].data.keyFrameData.fieldCount; ++i) {
30414 dsmStore[dsmCount].data.keyFrameData.dataSetFields[i].value.data = NULL;
30415 }
30416 }
30417 UA_DataSetMessage_clear(&dsmStore[dsmCount]);
30418
30419 continue; /* Don't increase the dsmCount, reuse the slot */
30420 }
30421
30422 dsmCount++;
30423 }
30424
30425 /* Send the NetworkMessages with batched DataSetMessages */
30426 UA_Byte nmDsmCount = 0;
30427 for(size_t i = 0; i < dsmCount; i += nmDsmCount) {
30428 /* How many dsm are batched in this iteration? */
30429 nmDsmCount = (i + maxDSM > dsmCount) ? (UA_Byte)(dsmCount - i) : maxDSM;
30430
30431 /* Send the batched messages */
30432 sendNetworkMessage(server, writerGroup, connection, &dsmStore[i],
30433 &dsWriterIds[i], nmDsmCount);
30434 }
30435
30436 /* Clean up DSM */
30437 for(size_t i = 0; i < dsmCount; i++) {
30438 if(writerGroup->config.rtLevel == UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) {
30439 for(size_t j = 0; j < dsmStore[i].data.keyFrameData.fieldCount; ++j) {
30440 dsmStore[i].data.keyFrameData.dataSetFields[j].value.data = NULL;
30441 }
30442 }
30443 UA_DataSetMessage_clear(&dsmStore[i]);
30444 }
30445}
30446
30447/* Add new publishCallback. The first execution is triggered directly after
30448 * creation. */
30449UA_StatusCode
30450UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup) {
30451 UA_StatusCode retval = UA_STATUSCODE_GOOD;
30452 if(writerGroup->config.pubsubManagerCallback.addCustomCallback)
30453 retval |= writerGroup->config.pubsubManagerCallback.
30454 addCustomCallback(server, writerGroup->identifier,
30455 (UA_ServerCallback) UA_WriterGroup_publishCallback,
30456 writerGroup, writerGroup->config.publishingInterval,
30457 NULL, // TODO: Send base time from writer group config
30458 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
30459 &writerGroup->publishCallbackId);
30460 else
30461 retval |= UA_PubSubManager_addRepeatedCallback(server,
30462 (UA_ServerCallback) UA_WriterGroup_publishCallback,
30463 writerGroup, writerGroup->config.publishingInterval,
30464 NULL, // TODO: Send base time from writer group config
30465 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, // TODO: Send timer policy from writer group config
30466 &writerGroup->publishCallbackId);
30467
30468 if(retval == UA_STATUSCODE_GOOD)
30469 writerGroup->publishCallbackIsRegistered = true;
30470
30471 /* Run once after creation */
30472 UA_WriterGroup_publishCallback(server, writerGroup);
30473 return retval;
30474}
30475
30476#endif /* UA_ENABLE_PUBSUB */
30477
30478/**** amalgamated original file "/src/pubsub/ua_pubsub_reader.c" ****/
30479
30480/* This Source Code Form is subject to the terms of the Mozilla Public
30481 * License, v. 2.0. If a copy of the MPL was not distributed with this
30482 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
30483 *
30484 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
30485 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
30486 * Copyright (c) 2019 Kalycito Infotech Private Limited
30487 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
30488 */
30489
30490
30491
30492#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
30493
30494
30495#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30496#endif
30497
30498#ifdef UA_ENABLE_PUBSUB_DELTAFRAMES
30499#endif
30500
30501#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
30502#endif
30503
30504/* This functionality of this API will be used in future to create mirror Variables - TODO */
30505/* #define UA_MAX_SIZENAME 64 */ /* Max size of Qualified Name of Subscribed Variable */
30506
30507/* Clear DataSetReader */
30508static void
30509UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dataSetReader);
30510
30511static void
30512UA_PubSubDSRDataSetField_sampleValue(UA_Server *server, UA_DataSetReader *dataSetReader,
30513 UA_DataValue *value, UA_FieldTargetVariable *ftv) {
30514 /* TODO: Static value source without RT information model
30515 * This API supports only to external datasource in RT configutation
30516 * TODO: Extend to support other configuration if required */
30517
30518 /* Get the Node */
30519 const UA_VariableNode *rtNode = (const UA_VariableNode *)
30520 UA_NODESTORE_GET(server, &ftv->targetVariable.targetNodeId);
30521 if(!rtNode)
30522 return;
30523
30524 if(rtNode->valueBackend.backendType == UA_VALUEBACKENDTYPE_EXTERNAL) {
30525 /* Set the external source in the dataset reader config */
30526 ftv->externalDataValue = rtNode->valueBackend.backend.external.value;
30527
30528 /* Get the value to compute the offsets */
30529 *value = **rtNode->valueBackend.backend.external.value;
30530 value->value.storageType = UA_VARIANT_DATA_NODELETE;
30531 }
30532
30533 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
30534}
30535
30536static UA_StatusCode
30537UA_PubSubDataSetReader_generateKeyFrameMessage(UA_Server *server,
30538 UA_DataSetMessage *dataSetMessage,
30539 UA_DataSetReader *dataSetReader) {
30540 /* Prepare DataSetMessageContent */
30541 UA_TargetVariables *tv = &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
30542 dataSetMessage->header.dataSetMessageValid = true;
30543 dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME;
30544 dataSetMessage->data.keyFrameData.fieldCount = (UA_UInt16) tv->targetVariablesSize;
30545 dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *)
30546 UA_Array_new(tv->targetVariablesSize, &UA_TYPES[UA_TYPES_DATAVALUE]);
30547 if(!dataSetMessage->data.keyFrameData.dataSetFields)
30548 return UA_STATUSCODE_BADOUTOFMEMORY;
30549
30550 for(size_t counter = 0; counter < tv->targetVariablesSize; counter++) {
30551 /* Sample the value and set the source in the reader config */
30552 UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter];
30553 UA_FieldTargetVariable *ftv = &tv->targetVariables[counter];
30554 UA_PubSubDSRDataSetField_sampleValue(server, dataSetReader, dfv, ftv);
30555
30556 /* Deactivate statuscode? */
30557 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30558 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0)
30559 dfv->hasStatus = false;
30560
30561 /* Deactivate timestamps */
30562 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30563 (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0)
30564 dfv->hasSourceTimestamp = false;
30565 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30566 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0)
30567 dfv->hasSourcePicoseconds = false;
30568 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30569 (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0)
30570 dfv->hasServerTimestamp = false;
30571 if(((u64)dataSetReader->config.dataSetFieldContentMask &
30572 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0)
30573 dfv->hasServerPicoseconds = false;
30574 }
30575
30576 return UA_STATUSCODE_GOOD;
30577}
30578
30579/* Generate a DataSetMessage for the given reader. */
30580UA_StatusCode
30581UA_DataSetReader_generateDataSetMessage(UA_Server *server,
30582 UA_DataSetMessage *dataSetMessage,
30583 UA_DataSetReader *dataSetReader) {
30584 /* Reset the message */
30585 memset(dataSetMessage, 0, sizeof(UA_DataSetMessage));
30586
30587 /* Support only for UADP configuration
30588 * TODO: JSON encoding if UA_DataSetReader_generateDataSetMessage used other
30589 * that RT configuration */
30590
30591 UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
30592 if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
30593 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30594 "Only UADP encoding is supported.");
30595 return UA_STATUSCODE_BADNOTSUPPORTED;
30596 }
30597
30598 /* The configuration Flags are included inside the std. defined UA_UadpDataSetReaderMessageDataType */
30599 UA_UadpDataSetReaderMessageDataType defaultUadpConfiguration;
30600 UA_UadpDataSetReaderMessageDataType *dataSetReaderMessageDataType =
30601 (UA_UadpDataSetReaderMessageDataType*) settings->content.decoded.data;
30602
30603 if(!(settings->encoding == UA_EXTENSIONOBJECT_DECODED ||
30604 settings->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
30605 !dataSetReaderMessageDataType->dataSetMessageContentMask) {
30606 /* create default flag configuration if no dataSetMessageContentMask or even messageSettings in
30607 * UadpDataSetWriterMessageDataType was passed in */
30608 memset(&defaultUadpConfiguration, 0, sizeof(UA_UadpDataSetReaderMessageDataType));
30609 defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask)
30610 ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP |
30611 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION |
30612 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION);
30613 dataSetReaderMessageDataType = &defaultUadpConfiguration;
30614 }
30615
30616 /* Sanity-test the configuration */
30617 if(dataSetReaderMessageDataType &&
30618 (dataSetReaderMessageDataType->networkMessageNumber != 0 ||
30619 dataSetReaderMessageDataType->dataSetOffset != 0)) {
30620 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30621 "Static DSM configuration not supported. Using defaults");
30622 dataSetReaderMessageDataType->networkMessageNumber = 0;
30623 dataSetReaderMessageDataType->dataSetOffset = 0;
30624 }
30625
30626 /* The field encoding depends on the flags inside the reader config. */
30627 if(dataSetReader->config.dataSetFieldContentMask &
30628 (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) {
30629 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
30630 } else if((u64)dataSetReader->config.dataSetFieldContentMask &
30631 ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP |
30632 (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS |
30633 (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS |
30634 (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) {
30635 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
30636 } else {
30637 dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT;
30638 }
30639
30640 /* Std: 'The DataSetMessageContentMask defines the flags for the content
30641 * of the DataSetMessage header.' */
30642 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30643 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) {
30644 dataSetMessage->header.configVersionMajorVersionEnabled = true;
30645 dataSetMessage->header.configVersionMajorVersion =
30646 dataSetReader->config.dataSetMetaData.configurationVersion.majorVersion;
30647 }
30648
30649 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30650 (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) {
30651 dataSetMessage->header.configVersionMinorVersionEnabled = true;
30652 dataSetMessage->header.configVersionMinorVersion =
30653 dataSetReader->config.dataSetMetaData.configurationVersion.minorVersion;
30654 }
30655
30656 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30657 (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) {
30658 /* Will be modified when subscriber receives new nw msg */
30659 dataSetMessage->header.dataSetMessageSequenceNrEnabled = true;
30660 dataSetMessage->header.dataSetMessageSequenceNr = 1;
30661 }
30662
30663 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30664 (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) {
30665 dataSetMessage->header.timestampEnabled = true;
30666 dataSetMessage->header.timestamp = UA_DateTime_now();
30667 }
30668
30669 /* TODO: Picoseconds resolution not supported atm */
30670 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30671 (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) {
30672 dataSetMessage->header.picoSecondsIncluded = false;
30673 }
30674
30675 if((u64)dataSetReaderMessageDataType->dataSetMessageContentMask &
30676 (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) {
30677 dataSetMessage->header.statusEnabled = true;
30678 }
30679
30680 /* Not supported for Delta frames atm */
30681 return UA_PubSubDataSetReader_generateKeyFrameMessage(server, dataSetMessage, dataSetReader);
30682}
30683
30684UA_StatusCode
30685UA_DataSetReader_generateNetworkMessage(UA_PubSubConnection *pubSubConnection,
30686 UA_DataSetReader *dataSetReader,
30687 UA_DataSetMessage *dsm, UA_UInt16 *writerId,
30688 UA_Byte dsmCount, UA_NetworkMessage *nm) {
30689 UA_ExtensionObject *settings = &dataSetReader->config.messageSettings;
30690 if(settings->content.decoded.type != &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE])
30691 return UA_STATUSCODE_BADNOTSUPPORTED;
30692
30693 UA_UadpDataSetReaderMessageDataType *dsrm =
30694 (UA_UadpDataSetReaderMessageDataType*)settings->content.decoded.data;
30695 nm->publisherIdEnabled = ((u64)dsrm->networkMessageContentMask &
30696 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0;
30697 nm->groupHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
30698 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0;
30699 nm->groupHeader.writerGroupIdEnabled = ((u64)dsrm->networkMessageContentMask &
30700 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0;
30701 nm->groupHeader.groupVersionEnabled = ((u64)dsrm->networkMessageContentMask &
30702 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0;
30703 nm->groupHeader.networkMessageNumberEnabled = ((u64)dsrm->networkMessageContentMask &
30704 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0;
30705 nm->groupHeader.sequenceNumberEnabled = ((u64)dsrm->networkMessageContentMask &
30706 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0;
30707 nm->payloadHeaderEnabled = ((u64)dsrm->networkMessageContentMask &
30708 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0;
30709 nm->timestampEnabled = ((u64)dsrm->networkMessageContentMask &
30710 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0;
30711 nm->picosecondsEnabled = ((u64)dsrm->networkMessageContentMask &
30712 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0;
30713 nm->dataSetClassIdEnabled = ((u64)dsrm->networkMessageContentMask &
30714 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0;
30715 nm->promotedFieldsEnabled = ((u64)dsrm->networkMessageContentMask &
30716 (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0;
30717 nm->version = 1;
30718 nm->networkMessageType = UA_NETWORKMESSAGE_DATASET;
30719
30720 if(!UA_DataType_isNumeric(dataSetReader->config.publisherId.type))
30721 return UA_STATUSCODE_BADNOTSUPPORTED;
30722
30723 switch(dataSetReader->config.publisherId.type->typeKind) {
30724 case UA_DATATYPEKIND_BYTE:
30725 nm->publisherIdType = UA_PUBLISHERDATATYPE_BYTE;
30726 nm->publisherId.publisherIdByte = *(UA_Byte *) dataSetReader->config.publisherId.data;
30727 break;
30728 case UA_DATATYPEKIND_UINT16:
30729 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT16;
30730 nm->publisherId.publisherIdUInt16 = *(UA_UInt16 *) dataSetReader->config.publisherId.data;
30731 break;
30732 case UA_DATATYPEKIND_UINT32:
30733 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT32;
30734 nm->publisherId.publisherIdUInt32 = *(UA_UInt32 *) dataSetReader->config.publisherId.data;
30735 break;
30736 case UA_DATATYPEKIND_UINT64:
30737 nm->publisherIdType = UA_PUBLISHERDATATYPE_UINT64;
30738 nm->publisherId.publisherIdUInt64 = *(UA_UInt64 *) dataSetReader->config.publisherId.data;
30739 break;
30740 default:
30741 return UA_STATUSCODE_BADNOTSUPPORTED;
30742 }
30743
30744 if(nm->groupHeader.sequenceNumberEnabled)
30745 nm->groupHeader.sequenceNumber = 1; /* Will be modified when subscriber receives new nw msg. */
30746
30747 if(nm->groupHeader.groupVersionEnabled)
30748 nm->groupHeader.groupVersion = dsrm->groupVersion;
30749
30750 /* Compute the length of the dsm separately for the header */
30751 UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(dsmCount, sizeof(UA_UInt16));
30752 if(!dsmLengths)
30753 return UA_STATUSCODE_BADOUTOFMEMORY;
30754 for(UA_Byte i = 0; i < dsmCount; i++){
30755 dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(&dsm[i], NULL, 0);
30756 switch(dataSetReader->config.expectedEncoding) {
30757 case UA_PUBSUB_RT_UNKNOWN:
30758 break;
30759 case UA_PUBSUB_RT_VARIANT:
30760 dsm[i].header.fieldEncoding = UA_FIELDENCODING_VARIANT;
30761 break;
30762 case UA_PUBSUB_RT_DATA_VALUE:
30763 dsm[i].header.fieldEncoding = UA_FIELDENCODING_DATAVALUE;
30764 break;
30765 case UA_PUBSUB_RT_RAW:
30766 dsm[i].header.fieldEncoding = UA_FIELDENCODING_RAWDATA;
30767 break;
30768 }
30769 }
30770 nm->payloadHeader.dataSetPayloadHeader.count = dsmCount;
30771 nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerId;
30772 nm->groupHeader.writerGroupId = dataSetReader->config.writerGroupId;
30773 nm->groupHeader.networkMessageNumber = 1; /* number of the NetworkMessage inside a PublishingInterval */
30774 nm->payload.dataSetPayload.sizes = dsmLengths;
30775 nm->payload.dataSetPayload.dataSetMessages = dsm;
30776 return UA_STATUSCODE_GOOD;
30777}
30778
30779static UA_StatusCode
30780checkReaderIdentifier(UA_Server *server, UA_NetworkMessage *msg,
30781 UA_DataSetReader *reader) {
30782 if(!msg->groupHeaderEnabled || !msg->groupHeader.writerGroupIdEnabled ||
30783 !msg->payloadHeaderEnabled) {
30784 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
30785 "Cannot process DataSetReader without WriterGroup"
30786 "and DataSetWriter identifiers");
30787 return UA_STATUSCODE_BADNOTIMPLEMENTED;
30788 }
30789
30790 switch(msg->publisherIdType) {
30791 case UA_PUBLISHERDATATYPE_BYTE:
30792 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_BYTE] &&
30793 msg->publisherIdType == UA_PUBLISHERDATATYPE_BYTE &&
30794 msg->publisherId.publisherIdByte == *(UA_Byte*)reader->config.publisherId.data)
30795 break;
30796 return UA_STATUSCODE_BADNOTFOUND;
30797 case UA_PUBLISHERDATATYPE_UINT16:
30798 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT16] &&
30799 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT16 &&
30800 msg->publisherId.publisherIdUInt16 == *(UA_UInt16*)reader->config.publisherId.data)
30801 break;
30802 return UA_STATUSCODE_BADNOTFOUND;
30803 case UA_PUBLISHERDATATYPE_UINT32:
30804 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT32] &&
30805 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT32 &&
30806 msg->publisherId.publisherIdUInt32 == *(UA_UInt32*)reader->config.publisherId.data)
30807 break;
30808 return UA_STATUSCODE_BADNOTFOUND;
30809 case UA_PUBLISHERDATATYPE_UINT64:
30810 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_UINT64] &&
30811 msg->publisherIdType == UA_PUBLISHERDATATYPE_UINT64 &&
30812 msg->publisherId.publisherIdUInt64 == *(UA_UInt64*)reader->config.publisherId.data)
30813 break;
30814 return UA_STATUSCODE_BADNOTFOUND;
30815 case UA_PUBLISHERDATATYPE_STRING:
30816 if(reader->config.publisherId.type == &UA_TYPES[UA_TYPES_STRING] &&
30817 msg->publisherIdType == UA_PUBLISHERDATATYPE_STRING &&
30818 UA_String_equal(&msg->publisherId.publisherIdString,
30819 (UA_String*)reader->config.publisherId.data))
30820 break;
30821 return UA_STATUSCODE_BADNOTFOUND;
30822 default:
30823 return UA_STATUSCODE_BADNOTFOUND;
30824 }
30825
30826 if(reader->config.writerGroupId == msg->groupHeader.writerGroupId &&
30827 reader->config.dataSetWriterId == *msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds) {
30828 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
30829 "DataSetReader found. Process NetworkMessage");
30830 return UA_STATUSCODE_GOOD;
30831 }
30832
30833 return UA_STATUSCODE_BADNOTFOUND;
30834}
30835
30836UA_StatusCode
30837UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier,
30838 const UA_DataSetReaderConfig *dataSetReaderConfig,
30839 UA_NodeId *readerIdentifier) {
30840 /* Search the reader group by the given readerGroupIdentifier */
30841 UA_ReaderGroup *readerGroup = UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
30842 if(readerGroup == NULL)
30843 return UA_STATUSCODE_BADNOTFOUND;
30844
30845 if(!dataSetReaderConfig)
30846 return UA_STATUSCODE_BADNOTFOUND;
30847
30848 if(readerGroup->configurationFrozen){
30849 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30850 "Add DataSetReader failed. Subscriber configuration is frozen.");
30851 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30852 }
30853
30854 /* Allocate memory for new DataSetReader */
30855 UA_DataSetReader *newDataSetReader = (UA_DataSetReader *)
30856 UA_calloc(1, sizeof(UA_DataSetReader));
30857 if(!newDataSetReader)
30858 return UA_STATUSCODE_BADOUTOFMEMORY;
30859
30860 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
30861 newDataSetReader->componentType = UA_PUBSUB_COMPONENT_DATASETREADER;
30862 if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL) {
30863 retVal = UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, newDataSetReader);
30864 if(retVal != UA_STATUSCODE_GOOD) {
30865 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30866 "Add DataSetReader failed. setPubSubState failed.");
30867 UA_free(newDataSetReader);
30868 newDataSetReader = 0;
30869 return retVal;
30870 }
30871 }
30872
30873 /* Copy the config into the new dataSetReader */
30874 UA_DataSetReaderConfig_copy(dataSetReaderConfig, &newDataSetReader->config);
30875 newDataSetReader->linkedReaderGroup = readerGroup->identifier;
30876
30877#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30878 retVal = addDataSetReaderRepresentation(server, newDataSetReader);
30879 if(retVal != UA_STATUSCODE_GOOD) {
30880 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30881 "Add DataSetReader failed. addDataSetReaderRepresentation failed.");
30882 UA_DataSetReaderConfig_clear(&newDataSetReader->config);
30883 UA_free(newDataSetReader);
30884 newDataSetReader = 0;
30885 return retVal;
30886 }
30887#else
30888 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
30889 &newDataSetReader->identifier);
30890#endif
30891
30892#ifdef UA_ENABLE_PUBSUB_MONITORING
30893 /* create message receive timeout timer */
30894 retVal = server->config.pubSubConfig.monitoringInterface.createMonitoring(
30895 server,
30896 newDataSetReader->identifier,
30897 UA_PUBSUB_COMPONENT_DATASETREADER,
30898 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
30899 newDataSetReader,
30900 UA_DataSetReader_handleMessageReceiveTimeout);
30901 if(retVal != UA_STATUSCODE_GOOD) {
30902 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30903 "Add DataSetReader failed. Create message receive timeout timer failed.");
30904 UA_DataSetReaderConfig_clear(&newDataSetReader->config);
30905 UA_free(newDataSetReader);
30906 newDataSetReader = 0;
30907 return retVal;
30908 }
30909#endif /* UA_ENABLE_PUBSUB_MONITORING */
30910
30911 /* Add the new reader to the group */
30912 LIST_INSERT_HEAD(&readerGroup->readers, newDataSetReader, listEntry);
30913 readerGroup->readersCount++;
30914
30915 if(readerIdentifier)
30916 UA_NodeId_copy(&newDataSetReader->identifier, readerIdentifier);
30917
30918 return retVal;
30919}
30920
30921UA_StatusCode
30922UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier) {
30923 /* Remove datasetreader given by the identifier */
30924 UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, readerIdentifier);
30925 if(!dsr)
30926 return UA_STATUSCODE_BADNOTFOUND;
30927
30928 if(dsr->configurationFrozen) {
30929 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30930 "Remove DataSetReader failed. "
30931 "Subscriber configuration is frozen.");
30932 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30933 }
30934
30935#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
30936 removeDataSetReaderRepresentation(server, dsr);
30937#endif
30938
30939 UA_StatusCode res = UA_STATUSCODE_GOOD;
30940#ifdef UA_ENABLE_PUBSUB_MONITORING
30941 /* Stop and remove message receive timeout timer */
30942 if(dsr->msgRcvTimeoutTimerRunning) {
30943 res = server->config.pubSubConfig.monitoringInterface.
30944 stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
30945 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
30946 if(res != UA_STATUSCODE_GOOD) {
30947 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30948 "Remove DataSetReader failed. Stop message "
30949 "receive timeout timer of DataSetReader '%.*s' failed.",
30950 (int) dsr->config.name.length, dsr->config.name.data);
30951 }
30952 }
30953
30954 res |= server->config.pubSubConfig.monitoringInterface.
30955 deleteMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
30956 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
30957 if(res != UA_STATUSCODE_GOOD) {
30958 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
30959 "Remove DataSetReader failed. Delete message receive "
30960 "timeout timer of DataSetReader '%.*s' failed.",
30961 (int) dsr->config.name.length, dsr->config.name.data);
30962 }
30963#endif /* UA_ENABLE_PUBSUB_MONITORING */
30964
30965 UA_DataSetReader_clear(server, dsr);
30966 return res;
30967}
30968
30969UA_StatusCode
30970UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
30971 UA_NodeId readerGroupIdentifier,
30972 const UA_DataSetReaderConfig *config) {
30973 if(config == NULL)
30974 return UA_STATUSCODE_BADINVALIDARGUMENT;
30975
30976 UA_DataSetReader *currentDataSetReader =
30977 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
30978 if(!currentDataSetReader)
30979 return UA_STATUSCODE_BADNOTFOUND;
30980
30981 if(currentDataSetReader->configurationFrozen){
30982 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30983 "Update DataSetReader config failed. "
30984 "Subscriber configuration is frozen.");
30985 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30986 }
30987
30988 UA_ReaderGroup *currentReaderGroup =
30989 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
30990 if(currentReaderGroup->configurationFrozen) {
30991 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
30992 "Update DataSetReader config failed. "
30993 "Subscriber configuration is frozen.");
30994 return UA_STATUSCODE_BADCONFIGURATIONERROR;
30995 }
30996
30997 /* The update functionality will be extended during the next PubSub batches.
30998 * Currently changes for writerGroupId, dataSetWriterId and TargetVariables are possible. */
30999 if(currentDataSetReader->config.writerGroupId != config->writerGroupId)
31000 currentDataSetReader->config.writerGroupId = config->writerGroupId;
31001
31002 if(currentDataSetReader->config.dataSetWriterId != config->dataSetWriterId)
31003 currentDataSetReader->config.dataSetWriterId = config->dataSetWriterId;
31004
31005 if(currentDataSetReader->config.subscribedDataSetType != UA_PUBSUB_SDS_TARGET) {
31006 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31007 "Unsupported SubscribedDataSetType.");
31008 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31009 }
31010
31011 UA_TargetVariables *oldTV =
31012 &currentDataSetReader->config.subscribedDataSet.subscribedDataSetTarget;
31013 const UA_TargetVariables *newTV =
31014 &config->subscribedDataSet.subscribedDataSetTarget;
31015 if(oldTV->targetVariablesSize == newTV->targetVariablesSize) {
31016 for(size_t i = 0; i < config->subscribedDataSet.subscribedDataSetTarget.targetVariablesSize; i++) {
31017 if(!UA_NodeId_equal(&oldTV->targetVariables[i].targetVariable.targetNodeId,
31018 &newTV->targetVariables[i].targetVariable.targetNodeId)) {
31019 UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
31020 newTV->targetVariablesSize, newTV->targetVariables);
31021 }
31022 }
31023 } else {
31024 UA_Server_DataSetReader_createTargetVariables(server, currentDataSetReader->identifier,
31025 newTV->targetVariablesSize, newTV->targetVariables);
31026 }
31027
31028 UA_StatusCode res = UA_STATUSCODE_GOOD;
31029#ifdef UA_ENABLE_PUBSUB_MONITORING
31030 if(currentDataSetReader->config.messageReceiveTimeout != config->messageReceiveTimeout) {
31031 /* Update message receive timeout timer interval */
31032 currentDataSetReader->config.messageReceiveTimeout = config->messageReceiveTimeout;
31033 res = server->config.pubSubConfig.monitoringInterface.
31034 updateMonitoringInterval(server, currentDataSetReader->identifier,
31035 UA_PUBSUB_COMPONENT_DATASETREADER,
31036 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT,
31037 currentDataSetReader);
31038 if(res != UA_STATUSCODE_GOOD) {
31039 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31040 "Update DataSetReader message receive timeout timer failed.");
31041 }
31042 }
31043#endif /* UA_ENABLE_PUBSUB_MONITORING */
31044 return res;
31045}
31046
31047UA_StatusCode
31048UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
31049 UA_DataSetReaderConfig *config) {
31050 if(!config)
31051 return UA_STATUSCODE_BADINVALIDARGUMENT;
31052
31053 UA_DataSetReader *currentDataSetReader =
31054 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31055 if(!currentDataSetReader)
31056 return UA_STATUSCODE_BADNOTFOUND;
31057
31058 UA_DataSetReaderConfig tmpReaderConfig;
31059 /* Deep copy of the actual config */
31060 UA_DataSetReaderConfig_copy(&currentDataSetReader->config, &tmpReaderConfig);
31061 *config = tmpReaderConfig;
31062 return UA_STATUSCODE_GOOD;
31063}
31064
31065UA_StatusCode
31066UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src,
31067 UA_DataSetReaderConfig *dst) {
31068 memset(dst, 0, sizeof(UA_DataSetReaderConfig));
31069 UA_StatusCode retVal = UA_String_copy(&src->name, &dst->name);
31070 if(retVal != UA_STATUSCODE_GOOD)
31071 return retVal;
31072
31073 retVal = UA_Variant_copy(&src->publisherId, &dst->publisherId);
31074 if(retVal != UA_STATUSCODE_GOOD)
31075 return retVal;
31076
31077 dst->writerGroupId = src->writerGroupId;
31078 dst->dataSetWriterId = src->dataSetWriterId;
31079 dst->expectedEncoding = src->expectedEncoding;
31080 retVal = UA_DataSetMetaDataType_copy(&src->dataSetMetaData, &dst->dataSetMetaData);
31081 if(retVal != UA_STATUSCODE_GOOD)
31082 return retVal;
31083
31084 dst->dataSetFieldContentMask = src->dataSetFieldContentMask;
31085 dst->messageReceiveTimeout = src->messageReceiveTimeout;
31086
31087 /* Currently memcpy is used to copy the securityParameters */
31088 memcpy(&dst->securityParameters, &src->securityParameters, sizeof(UA_PubSubSecurityParameters));
31089 retVal = UA_ExtensionObject_copy(&src->messageSettings, &dst->messageSettings);
31090 if(retVal != UA_STATUSCODE_GOOD)
31091 return retVal;
31092
31093 retVal = UA_ExtensionObject_copy(&src->transportSettings, &dst->transportSettings);
31094 if(retVal != UA_STATUSCODE_GOOD)
31095 return retVal;
31096
31097 if(src->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31098 retVal = UA_TargetVariables_copy(&src->subscribedDataSet.subscribedDataSetTarget,
31099 &dst->subscribedDataSet.subscribedDataSetTarget);
31100 }
31101 return retVal;
31102}
31103
31104void
31105UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg) {
31106 UA_String_clear(&cfg->name);
31107 UA_Variant_clear(&cfg->publisherId);
31108 UA_DataSetMetaDataType_clear(&cfg->dataSetMetaData);
31109 UA_ExtensionObject_clear(&cfg->messageSettings);
31110 UA_ExtensionObject_clear(&cfg->transportSettings);
31111 if(cfg->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31112 UA_TargetVariables_clear(&cfg->subscribedDataSet.subscribedDataSetTarget);
31113 }
31114}
31115
31116UA_StatusCode
31117UA_Server_DataSetReader_getState(UA_Server *server, UA_NodeId dataSetReaderIdentifier,
31118 UA_PubSubState *state) {
31119
31120 if((server == NULL) || (state == NULL))
31121 return UA_STATUSCODE_BADINVALIDARGUMENT;
31122 UA_DataSetReader *currentDataSetReader =
31123 UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31124 if(currentDataSetReader == NULL)
31125 return UA_STATUSCODE_BADNOTFOUND;
31126 *state = currentDataSetReader->state;
31127 return UA_STATUSCODE_GOOD;
31128}
31129
31130static UA_StatusCode
31131UA_DataSetReader_setState_disabled(UA_Server *server, UA_DataSetReader *dsr) {
31132 UA_StatusCode ret = UA_STATUSCODE_GOOD;
31133 switch(dsr->state) {
31134 case UA_PUBSUBSTATE_DISABLED:
31135 return UA_STATUSCODE_GOOD;
31136 case UA_PUBSUBSTATE_PAUSED:
31137 dsr->state = UA_PUBSUBSTATE_DISABLED;
31138 return UA_STATUSCODE_GOOD;
31139 case UA_PUBSUBSTATE_OPERATIONAL:
31140#ifdef UA_ENABLE_PUBSUB_MONITORING
31141 /* Stop MessageReceiveTimeout timer */
31142 if(dsr->msgRcvTimeoutTimerRunning == UA_TRUE) {
31143 ret = server->config.pubSubConfig.monitoringInterface.
31144 stopMonitoring(server, dsr->identifier,
31145 UA_PUBSUB_COMPONENT_DATASETREADER,
31146 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31147 if(ret == UA_STATUSCODE_GOOD) {
31148 dsr->msgRcvTimeoutTimerRunning = UA_FALSE;
31149 } else {
31150 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31151 "Disable ReaderGroup failed. Stop message receive "
31152 "timeout timer of DataSetReader '%.*s' failed.",
31153 (int) dsr->config.name.length, dsr->config.name.data);
31154 }
31155 }
31156#endif /* UA_ENABLE_PUBSUB_MONITORING */
31157 if(ret == UA_STATUSCODE_GOOD)
31158 dsr->state = UA_PUBSUBSTATE_DISABLED;
31159 return ret;
31160 case UA_PUBSUBSTATE_ERROR:
31161 break;
31162 default:
31163 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31164 "Received unknown PubSub state!");
31165 }
31166 return UA_STATUSCODE_BADINVALIDARGUMENT;
31167}
31168
31169/* State machine methods not part of the open62541 state machine API */
31170UA_StatusCode
31171UA_DataSetReader_setPubSubState(UA_Server *server, UA_PubSubState state,
31172 UA_DataSetReader *dataSetReader) {
31173 switch(state) {
31174 case UA_PUBSUBSTATE_DISABLED:
31175 return UA_DataSetReader_setState_disabled(server, dataSetReader);
31176 case UA_PUBSUBSTATE_PAUSED:
31177 return UA_STATUSCODE_BADNOTSUPPORTED;
31178 case UA_PUBSUBSTATE_OPERATIONAL:
31179 dataSetReader->state = UA_PUBSUBSTATE_OPERATIONAL;
31180 break;
31181 case UA_PUBSUBSTATE_ERROR:
31182 dataSetReader->state = UA_PUBSUBSTATE_ERROR;
31183 break;
31184 default:
31185 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31186 "Received unknown PubSub state!");
31187 return UA_STATUSCODE_BADINVALIDARGUMENT;
31188 }
31189 return UA_STATUSCODE_GOOD;
31190}
31191
31192UA_StatusCode
31193UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src, UA_FieldTargetVariable *dst) {
31194 /* Do a simple memcpy */
31195 memcpy(dst, src, sizeof(UA_FieldTargetVariable));
31196 return UA_FieldTargetDataType_copy(&src->targetVariable, &dst->targetVariable);
31197}
31198
31199UA_StatusCode
31200UA_TargetVariables_copy(const UA_TargetVariables *src, UA_TargetVariables *dst) {
31201 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
31202 memcpy(dst, src, sizeof(UA_TargetVariables));
31203 if(src->targetVariablesSize > 0) {
31204 dst->targetVariables = (UA_FieldTargetVariable*)
31205 UA_calloc(src->targetVariablesSize, sizeof(UA_FieldTargetVariable));
31206 if(!dst->targetVariables)
31207 return UA_STATUSCODE_BADOUTOFMEMORY;
31208 for(size_t i = 0; i < src->targetVariablesSize; i++)
31209 retVal |= UA_FieldTargetVariable_copy(&src->targetVariables[i], &dst->targetVariables[i]);
31210 }
31211 return retVal;
31212}
31213
31214void
31215UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget) {
31216 for(size_t i = 0; i < subscribedDataSetTarget->targetVariablesSize; i++) {
31217 UA_FieldTargetDataType_clear(&subscribedDataSetTarget->targetVariables[i].targetVariable);
31218 }
31219 if(subscribedDataSetTarget->targetVariablesSize > 0)
31220 UA_free(subscribedDataSetTarget->targetVariables);
31221 memset(subscribedDataSetTarget, 0, sizeof(UA_TargetVariables));
31222}
31223
31224/* This Method is used to initially set the SubscribedDataSet to
31225 * TargetVariablesType and to create the list of target Variables of a
31226 * SubscribedDataSetType. */
31227UA_StatusCode
31228UA_Server_DataSetReader_createTargetVariables(UA_Server *server,
31229 UA_NodeId dataSetReaderIdentifier,
31230 size_t targetVariablesSize,
31231 const UA_FieldTargetVariable *targetVariables) {
31232 UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31233 if(!dataSetReader)
31234 return UA_STATUSCODE_BADINVALIDARGUMENT;
31235
31236 if(dataSetReader->configurationFrozen) {
31237 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31238 "Create Target Variables failed. Subscriber configuration is frozen.");
31239 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31240 }
31241
31242 if(dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize > 0)
31243 UA_TargetVariables_clear(&dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
31244
31245 /* Set subscribed dataset to TargetVariableType */
31246 dataSetReader->config.subscribedDataSetType = UA_PUBSUB_SDS_TARGET;
31247 UA_TargetVariables tmp;
31248 tmp.targetVariablesSize = targetVariablesSize;
31249 tmp.targetVariables = (UA_FieldTargetVariable*)(uintptr_t)targetVariables;
31250 return UA_TargetVariables_copy(&tmp, &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget);
31251}
31252
31253/* This functionality of this API will be used in future to create mirror Variables - TODO */
31254/* UA_StatusCode
31255UA_Server_DataSetReader_createDataSetMirror(UA_Server *server, UA_String *parentObjectNodeName,
31256 UA_NodeId dataSetReaderIdentifier) {
31257 if((server == NULL) || (parentNode == NULL)) {
31258 return UA_STATUSCODE_BADINVALIDARGUMENT;
31259 }
31260
31261 UA_StatusCode retval = UA_STATUSCODE_GOOD;
31262 UA_DataSetReader* pDataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier);
31263 if(pDataSetReader == NULL) {
31264 return UA_STATUSCODE_BADINVALIDARGUMENT;
31265 }
31266
31267 if(pDataSetReader->configurationFrozen) {
31268 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31269 "Add Target Variables failed. Subscriber configuration is frozen.");
31270 return UA_STATUSCODE_BADCONFIGURATIONERROR;
31271 } // TODO: Frozen configuration variable in TargetVariable structure
31272
31273 UA_TargetVariables targetVars;
31274 targetVars.targetVariablesSize = pDataSetReader->config.dataSetMetaData.fieldsSize;
31275 targetVars.targetVariables = (UA_FieldTargetVariable *)
31276 UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetVariable));
31277
31278 for(size_t i = 0; i < pDataSetReader->config.dataSetMetaData.fieldsSize; i++) {
31279 UA_VariableAttributes vAttr = UA_VariableAttributes_default;
31280 vAttr.valueRank = pDataSetReader->config.dataSetMetaData.fields[i].valueRank;
31281 if(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize > 0) {
31282 retval = UA_Array_copy(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensions,
31283 pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize,
31284 (void**)&vAttr.arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]);
31285 if(retval == UA_STATUSCODE_GOOD) {
31286 vAttr.arrayDimensionsSize =
31287 pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize;
31288 }
31289
31290 }
31291
31292 vAttr.dataType = pDataSetReader->config.dataSetMetaData.fields[i].dataType;
31293
31294 vAttr.accessLevel = UA_ACCESSLEVELMASK_READ;
31295 UA_LocalizedText_copy(&pDataSetReader->config.dataSetMetaData.fields[i].description,
31296 &vAttr.description);
31297 UA_QualifiedName qn;
31298 UA_QualifiedName_init(&qn);
31299 char szTmpName[UA_MAX_SIZENAME];
31300 if(pDataSetReader->config.dataSetMetaData.fields[i].name.length > 0) {
31301 UA_UInt16 slen = UA_MAX_SIZENAME -1;
31302 vAttr.displayName.locale = UA_STRING("en-US");
31303 vAttr.displayName.text = pDataSetReader->config.dataSetMetaData.fields[i].name;
31304 if(pDataSetReader->config.dataSetMetaData.fields[i].name.length < slen) {
31305 slen = (UA_UInt16)pDataSetReader->config.dataSetMetaData.fields[i].name.length;
31306 UA_snprintf(szTmpName, sizeof(szTmpName), "%.*s", (int)slen,
31307 (const char*)pDataSetReader->config.dataSetMetaData.fields[i].name.data);
31308 }
31309
31310 szTmpName[slen] = '\0';
31311 qn = UA_QUALIFIEDNAME(1, szTmpName);
31312 }
31313 else {
31314 strcpy(szTmpName, "SubscribedVariable");
31315 vAttr.displayName = UA_LOCALIZEDTEXT("en-US", szTmpName);
31316 qn = UA_QUALIFIEDNAME(1, "SubscribedVariable");
31317 }
31318
31319 // Add variable to the given parent node
31320 UA_NodeId newNode;
31321 retval = UA_Server_addVariableNode(server, UA_NODEID_NULL, *parentNode,
31322 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qn,
31323 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
31324 vAttr, NULL, &newNode);
31325 if(retval == UA_STATUSCODE_GOOD) {
31326 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
31327 "addVariableNode %s succeeded", szTmpName);
31328 }
31329 else {
31330 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_USERLAND,
31331 "addVariableNode: error 0x%" PRIx32, retval);
31332 }
31333
31334 targetVars.targetVariables[i].targetVariable.attributeId = UA_ATTRIBUTEID_VALUE;
31335 UA_NodeId_copy(&newNode, &targetVars.targetVariables[i].targetVariable.targetNodeId);
31336 UA_NodeId_clear(&newNode);
31337 if(vAttr.arrayDimensionsSize > 0) {
31338 UA_Array_delete(vAttr.arrayDimensions, vAttr.arrayDimensionsSize,
31339 &UA_TYPES[UA_TYPES_UINT32]);
31340 }
31341 }
31342
31343 UA_TargetVariables_clear(&targetVars);
31344 return retval;
31345}*/
31346
31347static void
31348DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg,
31349 UA_DataSetReader *dsr, UA_DataSetMessage* msg) {
31350 UA_LOG_TRACE(&server->config.logger, UA_LOGCATEGORY_SERVER,
31351 "Received RAW Frame");
31352 msg->data.keyFrameData.fieldCount = (UA_UInt16)
31353 dsr->config.dataSetMetaData.fieldsSize;
31354
31355 size_t offset = 0;
31356 for(size_t i = 0; i < dsr->config.dataSetMetaData.fieldsSize; i++) {
31357 /* TODO The datatype reference should be part of the internal
31358 * pubsub configuration to avoid the time-expensive lookup */
31359 const UA_DataType *type =
31360 UA_findDataTypeWithCustom(&dsr->config.dataSetMetaData.fields[i].dataType,
31361 server->config.customDataTypes);
31362 msg->data.keyFrameData.rawFields.length += type->memSize;
31363 UA_STACKARRAY(UA_Byte, value, type->memSize);
31364 UA_StatusCode res =
31365 UA_decodeBinaryInternal(&msg->data.keyFrameData.rawFields,
31366 &offset, value, type, NULL);
31367 if(res != UA_STATUSCODE_GOOD) {
31368 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31369 "Error during Raw-decode KeyFrame field %u: %s",
31370 (unsigned)i, UA_StatusCode_name(res));
31371 return;
31372 }
31373
31374 UA_FieldTargetVariable *tv =
31375 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31376
31377 if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
31378 if (tv->beforeWrite) {
31379 void *pData = (**tv->externalDataValue).value.data;
31380 (**tv->externalDataValue).value.data = value; // set raw data as "preview"
31381 tv->beforeWrite(server,
31382 &dsr->identifier,
31383 &dsr->linkedReaderGroup,
31384 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
31385 dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
31386 tv->externalDataValue);
31387 (**tv->externalDataValue).value.data = pData; // restore previous data pointer
31388 }
31389 memcpy((**tv->externalDataValue).value.data, value, type->memSize);
31390 if(tv->afterWrite)
31391 tv->afterWrite(server, &dsr->identifier,
31392 &dsr->linkedReaderGroup,
31393 &tv->targetVariable.targetNodeId,
31394 tv->targetVariableContext,
31395 tv->externalDataValue);
31396 continue; /* No dynamic allocation for fixed-size msg, no need to _clear */
31397 }
31398
31399 UA_WriteValue writeVal;
31400 UA_WriteValue_init(&writeVal);
31401 writeVal.attributeId = tv->targetVariable.attributeId;
31402 writeVal.indexRange = tv->targetVariable.receiverIndexRange;
31403 writeVal.nodeId = tv->targetVariable.targetNodeId;
31404 UA_Variant_setScalar(&writeVal.value.value, value, type);
31405 writeVal.value.hasValue = true;
31406 res = UA_Server_write(server, &writeVal);
31407 UA_clear(value, type);
31408 if(res != UA_STATUSCODE_GOOD) {
31409 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31410 "Error writing KeyFrame field %u: %s",
31411 (unsigned)i, UA_StatusCode_name(res));
31412 }
31413 }
31414}
31415
31416static void
31417DataSetReader_processFixedSize(UA_Server *server, UA_ReaderGroup *rg,
31418 UA_DataSetReader *dsr, UA_DataSetMessage *msg,
31419 size_t fieldCount) {
31420 for(size_t i = 0; i < fieldCount; i++) {
31421 if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
31422 continue;
31423
31424 UA_FieldTargetVariable *tv =
31425 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31426 if(tv->targetVariable.attributeId != UA_ATTRIBUTEID_VALUE)
31427 continue;
31428 if (tv->beforeWrite) {
31429 UA_DataValue *tmp = &msg->data.keyFrameData.dataSetFields[i];
31430 tv->beforeWrite(server,
31431 &dsr->identifier,
31432 &dsr->linkedReaderGroup,
31433 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariable.targetNodeId,
31434 dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i].targetVariableContext,
31435 &tmp);
31436 }
31437 memcpy((**tv->externalDataValue).value.data,
31438 msg->data.keyFrameData.dataSetFields[i].value.data,
31439 msg->data.keyFrameData.dataSetFields[i].value.type->memSize);
31440 if(tv->afterWrite)
31441 tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup,
31442 &tv->targetVariable.targetNodeId,
31443 tv->targetVariableContext, tv->externalDataValue);
31444 }
31445}
31446
31447void
31448UA_DataSetReader_process(UA_Server *server, UA_ReaderGroup *rg,
31449 UA_DataSetReader *dsr, UA_DataSetMessage *msg) {
31450 if(!dsr || !rg || !msg || !server)
31451 return;
31452
31453 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31454 "DataSetReader '%.*s': received a network message",
31455 (int) dsr->config.name.length, dsr->config.name.data);
31456
31457 if(!msg->header.dataSetMessageValid) {
31458 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31459 "DataSetMessage is discarded: message is not valid");
31460 /* To Do check ConfigurationVersion */
31461 /* if(msg->header.configVersionMajorVersionEnabled) {
31462 * if(msg->header.configVersionMajorVersion !=
31463 * dsr->config.dataSetMetaData.configurationVersion.majorVersion) {
31464 * UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_SERVER,
31465 * "DataSetMessage is discarded: ConfigurationVersion "
31466 * "MajorVersion does not match");
31467 * return;
31468 * }
31469 * } */
31470 return;
31471 }
31472
31473 if(msg->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME) {
31474 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
31475 "DataSetMessage is discarded: Only keyframes are supported");
31476 return;
31477 }
31478
31479 /* Process message with raw encoding (realtime and non-realtime) */
31480 if(msg->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) {
31481 DataSetReader_processRaw(server, rg, dsr, msg);
31482#ifdef UA_ENABLE_PUBSUB_MONITORING
31483 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31484#endif
31485 return;
31486 }
31487
31488 /* Check and adjust the field count
31489 * TODO Throw an error if non-matching? */
31490 size_t fieldCount = msg->data.keyFrameData.fieldCount;
31491 if(dsr->config.dataSetMetaData.fieldsSize < fieldCount)
31492 fieldCount = dsr->config.dataSetMetaData.fieldsSize;
31493
31494 if(dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize < fieldCount)
31495 fieldCount = dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize;
31496
31497 /* Process message with fixed size fields (realtime capable) */
31498 if(rg->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE) {
31499 DataSetReader_processFixedSize(server, rg, dsr, msg, fieldCount);
31500#ifdef UA_ENABLE_PUBSUB_MONITORING
31501 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31502#endif
31503 return;
31504 }
31505
31506 /* Write the message fields via the write service (non realtime) */
31507 UA_StatusCode res = UA_STATUSCODE_GOOD;
31508 for(size_t i = 0; i < fieldCount; i++) {
31509 if(!msg->data.keyFrameData.dataSetFields[i].hasValue)
31510 continue;
31511
31512 UA_FieldTargetVariable *tv =
31513 &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
31514
31515 UA_WriteValue writeVal;
31516 UA_WriteValue_init(&writeVal);
31517 writeVal.attributeId = tv->targetVariable.attributeId;
31518 writeVal.indexRange = tv->targetVariable.receiverIndexRange;
31519 writeVal.nodeId = tv->targetVariable.targetNodeId;
31520 writeVal.value = msg->data.keyFrameData.dataSetFields[i];
31521 res = UA_Server_write(server, &writeVal);
31522 if(res != UA_STATUSCODE_GOOD)
31523 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31524 "Error writing KeyFrame field %u: %s",
31525 (unsigned)i, UA_StatusCode_name(res));
31526 }
31527
31528#ifdef UA_ENABLE_PUBSUB_MONITORING
31529 UA_DataSetReader_checkMessageReceiveTimeout(server, dsr);
31530#endif
31531}
31532
31533#ifdef UA_ENABLE_PUBSUB_MONITORING
31534
31535void
31536UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server,
31537 UA_DataSetReader *dsr) {
31538 UA_assert(server != 0);
31539 UA_assert(dsr != 0);
31540
31541 /* If previous reader state was error (because we haven't received messages
31542 * and ran into timeout) we should set the state back to operational */
31543 if(dsr->state == UA_PUBSUBSTATE_ERROR) {
31544 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dsr);
31545 if(server->config.pubSubConfig.stateChangeCallback != 0) {
31546 server->config.pubSubConfig.stateChangeCallback(&dsr->identifier,
31547 UA_PUBSUBSTATE_OPERATIONAL,
31548 UA_STATUSCODE_GOOD);
31549 }
31550 }
31551
31552 /* Stop message receive timeout timer */
31553 UA_StatusCode res;
31554 if(dsr->msgRcvTimeoutTimerRunning) {
31555 res = server->config.pubSubConfig.monitoringInterface.
31556 stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
31557 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31558 if(res == UA_STATUSCODE_GOOD) {
31559 dsr->msgRcvTimeoutTimerRunning = false;
31560 } else {
31561 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31562 "DataSetReader '%.*s': stop receive timeout timer failed",
31563 (int)dsr->config.name.length, dsr->config.name.data);
31564 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31565 }
31566 }
31567
31568 /* Start message receive timeout timer */
31569 res = server->config.pubSubConfig.monitoringInterface.
31570 startMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER,
31571 UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr);
31572 if(res == UA_STATUSCODE_GOOD) {
31573 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31574 "Info: DataSetReader '%.*s': start receive timeout timer",
31575 (int)dsr->config.name.length, dsr->config.name.data);
31576 dsr->msgRcvTimeoutTimerRunning = true;
31577 } else {
31578 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31579 "Starting Message Receive Timeout timer failed.");
31580 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31581 }
31582}
31583
31584/* Timeout callback for DataSetReader MessageReceiveTimeout handling */
31585void
31586UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server,
31587 void *dataSetReader) {
31588 if(!server || !dataSetReader) {
31589 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31590 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31591 "null pointer param");
31592 return;
31593 }
31594
31595 UA_DataSetReader *dsr = (UA_DataSetReader*) dataSetReader;
31596 if(dsr->componentType != UA_PUBSUB_COMPONENT_DATASETREADER) {
31597 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31598 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31599 "input param is not of type DataSetReader");
31600 return;
31601 }
31602
31603 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31604 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31605 "MessageReceiveTimeout occurred at DataSetReader "
31606 "'%.*s': MessageReceiveTimeout = %f Timer Id = %u ",
31607 (int)dsr->config.name.length, dsr->config.name.data,
31608 dsr->config.messageReceiveTimeout,
31609 (UA_UInt32) dsr->msgRcvTimeoutTimerId);
31610
31611 UA_ServerConfig *pConfig = UA_Server_getConfig(server);
31612 if(pConfig->pubSubConfig.stateChangeCallback != 0) {
31613 pConfig->pubSubConfig.stateChangeCallback(&dsr->identifier,
31614 UA_PUBSUBSTATE_ERROR,
31615 UA_STATUSCODE_BADTIMEOUT);
31616 }
31617
31618 UA_StatusCode res =
31619 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dsr);
31620 if(res != UA_STATUSCODE_GOOD) {
31621 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31622 "UA_DataSetReader_handleMessageReceiveTimeout(): "
31623 "setting pubsub state failed");
31624 }
31625}
31626#endif /* UA_ENABLE_PUBSUB_MONITORING */
31627
31628static void
31629UA_DataSetReader_clear(UA_Server *server, UA_DataSetReader *dsr) {
31630 /* Delete DataSetReader config */
31631 UA_DataSetReaderConfig_clear(&dsr->config);
31632
31633 /* Delete DataSetReader */
31634 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, dsr->linkedReaderGroup);
31635 if(rg)
31636 rg->readersCount--;
31637
31638 UA_NodeId_clear(&dsr->identifier);
31639 UA_NodeId_clear(&dsr->linkedReaderGroup);
31640 if(dsr->config.subscribedDataSetType == UA_PUBSUB_SDS_TARGET) {
31641 UA_TargetVariables_clear(&dsr->config.subscribedDataSet.subscribedDataSetTarget);
31642 } else {
31643 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
31644 "UA_DataSetReader_clear(): unsupported subscribed dataset enum type");
31645 }
31646
31647 /* Remove DataSetReader from group */
31648 LIST_REMOVE(dsr, listEntry);
31649
31650 /* Free memory allocated for DataSetReader */
31651 UA_free(dsr);
31652}
31653
31654static void
31655processMessageWithReader(UA_Server *server, UA_ReaderGroup *readerGroup,
31656 UA_DataSetReader *reader, UA_NetworkMessage *msg) {
31657 UA_Byte totalDataSets = 1;
31658 if(msg->payloadHeaderEnabled)
31659 totalDataSets = msg->payloadHeader.dataSetPayloadHeader.count;
31660 for(UA_Byte i = 0; i < totalDataSets; i++) {
31661 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
31662 "Process Msg with DataSetReader!");
31663 UA_DataSetReader_process(server, readerGroup, reader,
31664 &msg->payload.dataSetPayload.dataSetMessages[i]);
31665 }
31666}
31667
31668UA_StatusCode
31669UA_Server_processNetworkMessage(UA_Server *server, UA_PubSubConnection *connection,
31670 UA_NetworkMessage* msg) {
31671 if(!msg || !connection)
31672 return UA_STATUSCODE_BADINVALIDARGUMENT;
31673
31674 /* To Do The condition pMsg->dataSetClassIdEnabled
31675 * Here some filtering is possible */
31676
31677 if(!msg->publisherIdEnabled) {
31678 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31679 "Cannot process DataSetReader without PublisherId");
31680 return UA_STATUSCODE_BADNOTIMPLEMENTED; /* TODO: Handle DSR without PublisherId */
31681 }
31682
31683 /* There can be several readers listening for the same network message */
31684 UA_Boolean processed = false;
31685 UA_ReaderGroup *readerGroup;
31686 UA_DataSetReader *reader;
31687 LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
31688 LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
31689 UA_StatusCode retval = checkReaderIdentifier(server, msg, reader);
31690 if(retval == UA_STATUSCODE_GOOD) {
31691 processed = true;
31692 processMessageWithReader(server, readerGroup, reader, msg);
31693 }
31694 }
31695 }
31696
31697 if(!processed) {
31698 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31699 "Dataset reader not found. Check PublisherID, WriterGroupID "
31700 "and DatasetWriterID");
31701 }
31702
31703 return UA_STATUSCODE_GOOD;
31704}
31705
31706/********************************************************************************
31707 * Functionality related to decoding, decrypting and processing network messages
31708 * as a subscriber
31709 ********************************************************************************/
31710
31711#define MIN_PAYLOAD_SIZE_ETHERNET 46
31712
31713/* Delete the payload value of every decoded DataSet field */
31714static void UA_DataSetMessage_freeDecodedPayload(UA_DataSetMessage *dsm) {
31715 if(dsm->header.fieldEncoding == UA_FIELDENCODING_VARIANT) {
31716 for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
31717#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31718 UA_Variant_init(&dsm->data.keyFrameData.dataSetFields[i].value);
31719#else
31720 UA_Variant_clear(&dsm->data.keyFrameData.dataSetFields[i].value);
31721#endif
31722 }
31723 }
31724 else if(dsm->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) {
31725 for(size_t i = 0; i < dsm->data.keyFrameData.fieldCount; i++) {
31726#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31727 UA_DataValue_init(&dsm->data.keyFrameData.dataSetFields[i]);
31728#else
31729 UA_DataValue_clear(&dsm->data.keyFrameData.dataSetFields[i]);
31730#endif
31731 }
31732 }
31733}
31734
31735UA_StatusCode
31736decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos,
31737 UA_NetworkMessage *nm, UA_PubSubConnection *connection) {
31738#ifdef UA_DEBUG_DUMP_PKGS
31739 UA_dump_hex_pkg(buffer->data, buffer->length);
31740#endif
31741
31742 UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(buffer, pos, nm);
31743 UA_CHECK_STATUS_ERROR(rv, return rv,
31744 &server->config.logger, UA_LOGCATEGORY_SERVER,
31745 "PubSub receive. decoding headers failed");
31746
31747#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
31748 UA_Boolean processed = false;
31749 UA_ReaderGroup *readerGroup;
31750 UA_DataSetReader *reader;
31751
31752 /* Choose a correct readergroup for decrypt/verify this message
31753 * (there could be multiple) */
31754 LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) {
31755 LIST_FOREACH(reader, &readerGroup->readers, listEntry) {
31756 UA_StatusCode retval = checkReaderIdentifier(server, nm, reader);
31757 if(retval == UA_STATUSCODE_GOOD) {
31758 processed = true;
31759 rv = verifyAndDecryptNetworkMessage(&server->config.logger, buffer, pos,
31760 nm, readerGroup);
31761 UA_CHECK_STATUS_WARN(rv, return rv,
31762 &server->config.logger, UA_LOGCATEGORY_SERVER,
31763 "Subscribe failed. verify and decrypt network message failed.");
31764
31765#ifdef UA_DEBUG_DUMP_PKGS
31766 UA_dump_hex_pkg(buffer->data, buffer->length);
31767#endif
31768 /* break out of all loops when first verify & decrypt was successful */
31769 goto loops_exit;
31770 }
31771 }
31772 }
31773
31774loops_exit:
31775 if(!processed) {
31776 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31777 "Dataset reader not found. Check PublisherId, "
31778 "WriterGroupId and DatasetWriterId");
31779 /* Possible multicast scenario: there are multiple connections (with one
31780 * or more ReaderGroups) within a multicast group every connection
31781 * receives all network messages, even if some of them are not meant for
31782 * the connection currently processed -> therefore it is ok if the
31783 * connection does not have a DataSetReader for every received network
31784 * message. We must not return an error here, but continue with the
31785 * buffer decoding and see if we have a matching DataSetReader for the
31786 * next network message. */
31787 }
31788#endif
31789
31790 rv = UA_NetworkMessage_decodePayload(buffer, pos, nm);
31791 UA_CHECK_STATUS(rv, return rv);
31792
31793 rv = UA_NetworkMessage_decodeFooters(buffer, pos, nm);
31794 UA_CHECK_STATUS(rv, return rv);
31795
31796 return UA_STATUSCODE_GOOD;
31797}
31798
31799static
31800UA_StatusCode
31801decodeAndProcessNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
31802 UA_PubSubConnection *connection,
31803 UA_ByteString *buffer) {
31804 UA_NetworkMessage nm;
31805 memset(&nm, 0, sizeof(UA_NetworkMessage));
31806 size_t currentPosition = 0;
31807
31808 UA_StatusCode rv = UA_STATUSCODE_GOOD;
31809 rv = decodeNetworkMessage(server, buffer, &currentPosition, &nm, connection);
31810 UA_CHECK_STATUS_WARN(rv, goto cleanup, &server->config.logger, UA_LOGCATEGORY_SERVER,
31811 "Subscribe failed. verify, decrypt and decode network message failed.");
31812
31813 rv = UA_Server_processNetworkMessage(server, connection, &nm);
31814 // TODO: check what action to perform on error (nothing?)
31815 UA_CHECK_STATUS_WARN(rv, (void)0, &server->config.logger, UA_LOGCATEGORY_SERVER,
31816 "Subscribe failed. process network message failed.");
31817
31818cleanup:
31819 UA_NetworkMessage_clear(&nm);
31820 return rv;
31821}
31822
31823static
31824UA_StatusCode
31825decodeAndProcessNetworkMessageRT(UA_Server *server, UA_ReaderGroup *readerGroup,
31826 UA_PubSubConnection *connection,
31827 UA_ByteString *buffer) {
31828#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31829 useMembufAlloc();
31830#endif
31831
31832 /* Considering max DSM as 1
31833 * TODO: Process with the static value source */
31834 size_t currentPosition = 0;
31835 UA_DataSetReader *dataSetReader = LIST_FIRST(&readerGroup->readers);
31836 UA_NetworkMessage *nm = dataSetReader->bufferedMessage.nm;
31837
31838 /* Decode only the necessary offset and update the networkMessage */
31839 UA_StatusCode res =
31840 UA_NetworkMessage_updateBufferedNwMessage(&dataSetReader->bufferedMessage,
31841 buffer, &currentPosition);
31842 if(res != UA_STATUSCODE_GOOD) {
31843 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31844 "PubSub receive. Unknown field type.");
31845 res = UA_STATUSCODE_UNCERTAIN;
31846 goto cleanup;
31847 }
31848
31849 /* Check the decoded message is the expected one
31850 * TODO: PublisherID check after modification in NM to support all datatypes */
31851 if(nm->groupHeader.writerGroupId != dataSetReader->config.writerGroupId ||
31852 *nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != dataSetReader->config.dataSetWriterId) {
31853 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
31854 "PubSub receive. Unknown message received. Will not be processed.");
31855 res = UA_STATUSCODE_UNCERTAIN;
31856 goto cleanup;
31857 }
31858
31859 UA_DataSetReader_process(server, readerGroup, dataSetReader,
31860 nm->payload.dataSetPayload.dataSetMessages);
31861
31862 cleanup:
31863 UA_DataSetMessage_freeDecodedPayload(nm->payload.dataSetPayload.dataSetMessages);
31864#ifdef UA_ENABLE_PUBSUB_BUFMALLOC
31865 useNormalAlloc();
31866#endif
31867 return res;
31868}
31869
31870typedef struct {
31871 UA_Server *server;
31872 UA_PubSubConnection *connection;
31873 UA_ReaderGroup *readerGroup;
31874} UA_RGContext;
31875
31876static UA_StatusCode
31877decodeAndProcessFun(UA_PubSubChannel *channel, void *cbContext,
31878 const UA_ByteString *buffer) {
31879 UA_ByteString mutableBuffer = {buffer->length, buffer->data};
31880 UA_RGContext *ctx = (UA_RGContext*) cbContext;
31881 return decodeAndProcessNetworkMessage(ctx->server, ctx->readerGroup,
31882 ctx->connection, &mutableBuffer);
31883}
31884
31885static UA_StatusCode
31886decodeAndProcessFunRT(UA_PubSubChannel *channel, void *cbContext,
31887 const UA_ByteString *buffer) {
31888 UA_ByteString mutableBuffer = {buffer->length, buffer->data};
31889 UA_RGContext *ctx = (UA_RGContext*) cbContext;
31890 return decodeAndProcessNetworkMessageRT(ctx->server, ctx->readerGroup,
31891 ctx->connection, &mutableBuffer);
31892}
31893
31894UA_StatusCode
31895receiveBufferedNetworkMessage(UA_Server *server, UA_ReaderGroup *readerGroup,
31896 UA_PubSubConnection *connection) {
31897 UA_RGContext ctx = {server, connection, readerGroup};
31898 UA_PubSubReceiveCallback receiveCB;
31899 if(readerGroup->config.rtLevel == UA_PUBSUB_RT_FIXED_SIZE)
31900 receiveCB = decodeAndProcessFunRT;
31901 else
31902 receiveCB = decodeAndProcessFun;
31903
31904 /* TODO: Move the TransportSettings to to the readerGroupConfig. So we can
31905 * use it here instead of a NULL pointer. */
31906 UA_StatusCode rv =
31907 connection->channel->receive(connection->channel, NULL,
31908 receiveCB, &ctx,
31909 readerGroup->config.timeout);
31910
31911 // TODO attention: here rv is ok if UA_STATUSCODE_GOOD != rv
31912 UA_CHECK_WARN(!UA_StatusCode_isBad(rv), return rv,
31913 &server->config.logger, UA_LOGCATEGORY_SERVER,
31914 "SubscribeCallback(): Connection receive failed!");
31915
31916 return UA_STATUSCODE_GOOD;
31917}
31918
31919#endif /* UA_ENABLE_PUBSUB */
31920
31921/**** amalgamated original file "/src/pubsub/ua_pubsub_readergroup.c" ****/
31922
31923/* This Source Code Form is subject to the terms of the Mozilla Public
31924 * License, v. 2.0. If a copy of the MPL was not distributed with this
31925 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
31926 *
31927 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
31928 * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer)
31929 * Copyright (c) 2019 Kalycito Infotech Private Limited
31930 * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes)
31931 */
31932
31933
31934
31935#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
31936
31937
31938#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
31939#endif
31940
31941UA_ReaderGroup *
31942UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier) {
31943 UA_PubSubConnection *pubSubConnection;
31944 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
31945 UA_ReaderGroup* readerGroup = NULL;
31946 LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
31947 if(UA_NodeId_equal(&identifier, &readerGroup->identifier))
31948 return readerGroup;
31949 }
31950 }
31951 return NULL;
31952}
31953
31954UA_DataSetReader *UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier) {
31955 UA_PubSubConnection *pubSubConnection;
31956 TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){
31957 UA_ReaderGroup* readerGroup = NULL;
31958 LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) {
31959 UA_DataSetReader *tmpReader;
31960 LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) {
31961 if(UA_NodeId_equal(&tmpReader->identifier, &identifier))
31962 return tmpReader;
31963 }
31964 }
31965 }
31966 return NULL;
31967}
31968
31969/* Clear ReaderGroup */
31970static void
31971UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup);
31972
31973/* ReaderGroup Config Handling */
31974
31975UA_StatusCode
31976UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src,
31977 UA_ReaderGroupConfig *dst) {
31978 memcpy(dst, src, sizeof(UA_ReaderGroupConfig));
31979
31980 UA_StatusCode res = UA_String_copy(&src->name, &dst->name);
31981 if(res != UA_STATUSCODE_GOOD)
31982 return res;
31983
31984 res = UA_Array_copy(src->groupProperties, src->groupPropertiesSize,
31985 (void**)&dst->groupProperties,
31986 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
31987 if(res != UA_STATUSCODE_GOOD) {
31988 UA_String_clear(&dst->name);
31989 return res;
31990 }
31991 dst->groupPropertiesSize = src->groupPropertiesSize;
31992 return UA_STATUSCODE_GOOD;
31993}
31994
31995void
31996UA_ReaderGroupConfig_clear(UA_ReaderGroupConfig *readerGroupConfig) {
31997 UA_String_clear(&readerGroupConfig->name);
31998 UA_Array_delete(readerGroupConfig->groupProperties,
31999 readerGroupConfig->groupPropertiesSize,
32000 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
32001 readerGroupConfig->groupProperties = NULL;
32002 readerGroupConfig->groupPropertiesSize = 0;
32003}
32004
32005/* ReaderGroup Lifecycle */
32006
32007UA_StatusCode
32008UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier,
32009 const UA_ReaderGroupConfig *readerGroupConfig,
32010 UA_NodeId *readerGroupIdentifier) {
32011 UA_StatusCode retval = UA_STATUSCODE_GOOD;
32012
32013 /* Check for valid readergroup configuration */
32014 if(!readerGroupConfig)
32015 return UA_STATUSCODE_BADINVALIDARGUMENT;
32016
32017 if(!readerGroupConfig->pubsubManagerCallback.addCustomCallback &&
32018 readerGroupConfig->enableBlockingSocket) {
32019 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32020 "Adding ReaderGroup failed, blocking socket functionality "
32021 "only supported in customcallback");
32022 return UA_STATUSCODE_BADNOTSUPPORTED;
32023 }
32024
32025 /* Search the connection by the given connectionIdentifier */
32026 UA_PubSubConnection *currentConnectionContext =
32027 UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier);
32028 if(!currentConnectionContext)
32029 return UA_STATUSCODE_BADNOTFOUND;
32030
32031 if(currentConnectionContext->configurationFrozen){
32032 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32033 "Adding ReaderGroup failed. Subscriber configuration is frozen.");
32034 return UA_STATUSCODE_BADCONFIGURATIONERROR;
32035 }
32036
32037 /* Regist (bind) the connection channel if it is not already registered */
32038 if(!currentConnectionContext->isRegistered) {
32039 retval |= UA_PubSubConnection_regist(server, &connectionIdentifier);
32040 if(retval != UA_STATUSCODE_GOOD)
32041 return retval;
32042 }
32043
32044 /* Allocate memory for new reader group */
32045 UA_ReaderGroup *newGroup = (UA_ReaderGroup *)UA_calloc(1, sizeof(UA_ReaderGroup));
32046 if(!newGroup)
32047 return UA_STATUSCODE_BADOUTOFMEMORY;
32048
32049 newGroup->componentType = UA_PUBSUB_COMPONENT_READERGROUP;
32050 /* Generate nodeid for the readergroup identifier */
32051 newGroup->linkedConnection = currentConnectionContext->identifier;
32052
32053 /* Deep copy of the config */
32054 retval |= UA_ReaderGroupConfig_copy(readerGroupConfig, &newGroup->config);
32055 /* Check user configured params and define it accordingly */
32056 if(newGroup->config.subscribingInterval <= 0.0)
32057 newGroup->config.subscribingInterval = 5; // Set default to 5 ms
32058
32059 if(newGroup->config.enableBlockingSocket)
32060 newGroup->config.timeout = 0; // Set timeout to 0 for blocking socket
32061
32062 if((!newGroup->config.enableBlockingSocket) && (!newGroup->config.timeout))
32063 newGroup->config.timeout = 1000; /* Set default to 1ms socket timeout
32064 when non-blocking socket allows with
32065 zero timeout */
32066
32067 LIST_INSERT_HEAD(&currentConnectionContext->readerGroups, newGroup, listEntry);
32068 currentConnectionContext->readerGroupsSize++;
32069
32070#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32071 retval |= addReaderGroupRepresentation(server, newGroup);
32072#else
32073 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
32074 &newGroup->identifier);
32075#endif
32076 if(readerGroupIdentifier)
32077 UA_NodeId_copy(&newGroup->identifier, readerGroupIdentifier);
32078
32079 return retval;
32080}
32081
32082UA_StatusCode
32083UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier) {
32084 UA_ReaderGroup* readerGroup =
32085 UA_ReaderGroup_findRGbyId(server, groupIdentifier);
32086 if(readerGroup == NULL)
32087 return UA_STATUSCODE_BADNOTFOUND;
32088
32089 if(readerGroup->configurationFrozen){
32090 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32091 "Remove ReaderGroup failed. Subscriber configuration is frozen.");
32092 return UA_STATUSCODE_BADCONFIGURATIONERROR;
32093 }
32094
32095 /* Search the connection to which the given readergroup is connected to */
32096 UA_PubSubConnection *connection =
32097 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32098 if(connection == NULL)
32099 return UA_STATUSCODE_BADNOTFOUND;
32100
32101 /* Unregister subscribe callback */
32102 if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL)
32103 UA_ReaderGroup_removeSubscribeCallback(server, readerGroup);
32104
32105#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32106 removeReaderGroupRepresentation(server, readerGroup);
32107#endif
32108
32109 /* UA_Server_ReaderGroup_clear also removes itself from the list */
32110 UA_Server_ReaderGroup_clear(server, readerGroup);
32111
32112 /* Remove readerGroup from Connection */
32113 LIST_REMOVE(readerGroup, listEntry);
32114 UA_free(readerGroup);
32115 return UA_STATUSCODE_GOOD;
32116}
32117
32118/* TODO: Implement
32119UA_StatusCode
32120UA_Server_ReaderGroup_updateConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
32121 const UA_ReaderGroupConfig *config) {
32122 return UA_STATUSCODE_BADNOTIMPLEMENTED;
32123}
32124*/
32125
32126UA_StatusCode
32127UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier,
32128 UA_ReaderGroupConfig *config) {
32129 if(!config)
32130 return UA_STATUSCODE_BADINVALIDARGUMENT;
32131
32132 /* Identify the readergroup through the readerGroupIdentifier */
32133 UA_ReaderGroup *currentReaderGroup =
32134 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
32135 if(!currentReaderGroup)
32136 return UA_STATUSCODE_BADNOTFOUND;
32137
32138 UA_ReaderGroupConfig tmpReaderGroupConfig;
32139 /* deep copy of the actual config */
32140 UA_ReaderGroupConfig_copy(&currentReaderGroup->config, &tmpReaderGroupConfig);
32141 *config = tmpReaderGroupConfig;
32142 return UA_STATUSCODE_GOOD;
32143}
32144
32145static void
32146UA_Server_ReaderGroup_clear(UA_Server* server, UA_ReaderGroup *readerGroup) {
32147 UA_ReaderGroupConfig_clear(&readerGroup->config);
32148 UA_DataSetReader *dataSetReader;
32149 UA_DataSetReader *tmpDataSetReader;
32150 LIST_FOREACH_SAFE(dataSetReader, &readerGroup->readers, listEntry, tmpDataSetReader) {
32151 UA_Server_removeDataSetReader(server, dataSetReader->identifier);
32152 }
32153 UA_PubSubConnection* pConn =
32154 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32155 if(pConn != NULL)
32156 pConn->readerGroupsSize--;
32157
32158 /* Delete ReaderGroup and its members */
32159 UA_NodeId_clear(&readerGroup->linkedConnection);
32160 UA_NodeId_clear(&readerGroup->identifier);
32161
32162#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
32163 if(readerGroup->config.securityPolicy && readerGroup->securityPolicyContext) {
32164 readerGroup->config.securityPolicy->deleteContext(readerGroup->securityPolicyContext);
32165 readerGroup->securityPolicyContext = NULL;
32166 }
32167#endif
32168
32169 UA_ReaderGroupConfig_clear(&readerGroup->config);
32170}
32171
32172UA_StatusCode
32173UA_Server_ReaderGroup_getState(UA_Server *server, UA_NodeId readerGroupIdentifier,
32174 UA_PubSubState *state) {
32175 if((server == NULL) || (state == NULL))
32176 return UA_STATUSCODE_BADINVALIDARGUMENT;
32177 UA_ReaderGroup *currentReaderGroup =
32178 UA_ReaderGroup_findRGbyId(server, readerGroupIdentifier);
32179 if(!currentReaderGroup)
32180 return UA_STATUSCODE_BADNOTFOUND;
32181 *state = currentReaderGroup->state;
32182 return UA_STATUSCODE_GOOD;
32183}
32184
32185/* ReaderGroup State */
32186
32187static UA_StatusCode
32188UA_ReaderGroup_setPubSubState_disable(UA_Server *server,
32189 UA_ReaderGroup *rg) {
32190 UA_DataSetReader *dataSetReader;
32191 switch(rg->state) {
32192 case UA_PUBSUBSTATE_DISABLED:
32193 return UA_STATUSCODE_GOOD;
32194 case UA_PUBSUBSTATE_PAUSED:
32195 break;
32196 case UA_PUBSUBSTATE_OPERATIONAL:
32197 UA_ReaderGroup_removeSubscribeCallback(server, rg);
32198 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32199 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_DISABLED,
32200 dataSetReader);
32201 }
32202 rg->state = UA_PUBSUBSTATE_DISABLED;
32203 break;
32204 case UA_PUBSUBSTATE_ERROR:
32205 break;
32206 default:
32207 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32208 "Unknown PubSub state!");
32209 return UA_STATUSCODE_BADINTERNALERROR;
32210 }
32211 return UA_STATUSCODE_GOOD;
32212}
32213
32214static UA_StatusCode
32215UA_ReaderGroup_setPubSubState_paused(UA_Server *server,
32216 UA_ReaderGroup *rg) {
32217 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
32218 "PubSub state paused is unsupported at the moment!");
32219 switch(rg->state) {
32220 case UA_PUBSUBSTATE_DISABLED:
32221 break;
32222 case UA_PUBSUBSTATE_PAUSED:
32223 return UA_STATUSCODE_GOOD;
32224 case UA_PUBSUBSTATE_OPERATIONAL:
32225 break;
32226 case UA_PUBSUBSTATE_ERROR:
32227 break;
32228 default:
32229 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32230 "Unknown PubSub state!");
32231 return UA_STATUSCODE_BADINTERNALERROR;
32232 }
32233 return UA_STATUSCODE_BADNOTSUPPORTED;
32234}
32235
32236static UA_StatusCode
32237UA_ReaderGroup_setPubSubState_operational(UA_Server *server,
32238 UA_ReaderGroup *rg) {
32239 UA_DataSetReader *dataSetReader;
32240 switch(rg->state) {
32241 case UA_PUBSUBSTATE_DISABLED:
32242 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32243 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, dataSetReader);
32244 }
32245 UA_ReaderGroup_addSubscribeCallback(server, rg);
32246 rg->state = UA_PUBSUBSTATE_OPERATIONAL;
32247 return UA_STATUSCODE_GOOD;
32248 case UA_PUBSUBSTATE_PAUSED:
32249 break;
32250 case UA_PUBSUBSTATE_OPERATIONAL:
32251 return UA_STATUSCODE_GOOD;
32252 case UA_PUBSUBSTATE_ERROR:
32253 break;
32254 default:
32255 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32256 "Unknown PubSub state!");
32257 return UA_STATUSCODE_BADINTERNALERROR;
32258 }
32259 return UA_STATUSCODE_BADNOTSUPPORTED;
32260}
32261
32262static UA_StatusCode
32263UA_ReaderGroup_setPubSubState_error(UA_Server *server,
32264 UA_ReaderGroup *rg) {
32265 UA_DataSetReader *dataSetReader;
32266 switch(rg->state) {
32267 case UA_PUBSUBSTATE_DISABLED:
32268 break;
32269 case UA_PUBSUBSTATE_PAUSED:
32270 break;
32271 case UA_PUBSUBSTATE_OPERATIONAL:
32272 UA_ReaderGroup_removeSubscribeCallback(server, rg);
32273 LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
32274 UA_DataSetReader_setPubSubState(server, UA_PUBSUBSTATE_ERROR, dataSetReader);
32275 }
32276 break;
32277 case UA_PUBSUBSTATE_ERROR:
32278 return UA_STATUSCODE_GOOD;
32279 default:
32280 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32281 "Unknown PubSub state!");
32282 return UA_STATUSCODE_BADINTERNALERROR;
32283 }
32284 rg->state = UA_PUBSUBSTATE_ERROR;
32285 return UA_STATUSCODE_GOOD;
32286}
32287
32288UA_StatusCode
32289UA_ReaderGroup_setPubSubState(UA_Server *server, UA_PubSubState state,
32290 UA_ReaderGroup *readerGroup) {
32291 switch(state) {
32292 case UA_PUBSUBSTATE_DISABLED:
32293 return UA_ReaderGroup_setPubSubState_disable(server, readerGroup);
32294 case UA_PUBSUBSTATE_PAUSED:
32295 return UA_ReaderGroup_setPubSubState_paused(server, readerGroup);
32296 case UA_PUBSUBSTATE_OPERATIONAL:
32297 return UA_ReaderGroup_setPubSubState_operational(server, readerGroup);
32298 case UA_PUBSUBSTATE_ERROR:
32299 return UA_ReaderGroup_setPubSubState_error(server, readerGroup);
32300 default:
32301 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32302 "Received unknown PubSub state!");
32303 break;
32304 }
32305 return UA_STATUSCODE_BADINVALIDARGUMENT;
32306}
32307
32308UA_StatusCode
32309UA_Server_setReaderGroupOperational(UA_Server *server, const UA_NodeId readerGroupId){
32310 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32311 if(!rg)
32312 return UA_STATUSCODE_BADNOTFOUND;
32313 return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_OPERATIONAL, rg);
32314}
32315
32316UA_StatusCode
32317UA_Server_setReaderGroupDisabled(UA_Server *server, const UA_NodeId readerGroupId){
32318 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32319 if(!rg)
32320 return UA_STATUSCODE_BADNOTFOUND;
32321 return UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, rg);
32322}
32323
32324#ifdef UA_ENABLE_PUBSUB_ENCRYPTION
32325UA_StatusCode
32326UA_Server_setReaderGroupEncryptionKeys(UA_Server *server, const UA_NodeId readerGroup,
32327 UA_UInt32 securityTokenId,
32328 const UA_ByteString signingKey,
32329 const UA_ByteString encryptingKey,
32330 const UA_ByteString keyNonce) {
32331 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroup);
32332 UA_CHECK_MEM(rg, return UA_STATUSCODE_BADNOTFOUND);
32333
32334 UA_CHECK_MEM_WARN(rg->config.securityPolicy, return UA_STATUSCODE_BADINTERNALERROR,
32335 &server->config.logger, UA_LOGCATEGORY_SERVER,
32336 "No SecurityPolicy configured for the ReaderGroup");
32337
32338 if(securityTokenId != rg->securityTokenId) {
32339 rg->securityTokenId = securityTokenId;
32340 rg->nonceSequenceNumber = 1;
32341 }
32342
32343 /* Create a new context */
32344 if(!rg->securityPolicyContext) {
32345 return rg->config.securityPolicy->
32346 newContext(rg->config.securityPolicy->policyContext,
32347 &signingKey, &encryptingKey, &keyNonce,
32348 &rg->securityPolicyContext);
32349 }
32350
32351 /* Update the context */
32352 return rg->config.securityPolicy->
32353 setSecurityKeys(rg->securityPolicyContext, &signingKey,
32354 &encryptingKey, &keyNonce);
32355}
32356#endif
32357
32358/* Freezing of the configuration */
32359
32360UA_StatusCode
32361UA_Server_freezeReaderGroupConfiguration(UA_Server *server,
32362 const UA_NodeId readerGroupId) {
32363 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32364 if(!rg)
32365 return UA_STATUSCODE_BADNOTFOUND;
32366
32367 /* PubSubConnection freezeCounter++ */
32368 UA_NodeId pubSubConnectionId = rg->linkedConnection;
32369 UA_PubSubConnection *pubSubConnection =
32370 UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
32371 pubSubConnection->configurationFreezeCounter++;
32372 pubSubConnection->configurationFrozen = UA_TRUE;
32373
32374 /* ReaderGroup freeze */
32375 /* TODO: Clarify on the freeze functionality in multiple DSR, multiple
32376 * networkMessage conf in a RG */
32377 rg->configurationFrozen = UA_TRUE;
32378
32379 /* DataSetReader freeze */
32380 UA_DataSetReader *dataSetReader;
32381 UA_UInt16 dsrCount = 0;
32382 LIST_FOREACH(dataSetReader, &rg->readers, listEntry){
32383 dataSetReader->configurationFrozen = UA_TRUE;
32384 dsrCount++;
32385 /* TODO: Configuration frozen for subscribedDataSet once
32386 * UA_Server_DataSetReader_addTargetVariables API modified to support
32387 * adding target variable one by one or in a group stored in a list. */
32388 }
32389
32390 /* Not rt, we don't have to adjust anything */
32391 if(rg->config.rtLevel != UA_PUBSUB_RT_FIXED_SIZE)
32392 return UA_STATUSCODE_GOOD;
32393
32394 if(dsrCount > 1) {
32395 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32396 "Mutiple DSR in a readerGroup not supported in RT "
32397 "fixed size configuration");
32398 return UA_STATUSCODE_BADNOTIMPLEMENTED;
32399 }
32400
32401 dataSetReader = LIST_FIRST(&rg->readers);
32402
32403 /* Support only to UADP encoding */
32404 if(dataSetReader->config.messageSettings.content.decoded.type !=
32405 &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) {
32406 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32407 "PubSub-RT configuration fail: Non-RT capable encoding.");
32408 return UA_STATUSCODE_BADNOTSUPPORTED;
32409 }
32410
32411 size_t fieldsSize = dataSetReader->config.dataSetMetaData.fieldsSize;
32412 for(size_t i = 0; i < fieldsSize; i++) {
32413 UA_FieldTargetVariable *tv =
32414 &dataSetReader->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i];
32415 const UA_VariableNode *rtNode = (const UA_VariableNode *)
32416 UA_NODESTORE_GET(server, &tv->targetVariable.targetNodeId);
32417 if(rtNode != NULL &&
32418 rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) {
32419 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32420 "PubSub-RT configuration fail: PDS contains field "
32421 "without external data source.");
32422 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
32423 return UA_STATUSCODE_BADNOTSUPPORTED;
32424 }
32425
32426 UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode);
32427
32428 UA_FieldMetaData *field = &dataSetReader->config.dataSetMetaData.fields[i];
32429 if((UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_STRING].typeId) ||
32430 UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) &&
32431 field->maxStringLength == 0) {
32432 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32433 "PubSub-RT configuration fail: "
32434 "PDS contains String/ByteString with dynamic length.");
32435 return UA_STATUSCODE_BADNOTSUPPORTED;
32436 } else if(!UA_DataType_isNumeric(UA_findDataType(&field->dataType)) &&
32437 !UA_NodeId_equal(&field->dataType, &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) {
32438 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32439 "PubSub-RT configuration fail: "
32440 "PDS contains variable with dynamic size.");
32441 return UA_STATUSCODE_BADNOTSUPPORTED;
32442 }
32443 }
32444
32445 UA_DataSetMessage *dsm = (UA_DataSetMessage *) UA_calloc(1, sizeof(UA_DataSetMessage));
32446 if(!dsm) {
32447 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32448 "PubSub RT Offset calculation: DSM creation failed");
32449 return UA_STATUSCODE_BADOUTOFMEMORY;
32450 }
32451
32452 /* Generate the DSM */
32453 UA_StatusCode res = UA_DataSetReader_generateDataSetMessage(server, dsm, dataSetReader);
32454 if(res != UA_STATUSCODE_GOOD) {
32455 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32456 "PubSub RT Offset calculation: DataSetMessage generation failed");
32457 UA_DataSetMessage_clear(dsm);
32458 UA_free(dsm);
32459 return UA_STATUSCODE_BADINTERNALERROR;
32460 }
32461
32462 /* Generate data set messages - Considering 1 DSM as max */
32463 UA_UInt16 *dsWriterIds = (UA_UInt16 *)UA_calloc(1, sizeof(UA_UInt16));
32464 if(!dsWriterIds) {
32465 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32466 "PubSub RT Offset calculation: DataSetWriterId creation failed");
32467 UA_DataSetMessage_clear(dsm);
32468 UA_free(dsm);
32469 return UA_STATUSCODE_BADOUTOFMEMORY;
32470 }
32471 *dsWriterIds = dataSetReader->config.dataSetWriterId;
32472
32473 UA_NetworkMessage *networkMessage = (UA_NetworkMessage *)UA_calloc(1, sizeof(UA_NetworkMessage));
32474 if(!networkMessage) {
32475 UA_free(dsWriterIds);
32476 UA_DataSetMessage_clear(dsm);
32477 UA_free(dsm);
32478 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32479 "PubSub RT Offset calculation: Network message creation failed");
32480 return UA_STATUSCODE_BADOUTOFMEMORY;
32481 }
32482
32483 res = UA_DataSetReader_generateNetworkMessage(pubSubConnection, dataSetReader, dsm,
32484 dsWriterIds, 1, networkMessage);
32485 if(res != UA_STATUSCODE_GOOD) {
32486 UA_free(networkMessage->payload.dataSetPayload.sizes);
32487 UA_free(networkMessage);
32488 UA_free(dsWriterIds);
32489 UA_DataSetMessage_clear(dsm);
32490 UA_free(dsm);
32491 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32492 "PubSub RT Offset calculation: NetworkMessage generation failed");
32493 return UA_STATUSCODE_BADINTERNALERROR;
32494 }
32495
32496 /* Fix the offsets necessary to decode */
32497 memset(&dataSetReader->bufferedMessage, 0, sizeof(UA_NetworkMessageOffsetBuffer));
32498 UA_NetworkMessage_calcSizeBinary(networkMessage, &dataSetReader->bufferedMessage);
32499 dataSetReader->bufferedMessage.RTsubscriberEnabled = true;
32500 dataSetReader->bufferedMessage.nm = networkMessage;
32501
32502 return UA_STATUSCODE_GOOD;
32503}
32504
32505UA_StatusCode
32506UA_Server_unfreezeReaderGroupConfiguration(UA_Server *server,
32507 const UA_NodeId readerGroupId) {
32508 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupId);
32509 if(!rg)
32510 return UA_STATUSCODE_BADNOTFOUND;
32511
32512 /* PubSubConnection freezeCounter-- */
32513 UA_NodeId pubSubConnectionId = rg->linkedConnection;
32514 UA_PubSubConnection *pubSubConnection =
32515 UA_PubSubConnection_findConnectionbyId(server, pubSubConnectionId);
32516 pubSubConnection->configurationFreezeCounter--;
32517 if(pubSubConnection->configurationFreezeCounter == 0){
32518 pubSubConnection->configurationFrozen = UA_FALSE;
32519 }
32520
32521 /* ReaderGroup unfreeze */
32522 rg->configurationFrozen = UA_FALSE;
32523
32524 /* DataSetReader unfreeze */
32525 UA_DataSetReader *dataSetReader;
32526 LIST_FOREACH(dataSetReader, &rg->readers, listEntry) {
32527 UA_NetworkMessageOffsetBuffer_clear(&dataSetReader->bufferedMessage);
32528 dataSetReader->configurationFrozen = false;
32529 }
32530
32531 return UA_STATUSCODE_GOOD;
32532}
32533
32534/* This triggers the collection and reception of NetworkMessages and the
32535 * contained DataSetMessages. */
32536void
32537UA_ReaderGroup_subscribeCallback(UA_Server *server,
32538 UA_ReaderGroup *readerGroup) {
32539 // TODO: feedback for debug-assert vs runtime-check
32540 UA_assert(server);
32541 UA_assert(readerGroup);
32542
32543 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
32544 "PubSub subscribe callback");
32545
32546 UA_PubSubConnection *connection =
32547 UA_PubSubConnection_findConnectionbyId(server, readerGroup->linkedConnection);
32548 if(!connection) {
32549 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32550 "SubscribeCallback(): Find linked connection failed");
32551 UA_ReaderGroup_setPubSubState(server, UA_PUBSUBSTATE_ERROR, readerGroup);
32552 return;
32553 }
32554
32555 receiveBufferedNetworkMessage(server, readerGroup, connection);
32556}
32557
32558/* Add new subscribeCallback. The first execution is triggered directly after
32559 * creation. */
32560UA_StatusCode
32561UA_ReaderGroup_addSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
32562 UA_StatusCode retval = UA_STATUSCODE_GOOD;
32563 if(readerGroup->config.pubsubManagerCallback.addCustomCallback)
32564 retval = readerGroup->config.pubsubManagerCallback.
32565 addCustomCallback(server, readerGroup->identifier,
32566 (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
32567 readerGroup, readerGroup->config.subscribingInterval,
32568 NULL, // TODO: Send base time from reader group config
32569 // TODO: Send timer policy from reader group config
32570 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
32571 &readerGroup->subscribeCallbackId);
32572 else {
32573 if(readerGroup->config.enableBlockingSocket == UA_TRUE) {
32574 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32575 "addSubscribeCallback() failed, blocking socket "
32576 "functionality only supported in customcallback");
32577 return UA_STATUSCODE_BADNOTSUPPORTED;
32578 }
32579
32580 retval = UA_PubSubManager_addRepeatedCallback(server,
32581 (UA_ServerCallback)UA_ReaderGroup_subscribeCallback,
32582 readerGroup, readerGroup->config.subscribingInterval,
32583 NULL, // TODO: Send base time from reader group config
32584 // TODO: Send timer policy from reader group config
32585 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME,
32586 &readerGroup->subscribeCallbackId);
32587 }
32588
32589 /* Run once after creation */
32590 /* When using blocking socket functionality, the server mechanism might get
32591 * blocked. It is highly recommended to use custom callback when using
32592 * blockingsocket. */
32593 if(readerGroup->config.enableBlockingSocket != UA_TRUE)
32594 UA_ReaderGroup_subscribeCallback(server, readerGroup);
32595
32596 return retval;
32597}
32598
32599void
32600UA_ReaderGroup_removeSubscribeCallback(UA_Server *server, UA_ReaderGroup *readerGroup) {
32601 if(readerGroup->config.pubsubManagerCallback.removeCustomCallback)
32602 readerGroup->config.pubsubManagerCallback.
32603 removeCustomCallback(server, readerGroup->identifier,
32604 readerGroup->subscribeCallbackId);
32605 else
32606 UA_PubSubManager_removeRepeatedPubSubCallback(server,
32607 readerGroup->subscribeCallbackId);
32608}
32609
32610#endif /* UA_ENABLE_PUBSUB */
32611
32612/**** amalgamated original file "/src/pubsub/ua_pubsub_manager.c" ****/
32613
32614/* This Source Code Form is subject to the terms of the Mozilla Public
32615 * License, v. 2.0. If a copy of the MPL was not distributed with this
32616 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
32617 *
32618 * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner)
32619 * Copyright (c) 2018 Fraunhofer IOSB (Author: Julius Pfrommer)
32620 */
32621
32622
32623#ifdef UA_ENABLE_PUBSUB /* conditional compilation */
32624
32625
32626#define UA_DATETIMESTAMP_2000 125911584000000000
32627
32628UA_StatusCode
32629UA_Server_addPubSubConnection(UA_Server *server,
32630 const UA_PubSubConnectionConfig *connectionConfig,
32631 UA_NodeId *connectionIdentifier) {
32632 /* Find the matching UA_PubSubTransportLayers */
32633 UA_PubSubTransportLayer *tl = NULL;
32634 for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
32635 if(connectionConfig &&
32636 UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
32637 &connectionConfig->transportProfileUri)) {
32638 tl = &server->config.pubSubConfig.transportLayers[i];
32639 }
32640 }
32641 if(!tl) {
32642 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32643 "PubSub Connection creation failed. Requested transport layer not found.");
32644 return UA_STATUSCODE_BADNOTFOUND;
32645 }
32646
32647 /* Create a copy of the connection config */
32648 UA_PubSubConnectionConfig *tmpConnectionConfig = (UA_PubSubConnectionConfig *)
32649 UA_calloc(1, sizeof(UA_PubSubConnectionConfig));
32650 if(!tmpConnectionConfig){
32651 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32652 "PubSub Connection creation failed. Out of Memory.");
32653 return UA_STATUSCODE_BADOUTOFMEMORY;
32654 }
32655
32656 UA_StatusCode retval = UA_PubSubConnectionConfig_copy(connectionConfig, tmpConnectionConfig);
32657 if(retval != UA_STATUSCODE_GOOD){
32658 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32659 "PubSub Connection creation failed. Could not copy the config.");
32660 return retval;
32661 }
32662
32663 /* Create new connection and add to UA_PubSubManager */
32664 UA_PubSubConnection *newConnectionsField = (UA_PubSubConnection *)
32665 UA_calloc(1, sizeof(UA_PubSubConnection));
32666 if(!newConnectionsField) {
32667 UA_PubSubConnectionConfig_clear(tmpConnectionConfig);
32668 UA_free(tmpConnectionConfig);
32669 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32670 "PubSub Connection creation failed. Out of Memory.");
32671 return UA_STATUSCODE_BADOUTOFMEMORY;
32672 }
32673 newConnectionsField->componentType = UA_PUBSUB_COMPONENT_CONNECTION;
32674 if (server->pubSubManager.connectionsSize != 0)
32675 TAILQ_INSERT_TAIL(&server->pubSubManager.connections, newConnectionsField, listEntry);
32676 else {
32677 TAILQ_INIT(&server->pubSubManager.connections);
32678 TAILQ_INSERT_HEAD(&server->pubSubManager.connections, newConnectionsField, listEntry);
32679 }
32680
32681 server->pubSubManager.connectionsSize++;
32682
32683 LIST_INIT(&newConnectionsField->writerGroups);
32684 newConnectionsField->config = tmpConnectionConfig;
32685
32686 /* Open the channel */
32687 newConnectionsField->channel = tl->createPubSubChannel(newConnectionsField->config);
32688 if(!newConnectionsField->channel) {
32689 UA_PubSubConnection_clear(server, newConnectionsField);
32690 TAILQ_REMOVE(&server->pubSubManager.connections, newConnectionsField, listEntry);
32691 server->pubSubManager.connectionsSize--;
32692 UA_free(newConnectionsField);
32693 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32694 "PubSub Connection creation failed. Transport layer creation problem.");
32695 return UA_STATUSCODE_BADINTERNALERROR;
32696 }
32697
32698#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32699 /* Internally createa a unique id */
32700 addPubSubConnectionRepresentation(server, newConnectionsField);
32701#else
32702 /* Create a unique NodeId that does not correspond to a Node */
32703 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager,
32704 &newConnectionsField->identifier);
32705#endif
32706
32707 if(connectionIdentifier)
32708 UA_NodeId_copy(&newConnectionsField->identifier, connectionIdentifier);
32709
32710 return UA_STATUSCODE_GOOD;
32711}
32712
32713UA_StatusCode
32714UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection) {
32715 //search the identified Connection and store the Connection index
32716 UA_PubSubConnection *currentConnection = UA_PubSubConnection_findConnectionbyId(server, connection);
32717 if(!currentConnection)
32718 return UA_STATUSCODE_BADNOTFOUND;
32719
32720 UA_WriterGroup *wg, *wg_tmp;
32721 LIST_FOREACH_SAFE(wg, &currentConnection->writerGroups, listEntry, wg_tmp) {
32722 UA_Server_unfreezeWriterGroupConfiguration(server, wg->identifier);
32723 UA_Server_removeWriterGroup(server, wg->identifier);
32724 }
32725
32726 UA_ReaderGroup *rg, *rg_tmp;
32727 LIST_FOREACH_SAFE(rg, &currentConnection->readerGroups, listEntry, rg_tmp) {
32728 UA_Server_unfreezeReaderGroupConfiguration(server, rg->identifier);
32729 UA_Server_removeReaderGroup(server, rg->identifier);
32730 }
32731
32732#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32733 removePubSubConnectionRepresentation(server, currentConnection);
32734#endif
32735 server->pubSubManager.connectionsSize--;
32736
32737 UA_PubSubConnection_clear(server, currentConnection);
32738 TAILQ_REMOVE(&server->pubSubManager.connections, currentConnection, listEntry);
32739 UA_free(currentConnection);
32740 return UA_STATUSCODE_GOOD;
32741}
32742
32743UA_StatusCode
32744UA_PubSubConnection_regist(UA_Server *server, UA_NodeId *connectionIdentifier) {
32745 UA_PubSubConnection *connection =
32746 UA_PubSubConnection_findConnectionbyId(server, *connectionIdentifier);
32747 if(!connection)
32748 return UA_STATUSCODE_BADNOTFOUND;
32749
32750 if(connection->isRegistered) {
32751 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "Connection already registered");
32752 return UA_STATUSCODE_GOOD;
32753 }
32754
32755 UA_StatusCode retval = connection->channel->regist(connection->channel, NULL, NULL);
32756 if(retval != UA_STATUSCODE_GOOD)
32757 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32758 "register channel failed: 0x%" PRIx32 "!", retval);
32759
32760 connection->isRegistered = UA_TRUE;
32761 return retval;
32762}
32763
32764UA_AddPublishedDataSetResult
32765UA_Server_addPublishedDataSet(UA_Server *server,
32766 const UA_PublishedDataSetConfig *publishedDataSetConfig,
32767 UA_NodeId *pdsIdentifier) {
32768 UA_AddPublishedDataSetResult result = {UA_STATUSCODE_BADINVALIDARGUMENT, 0, NULL, {0, 0}};
32769 if(!publishedDataSetConfig){
32770 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32771 "PublishedDataSet creation failed. No config passed in.");
32772 return result;
32773 }
32774
32775 if(publishedDataSetConfig->publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS){
32776 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32777 "PublishedDataSet creation failed. Unsupported PublishedDataSet type.");
32778 return result;
32779 }
32780
32781 /* Create new PDS and add to UA_PubSubManager */
32782 UA_PublishedDataSet *newPDS = (UA_PublishedDataSet *)
32783 UA_calloc(1, sizeof(UA_PublishedDataSet));
32784 if(!newPDS) {
32785 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32786 "PublishedDataSet creation failed. Out of Memory.");
32787 result.addResult = UA_STATUSCODE_BADOUTOFMEMORY;
32788 return result;
32789 }
32790 TAILQ_INIT(&newPDS->fields);
32791
32792 UA_PublishedDataSetConfig *newConfig = &newPDS->config;
32793
32794 /* Deep copy the given connection config */
32795 UA_StatusCode res = UA_PublishedDataSetConfig_copy(publishedDataSetConfig, newConfig);
32796 if(res != UA_STATUSCODE_GOOD){
32797 UA_free(newPDS);
32798 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
32799 "PublishedDataSet creation failed. Configuration copy failed.");
32800 result.addResult = UA_STATUSCODE_BADINTERNALERROR;
32801 return result;
32802 }
32803
32804 /* TODO: Parse template config and add fields (later PubSub batch) */
32805 if(newConfig->publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE) {
32806 }
32807
32808 /* Fill the DataSetMetaData */
32809 result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference();
32810 result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference();
32811 switch(newConfig->publishedDataSetType) {
32812 case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE:
32813 res = UA_STATUSCODE_BADNOTSUPPORTED;
32814 break;
32815 case UA_PUBSUB_DATASET_PUBLISHEDEVENTS:
32816 res = UA_STATUSCODE_BADNOTSUPPORTED;
32817 break;
32818 case UA_PUBSUB_DATASET_PUBLISHEDITEMS:
32819 newPDS->dataSetMetaData.configurationVersion.majorVersion =
32820 UA_PubSubConfigurationVersionTimeDifference();
32821 newPDS->dataSetMetaData.configurationVersion.minorVersion =
32822 UA_PubSubConfigurationVersionTimeDifference();
32823 newPDS->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC("", "");
32824 newPDS->dataSetMetaData.dataSetClassId = UA_GUID_NULL;
32825 res = UA_String_copy(&newConfig->name, &newPDS->dataSetMetaData.name);
32826 break;
32827 case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE:
32828 res = UA_DataSetMetaDataType_copy(&newConfig->config.itemsTemplate.metaData,
32829 &newPDS->dataSetMetaData);
32830 break;
32831 default:
32832 res = UA_STATUSCODE_BADINTERNALERROR;
32833 }
32834
32835 /* Abort? */
32836 result.addResult = res;
32837 if(result.addResult != UA_STATUSCODE_GOOD) {
32838 UA_PublishedDataSetConfig_clear(newConfig);
32839 UA_free(newPDS);
32840 return result;
32841 }
32842
32843 /* Insert into the queue of the manager */
32844 if(server->pubSubManager.publishedDataSetsSize != 0) {
32845 TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets,
32846 newPDS, listEntry);
32847 } else {
32848 TAILQ_INIT(&server->pubSubManager.publishedDataSets);
32849 TAILQ_INSERT_HEAD(&server->pubSubManager.publishedDataSets,
32850 newPDS, listEntry);
32851 }
32852 server->pubSubManager.publishedDataSetsSize++;
32853
32854#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32855 /* Create representation and unique id */
32856 addPublishedDataItemsRepresentation(server, newPDS);
32857#else
32858 /* Generate unique nodeId */
32859 UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, &newPDS->identifier);
32860#endif
32861 if(pdsIdentifier)
32862 UA_NodeId_copy(&newPDS->identifier, pdsIdentifier);
32863
32864 return result;
32865}
32866
32867UA_StatusCode
32868UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) {
32869 //search the identified PublishedDataSet and store the PDS index
32870 UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, pds);
32871 if(!publishedDataSet){
32872 return UA_STATUSCODE_BADNOTFOUND;
32873 }
32874 if(publishedDataSet->configurationFrozen){
32875 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
32876 "Remove PublishedDataSet failed. PublishedDataSet is frozen.");
32877 return UA_STATUSCODE_BADCONFIGURATIONERROR;
32878 }
32879
32880 //search for referenced writers -> delete this writers. (Standard: writer must be connected with PDS)
32881 UA_PubSubConnection *tmpConnectoin;
32882 TAILQ_FOREACH(tmpConnectoin, &server->pubSubManager.connections, listEntry){
32883 UA_WriterGroup *writerGroup;
32884 LIST_FOREACH(writerGroup, &tmpConnectoin->writerGroups, listEntry){
32885 UA_DataSetWriter *currentWriter, *tmpWriterGroup;
32886 LIST_FOREACH_SAFE(currentWriter, &writerGroup->writers, listEntry, tmpWriterGroup){
32887 if(UA_NodeId_equal(&currentWriter->connectedDataSet, &publishedDataSet->identifier)){
32888 UA_Server_removeDataSetWriter(server, currentWriter->identifier);
32889 }
32890 }
32891 }
32892 }
32893#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32894 removePublishedDataSetRepresentation(server, publishedDataSet);
32895#endif
32896 UA_PublishedDataSet_clear(server, publishedDataSet);
32897 server->pubSubManager.publishedDataSetsSize--;
32898
32899 TAILQ_REMOVE(&server->pubSubManager.publishedDataSets, publishedDataSet, listEntry);
32900 UA_free(publishedDataSet);
32901 return UA_STATUSCODE_GOOD;
32902}
32903
32904/* Calculate the time difference between current time and UTC (00:00) on January
32905 * 1, 2000. */
32906UA_UInt32
32907UA_PubSubConfigurationVersionTimeDifference(void) {
32908 UA_UInt32 timeDiffSince2000 = (UA_UInt32) (UA_DateTime_now() - UA_DATETIMESTAMP_2000);
32909 return timeDiffSince2000;
32910}
32911
32912/* Generate a new unique NodeId. This NodeId will be used for the information
32913 * model representation of PubSub entities. */
32914#ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL
32915void
32916UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId) {
32917 *nodeId = UA_NODEID_NUMERIC(1, ++psm->uniqueIdCount);
32918}
32919#endif
32920
32921UA_Guid
32922UA_PubSubManager_generateUniqueGuid(UA_Server *server) {
32923 while(true) {
32924 UA_NodeId testId = UA_NODEID_GUID(1, UA_Guid_random());
32925 const UA_Node *testNode = UA_NODESTORE_GET(server, &testId);
32926 if(!testNode)
32927 return testId.identifier.guid;
32928 UA_NODESTORE_RELEASE(server, testNode);
32929 }
32930}
32931
32932/* Delete the current PubSub configuration including all nested members. This
32933 * action also delete the configured PubSub transport Layers. */
32934void
32935UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) {
32936 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER, "PubSub cleanup was called.");
32937
32938 /* Stop and unfreeze all WriterGroups */
32939 UA_PubSubConnection *tmpConnection;
32940 TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry){
32941 for(size_t i = 0; i < pubSubManager->connectionsSize; i++) {
32942 UA_WriterGroup *writerGroup;
32943 LIST_FOREACH(writerGroup, &tmpConnection->writerGroups, listEntry) {
32944 UA_WriterGroup_setPubSubState(server, UA_PUBSUBSTATE_DISABLED, writerGroup);
32945 UA_Server_unfreezeWriterGroupConfiguration(server, writerGroup->identifier);
32946 }
32947 }
32948 }
32949
32950 //free the currently configured transport layers
32951 if(server->config.pubSubConfig.transportLayersSize > 0) {
32952 UA_free(server->config.pubSubConfig.transportLayers);
32953 server->config.pubSubConfig.transportLayersSize = 0;
32954 }
32955
32956 //remove Connections and WriterGroups
32957 UA_PubSubConnection *tmpConnection1, *tmpConnection2;
32958 TAILQ_FOREACH_SAFE(tmpConnection1, &server->pubSubManager.connections, listEntry, tmpConnection2){
32959 UA_Server_removePubSubConnection(server, tmpConnection1->identifier);
32960 }
32961 UA_PublishedDataSet *tmpPDS1, *tmpPDS2;
32962 TAILQ_FOREACH_SAFE(tmpPDS1, &server->pubSubManager.publishedDataSets, listEntry, tmpPDS2){
32963 UA_Server_removePublishedDataSet(server, tmpPDS1->identifier);
32964 }
32965}
32966
32967/***********************************/
32968/* PubSub Jobs abstraction */
32969/***********************************/
32970
32971/* Default Timer based PubSub Callbacks */
32972
32973UA_StatusCode
32974UA_PubSubManager_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
32975 void *data, UA_Double interval_ms, UA_DateTime *baseTime,
32976 UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) {
32977 return UA_Timer_addRepeatedCallback(&server->timer, (UA_ApplicationCallback)callback,
32978 server, data, interval_ms, baseTime, timerPolicy, callbackId);
32979}
32980
32981UA_StatusCode
32982UA_PubSubManager_changeRepeatedCallback(UA_Server *server, UA_UInt64 callbackId,
32983 UA_Double interval_ms, UA_DateTime *baseTime,
32984 UA_TimerPolicy timerPolicy) {
32985 return UA_Timer_changeRepeatedCallback(&server->timer, callbackId, interval_ms, baseTime, timerPolicy);
32986}
32987
32988void
32989UA_PubSubManager_removeRepeatedPubSubCallback(UA_Server *server, UA_UInt64 callbackId) {
32990 UA_Timer_removeCallback(&server->timer, callbackId);
32991}
32992
32993
32994#ifdef UA_ENABLE_PUBSUB_MONITORING
32995
32996static UA_StatusCode
32997UA_PubSubComponent_createMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
32998 UA_PubSubMonitoringType eMonitoringType, void *data, UA_ServerCallback callback) {
32999
33000 if ((!server) || (!data)) {
33001 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_createMonitoring(): "
33002 "null pointer param");
33003 return UA_STATUSCODE_BADINVALIDARGUMENT;
33004 }
33005 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33006 switch (eComponentType) {
33007 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33008 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33009 switch (eMonitoringType) {
33010 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
33011 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
33012 "- MessageReceiveTimeout", (UA_Int32) reader->config.name.length, reader->config.name.data);
33013 reader->msgRcvTimeoutTimerCallback = callback;
33014 break;
33015 default:
33016 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): 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_createMonitoring(): 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_startMonitoring(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_startMonitoring(): "
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 /* use a timed callback, because one notification is enough,
33050 we assume that MessageReceiveTimeout configuration is in [ms], we do not handle or check fractions */
33051 UA_UInt64 interval = (UA_UInt64)(reader->config.messageReceiveTimeout * UA_DATETIME_MSEC);
33052 ret = UA_Timer_addTimedCallback(&server->timer, (UA_ApplicationCallback) reader->msgRcvTimeoutTimerCallback,
33053 server, reader, UA_DateTime_nowMonotonic() + (UA_DateTime) interval, &(reader->msgRcvTimeoutTimerId));
33054 if (ret == UA_STATUSCODE_GOOD) {
33055 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33056 "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s'- MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
33057 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33058 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33059 } else {
33060 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33061 "Error UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: start timer failed",
33062 (UA_Int32) reader->config.name.length, reader->config.name.data);
33063 }
33064 break;
33065 }
33066 default:
33067 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' "
33068 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33069 eMonitoringType);
33070 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33071 break;
33072 }
33073 break;
33074 }
33075 default:
33076 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33077 "Error UA_PubSubComponent_startMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33078 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33079 break;
33080 }
33081 return ret;
33082}
33083
33084static UA_StatusCode
33085UA_PubSubComponent_stopMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33086 UA_PubSubMonitoringType eMonitoringType, void *data) {
33087
33088 if ((!server) || (!data)) {
33089 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_stopMonitoring(): "
33090 "null pointer param");
33091 return UA_STATUSCODE_BADINVALIDARGUMENT;
33092 }
33093
33094 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33095 switch (eComponentType) {
33096 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33097 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33098 switch (eMonitoringType) {
33099 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
33100 UA_Timer_removeCallback(&server->timer, reader->msgRcvTimeoutTimerId);
33101 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33102 "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: MessageReceiveTimeout = '%f' "
33103 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33104 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33105 break;
33106 }
33107 default:
33108 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' "
33109 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33110 eMonitoringType);
33111 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33112 break;
33113 }
33114 break;
33115 }
33116 default:
33117 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33118 "Error UA_PubSubComponent_stopMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33119 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33120 break;
33121 }
33122 return ret;
33123}
33124
33125static UA_StatusCode
33126UA_PubSubComponent_updateMonitoringInterval(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33127 UA_PubSubMonitoringType eMonitoringType, void *data)
33128{
33129 if ((!server) || (!data)) {
33130 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_updateMonitoringInterval(): "
33131 "null pointer param");
33132 return UA_STATUSCODE_BADINVALIDARGUMENT;
33133 }
33134 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33135 switch (eComponentType) {
33136 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33137 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33138 switch (eMonitoringType) {
33139 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: {
33140 ret = UA_Timer_changeRepeatedCallback(&server->timer, reader->msgRcvTimeoutTimerId,
33141 reader->config.messageReceiveTimeout, NULL,
33142 UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
33143 if (ret == UA_STATUSCODE_GOOD) {
33144 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33145 "UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s' - MessageReceiveTimeout: new MessageReceiveTimeout = '%f' "
33146 "Timer Id = '%u'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33147 reader->config.messageReceiveTimeout, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33148 } else {
33149 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33150 "Error UA_PubSubComponent_updateMonitoringInterval(): DataSetReader '%.*s': update timer interval failed",
33151 (UA_Int32) reader->config.name.length, reader->config.name.data);
33152 }
33153 break;
33154 }
33155 default:
33156 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' "
33157 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33158 eMonitoringType);
33159 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33160 break;
33161 }
33162 break;
33163 }
33164 default:
33165 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33166 "Error UA_PubSubComponent_updateMonitoringInterval(): PubSub component type '%i' is not supported", eComponentType);
33167 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33168 break;
33169 }
33170 return ret;
33171}
33172
33173static UA_StatusCode
33174UA_PubSubComponent_deleteMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType,
33175 UA_PubSubMonitoringType eMonitoringType, void *data) {
33176
33177 if ((!server) || (!data)) {
33178 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Error UA_PubSubComponent_deleteMonitoring(): "
33179 "null pointer param");
33180 return UA_STATUSCODE_BADINVALIDARGUMENT;
33181 }
33182 UA_StatusCode ret = UA_STATUSCODE_GOOD;
33183 switch (eComponentType) {
33184 case UA_PUBSUB_COMPONENT_DATASETREADER: {
33185 UA_DataSetReader *reader = (UA_DataSetReader*) data;
33186 switch (eMonitoringType) {
33187 case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT:
33188 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
33189 "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' - MessageReceiveTimeout: Timer Id = '%u'",
33190 (UA_Int32) reader->config.name.length, reader->config.name.data, (UA_UInt32) reader->msgRcvTimeoutTimerId);
33191 break;
33192 default:
33193 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' "
33194 "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data,
33195 eMonitoringType);
33196 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33197 break;
33198 }
33199 break;
33200 }
33201 default:
33202 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
33203 "Error UA_PubSubComponent_deleteMonitoring(): PubSub component type '%i' is not supported", eComponentType);
33204 ret = UA_STATUSCODE_BADNOTSUPPORTED;
33205 break;
33206 }
33207 return ret;
33208}
33209
33210UA_StatusCode
33211UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface) {
33212 if (monitoringInterface == NULL) {
33213 return UA_STATUSCODE_BADINVALIDARGUMENT;
33214 }
33215 monitoringInterface->createMonitoring = UA_PubSubComponent_createMonitoring;
33216 monitoringInterface->startMonitoring = UA_PubSubComponent_startMonitoring;
33217 monitoringInterface->stopMonitoring = UA_PubSubComponent_stopMonitoring;
33218 monitoringInterface->updateMonitoringInterval = UA_PubSubComponent_updateMonitoringInterval;
33219 monitoringInterface->deleteMonitoring = UA_PubSubComponent_deleteMonitoring;
33220 return UA_STATUSCODE_GOOD;
33221}
33222
33223#endif /* UA_ENABLE_PUBSUB_MONITORING */
33224
33225#endif /* UA_ENABLE_PUBSUB */
33226
33227/**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.c" ****/
33228
33229/* This Source Code Form is subject to the terms of the Mozilla Public
33230 * License, v. 2.0. If a copy of the MPL was not distributed with this
33231 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
33232 *
33233 * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner)
33234 * Copyright (c) 2019-2021 Kalycito Infotech Private Limited
33235 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
33236 * Copyright (c) 2020 Thomas Fischer, Siemens AG
33237 */
33238
33239
33240#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
33241#endif
33242
33243#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */
33244
33245typedef struct {
33246 UA_NodeId parentNodeId;
33247 UA_UInt32 parentClassifier;
33248 UA_UInt32 elementClassiefier;
33249} UA_NodePropertyContext;
33250
33251static UA_StatusCode
33252writePubSubNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v,
33253 size_t length, const UA_DataType *type) {
33254 UA_Variant var;
33255 UA_Variant_init(&var);
33256 UA_Variant_setArray(&var, v, length, type);
33257 return UA_Server_writeValue(server, UA_NODEID_NUMERIC(0, id), var);
33258}
33259
33260static UA_NodeId
33261findSingleChildNode(UA_Server *server, UA_QualifiedName targetName,
33262 UA_NodeId referenceTypeId, UA_NodeId startingNode){
33263 UA_NodeId resultNodeId;
33264 UA_RelativePathElement rpe;
33265 UA_RelativePathElement_init(&rpe);
33266 rpe.referenceTypeId = referenceTypeId;
33267 rpe.isInverse = false;
33268 rpe.includeSubtypes = false;
33269 rpe.targetName = targetName;
33270 UA_BrowsePath bp;
33271 UA_BrowsePath_init(&bp);
33272 bp.startingNode = startingNode;
33273 bp.relativePath.elementsSize = 1;
33274 bp.relativePath.elements = &rpe;
33275 UA_BrowsePathResult bpr = UA_Server_translateBrowsePathToNodeIds(server, &bp);
33276 if(bpr.statusCode != UA_STATUSCODE_GOOD ||
33277 bpr.targetsSize < 1)
33278 return UA_NODEID_NULL;
33279 UA_StatusCode res = UA_NodeId_copy(&bpr.targets[0].targetId.nodeId, &resultNodeId);
33280 if(res != UA_STATUSCODE_GOOD){
33281 UA_BrowsePathResult_clear(&bpr);
33282 return UA_NODEID_NULL;
33283 }
33284 UA_BrowsePathResult_clear(&bpr);
33285 return resultNodeId;
33286}
33287
33288static void
33289onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
33290 const UA_NodeId *nodeid, void *context,
33291 const UA_NumericRange *range, const UA_DataValue *data) {
33292 UA_Variant value;
33293 UA_Variant_init(&value);
33294 const UA_NodePropertyContext *nodeContext = (const UA_NodePropertyContext*)context;
33295 const UA_NodeId *myNodeId = &nodeContext->parentNodeId;
33296
33297 switch(nodeContext->parentClassifier){
33298 case UA_NS0ID_PUBSUBCONNECTIONTYPE: {
33299 UA_PubSubConnection *pubSubConnection =
33300 UA_PubSubConnection_findConnectionbyId(server, *myNodeId);
33301 switch(nodeContext->elementClassiefier) {
33302 case UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID:
33303 if(pubSubConnection->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
33304 UA_Variant_setScalarCopy(&value, &pubSubConnection->config->publisherId.numeric,
33305 &UA_TYPES[UA_TYPES_STRING]);
33306 } else {
33307 UA_Variant_setScalarCopy(&value, &pubSubConnection->config->publisherId.numeric,
33308 &UA_TYPES[UA_TYPES_UINT32]);
33309 }
33310 break;
33311 default:
33312 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33313 "Read error! Unknown property.");
33314 }
33315 break;
33316 }
33317 case UA_NS0ID_DATASETREADERTYPE: {
33318 UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, *myNodeId);
33319 if(!dataSetReader)
33320 return;
33321
33322 switch(nodeContext->elementClassiefier) {
33323 case UA_NS0ID_DATASETREADERTYPE_PUBLISHERID:
33324 UA_Variant_setScalarCopy(&value, dataSetReader->config.publisherId.data,
33325 dataSetReader->config.publisherId.type);
33326 break;
33327 default:
33328 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33329 "Read error! Unknown property.");
33330 }
33331 break;
33332 }
33333 case UA_NS0ID_WRITERGROUPTYPE: {
33334 UA_WriterGroup *writerGroup = UA_WriterGroup_findWGbyId(server, *myNodeId);
33335 if(!writerGroup)
33336 return;
33337 switch(nodeContext->elementClassiefier){
33338 case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL:
33339 UA_Variant_setScalarCopy(&value, &writerGroup->config.publishingInterval,
33340 &UA_TYPES[UA_TYPES_DURATION]);
33341 break;
33342 default:
33343 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33344 "Read error! Unknown property.");
33345 }
33346 break;
33347 }
33348 case UA_NS0ID_DATASETWRITERTYPE: {
33349 UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, *myNodeId);
33350 if(!dataSetWriter)
33351 return;
33352
33353 switch(nodeContext->elementClassiefier) {
33354 case UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID:
33355 UA_Variant_setScalarCopy(&value, &dataSetWriter->config.dataSetWriterId,
33356 &UA_TYPES[UA_TYPES_UINT16]);
33357 break;
33358 default:
33359 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33360 "Read error! Unknown property.");
33361 }
33362 break;
33363 }
33364 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE: {
33365 UA_PublishedDataSet *publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, *myNodeId);
33366 if(!publishedDataSet)
33367 return;
33368 switch(nodeContext->elementClassiefier) {
33369 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA: {
33370 UA_PublishedVariableDataType *pvd = (UA_PublishedVariableDataType *)
33371 UA_calloc(publishedDataSet->fieldSize, sizeof(UA_PublishedVariableDataType));
33372 size_t counter = 0;
33373 UA_DataSetField *field;
33374 TAILQ_FOREACH(field, &publishedDataSet->fields, listEntry) {
33375 pvd[counter].attributeId = UA_ATTRIBUTEID_VALUE;
33376 UA_NodeId_copy(&field->config.field.variable.publishParameters.publishedVariable, &pvd[counter].publishedVariable);
33377 counter++;
33378 }
33379 UA_Variant_setArray(&value, pvd, publishedDataSet->fieldSize,
33380 &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]);
33381 break;
33382 }
33383 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA: {
33384 UA_Variant_setScalarCopy(&value, &publishedDataSet->dataSetMetaData, &UA_TYPES[UA_TYPES_DATASETMETADATATYPE]);
33385 break;
33386 }
33387 case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION: {
33388 UA_Variant_setScalarCopy(&value, &publishedDataSet->dataSetMetaData.configurationVersion,
33389 &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]);
33390 break;
33391 }
33392 default:
33393 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33394 "Read error! Unknown property.");
33395 }
33396 break;
33397 }
33398 default:
33399 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33400 "Read error! Unknown parent element.");
33401 }
33402 UA_Server_writeValue(server, *nodeid, value);
33403 UA_Variant_clear(&value);
33404}
33405
33406static void
33407onWrite(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext,
33408 const UA_NodeId *nodeId, void *nodeContext,
33409 const UA_NumericRange *range, const UA_DataValue *data){
33410 UA_Variant value;
33411 UA_NodeId myNodeId;
33412 UA_WriterGroup *writerGroup = NULL;
33413 switch(((UA_NodePropertyContext *) nodeContext)->parentClassifier){
33414 case UA_NS0ID_PUBSUBCONNECTIONTYPE:
33415 //no runtime writable attributes
33416 break;
33417 case UA_NS0ID_WRITERGROUPTYPE:
33418 myNodeId = ((UA_NodePropertyContext *) nodeContext)->parentNodeId;
33419 writerGroup = UA_WriterGroup_findWGbyId(server, myNodeId);
33420 UA_WriterGroupConfig writerGroupConfig;
33421 memset(&writerGroupConfig, 0, sizeof(writerGroupConfig));
33422 if(!writerGroup)
33423 return;
33424 switch(((UA_NodePropertyContext *) nodeContext)->elementClassiefier){
33425 case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL:
33426 UA_Server_getWriterGroupConfig(server, writerGroup->identifier, &writerGroupConfig);
33427 writerGroupConfig.publishingInterval = *((UA_Duration *) data->value.data);
33428 UA_Server_updateWriterGroupConfig(server, writerGroup->identifier, &writerGroupConfig);
33429 UA_Variant_setScalar(&value, data->value.data, &UA_TYPES[UA_TYPES_DURATION]);
33430 UA_WriterGroupConfig_clear(&writerGroupConfig);
33431 break;
33432 default:
33433 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33434 "Write error! Unknown property element.");
33435 }
33436 break;
33437 default:
33438 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
33439 "Read error! Unknown parent element.");
33440 }
33441}
33442
33443static UA_StatusCode
33444addVariableValueSource(UA_Server *server, UA_ValueCallback valueCallback,
33445 UA_NodeId node, UA_NodePropertyContext *context){
33446 UA_Server_setNodeContext(server, node, context);
33447 return UA_Server_setVariableNode_valueCallback(server, node, valueCallback);
33448}
33449
33450#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33451static UA_StatusCode
33452addPubSubConnectionConfig(UA_Server *server, UA_PubSubConnectionDataType *pubsubConnectionDataType,
33453 UA_NodeId *connectionId){
33454 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33455 UA_NetworkAddressUrlDataType networkAddressUrlDataType;
33456 memset(&networkAddressUrlDataType, 0, sizeof(networkAddressUrlDataType));
33457 UA_ExtensionObject eo = pubsubConnectionDataType->address;
33458 if(eo.encoding == UA_EXTENSIONOBJECT_DECODED){
33459 if(eo.content.decoded.type == &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]){
33460 if(UA_NetworkAddressUrlDataType_copy((UA_NetworkAddressUrlDataType *) eo.content.decoded.data,
33461 &networkAddressUrlDataType) != UA_STATUSCODE_GOOD){
33462 return UA_STATUSCODE_BADOUTOFMEMORY;
33463 }
33464 }
33465 }
33466
33467 UA_PubSubConnectionConfig connectionConfig;
33468 memset(&connectionConfig, 0, sizeof(UA_PubSubConnectionConfig));
33469 connectionConfig.transportProfileUri = pubsubConnectionDataType->transportProfileUri;
33470 connectionConfig.name = pubsubConnectionDataType->name;
33471 //TODO set real connection state
33472 connectionConfig.enabled = pubsubConnectionDataType->enabled;
33473 //connectionConfig.enabled = pubSubConnectionDataType.enabled;
33474 UA_Variant_setScalar(&connectionConfig.address, &networkAddressUrlDataType,
33475 &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]);
33476 if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]){
33477 connectionConfig.publisherId.numeric = * ((UA_UInt32 *) pubsubConnectionDataType->publisherId.data);
33478 } else if(pubsubConnectionDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
33479 connectionConfig.publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
33480 UA_String_copy((UA_String *) pubsubConnectionDataType->publisherId.data, &connectionConfig.publisherId.string);
33481 } else {
33482 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER, "Unsupported PublisherId Type used.");
33483 //TODO what's the best default behaviour here?
33484 connectionConfig.publisherId.numeric = 0;
33485 }
33486
33487 retVal |= UA_Server_addPubSubConnection(server, &connectionConfig, connectionId);
33488 UA_NetworkAddressUrlDataType_clear(&networkAddressUrlDataType);
33489 return retVal;
33490}
33491
33492/**
33493 * **WriterGroup handling**
33494 *
33495 * The WriterGroup (WG) is part of the connection and contains the primary
33496 * configuration parameters for the message creation. */
33497static UA_StatusCode
33498addWriterGroupConfig(UA_Server *server, UA_NodeId connectionId,
33499 UA_WriterGroupDataType *writerGroupDataType, UA_NodeId *writerGroupId){
33500 /* Now we create a new WriterGroupConfig and add the group to the existing
33501 * PubSubConnection. */
33502 UA_WriterGroupConfig writerGroupConfig;
33503 memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
33504 writerGroupConfig.name = writerGroupDataType->name;
33505 writerGroupConfig.publishingInterval = writerGroupDataType->publishingInterval;
33506 writerGroupConfig.enabled = writerGroupDataType->enabled;
33507 writerGroupConfig.writerGroupId = writerGroupDataType->writerGroupId;
33508 //TODO remove hard coded UADP
33509 writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
33510 writerGroupConfig.priority = writerGroupDataType->priority;
33511
33512 UA_UadpWriterGroupMessageDataType writerGroupMessage;
33513 UA_ExtensionObject *eoWG = &writerGroupDataType->messageSettings;
33514 if(eoWG->encoding == UA_EXTENSIONOBJECT_DECODED){
33515 writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
33516 if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]){
33517 if(UA_UadpWriterGroupMessageDataType_copy((UA_UadpWriterGroupMessageDataType *) eoWG->content.decoded.data,
33518 &writerGroupMessage) != UA_STATUSCODE_GOOD){
33519 return UA_STATUSCODE_BADOUTOFMEMORY;
33520 }
33521 writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
33522 writerGroupConfig.messageSettings.content.decoded.data = &writerGroupMessage;
33523 }
33524 }
33525
33526 return UA_Server_addWriterGroup(server, connectionId, &writerGroupConfig, writerGroupId);
33527}
33528
33529/**
33530 * **DataSetWriter handling**
33531 *
33532 * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is
33533 * linked to exactly one PDS and contains additional informations for the
33534 * message generation. */
33535static UA_StatusCode
33536addDataSetWriterConfig(UA_Server *server, const UA_NodeId *writerGroupId,
33537 UA_DataSetWriterDataType *dataSetWriterDataType,
33538 UA_NodeId *dataSetWriterId) {
33539 UA_NodeId publishedDataSetId = UA_NODEID_NULL;
33540 UA_PublishedDataSet *tmpPDS;
33541 TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){
33542 if(UA_String_equal(&dataSetWriterDataType->dataSetName, &tmpPDS->config.name)) {
33543 publishedDataSetId = tmpPDS->identifier;
33544 break;
33545 }
33546 }
33547
33548 if(UA_NodeId_isNull(&publishedDataSetId))
33549 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
33550
33551 /* We need now a DataSetWriter within the WriterGroup. This means we must
33552 * create a new DataSetWriterConfig and add call the addWriterGroup function. */
33553 UA_DataSetWriterConfig dataSetWriterConfig;
33554 memset(&dataSetWriterConfig, 0, sizeof(UA_DataSetWriterConfig));
33555 dataSetWriterConfig.name = dataSetWriterDataType->name;
33556 dataSetWriterConfig.dataSetWriterId = dataSetWriterDataType->dataSetWriterId;
33557 dataSetWriterConfig.keyFrameCount = dataSetWriterDataType->keyFrameCount;
33558 dataSetWriterConfig.dataSetFieldContentMask = dataSetWriterDataType->dataSetFieldContentMask;
33559 return UA_Server_addDataSetWriter(server, *writerGroupId, publishedDataSetId,
33560 &dataSetWriterConfig, dataSetWriterId);
33561}
33562
33563/**
33564 * **ReaderGroup**
33565 *
33566 * ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are
33567 * created within a PubSubConnection and automatically deleted if the connection
33568 * is removed. All network message related filters are only available in the DataSetReader. */
33569/* Add ReaderGroup to the created connection */
33570static UA_StatusCode
33571addReaderGroupConfig(UA_Server *server, UA_NodeId connectionId,
33572 UA_ReaderGroupDataType *readerGroupDataType,
33573 UA_NodeId *readerGroupId) {
33574 UA_ReaderGroupConfig readerGroupConfig;
33575 memset(&readerGroupConfig, 0, sizeof(UA_ReaderGroupConfig));
33576 readerGroupConfig.name = readerGroupDataType->name;
33577 return UA_Server_addReaderGroup(server, connectionId,
33578 &readerGroupConfig, readerGroupId);
33579}
33580
33581/**
33582 * **SubscribedDataSet**
33583 *
33584 * Set SubscribedDataSet type to TargetVariables data type.
33585 * Add subscribedvariables to the DataSetReader */
33586static UA_StatusCode
33587addSubscribedVariables(UA_Server *server, UA_NodeId dataSetReaderId,
33588 UA_DataSetReaderDataType *dataSetReaderDataType,
33589 UA_DataSetMetaDataType *pMetaData) {
33590 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33591 UA_ExtensionObject *eoTargetVar = &dataSetReaderDataType->subscribedDataSet;
33592 if(eoTargetVar->encoding != UA_EXTENSIONOBJECT_DECODED ||
33593 eoTargetVar->content.decoded.type != &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE])
33594 return UA_STATUSCODE_BADINTERNALERROR;
33595
33596 const UA_TargetVariablesDataType *targetVars =
33597 (UA_TargetVariablesDataType *) eoTargetVar->content.decoded.data;
33598
33599 UA_NodeId folderId;
33600 UA_String folderName = pMetaData->name;
33601 UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
33602 UA_QualifiedName folderBrowseName;
33603 if(folderName.length > 0) {
33604 oAttr.displayName.locale = UA_STRING("");
33605 oAttr.displayName.text = folderName;
33606 folderBrowseName.namespaceIndex = 1;
33607 folderBrowseName.name = folderName;
33608 } else {
33609 oAttr.displayName = UA_LOCALIZEDTEXT("", "Subscribed Variables");
33610 folderBrowseName = UA_QUALIFIEDNAME(1, "Subscribed Variables");
33611 }
33612
33613 UA_Server_addObjectNode(server, UA_NODEID_NULL, UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER),
33614 UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES), folderBrowseName,
33615 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEOBJECTTYPE), oAttr, NULL, &folderId);
33616 /**
33617 * **TargetVariables**
33618 *
33619 * The SubscribedDataSet option TargetVariables defines a list of Variable
33620 * mappings between received DataSet fields and target Variables in the Subscriber
33621 * AddressSpace. The values subscribed from the Publisher are updated in the value
33622 * field of these variables */
33623 /* Create the TargetVariables with respect to DataSetMetaData fields */
33624 UA_FieldTargetVariable *targetVarsData = (UA_FieldTargetVariable *)
33625 UA_calloc(targetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable));
33626 for(size_t i = 0; i < targetVars->targetVariablesSize; i++) {
33627 /* Variable to subscribe data */
33628 UA_VariableAttributes vAttr = UA_VariableAttributes_default;
33629 UA_LocalizedText_copy(&pMetaData->fields[i].description, &vAttr.description);
33630 vAttr.displayName.locale = UA_STRING("");
33631 vAttr.displayName.text = pMetaData->fields[i].name;
33632 vAttr.dataType = pMetaData->fields[i].dataType;
33633
33634 UA_QualifiedName browseName;
33635 browseName.namespaceIndex = 1;
33636 browseName.name = pMetaData->fields[i].name;
33637
33638 UA_NodeId newNode;
33639 retVal |= UA_Server_addVariableNode(
33640 server, targetVars->targetVariables[i].targetNodeId, folderId,
33641 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), browseName,
33642 UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), vAttr, NULL, &newNode);
33643
33644 /* For creating Targetvariables */
33645 targetVarsData[i].targetVariable.attributeId =
33646 targetVars->targetVariables[i].attributeId;
33647 targetVarsData[i].targetVariable.targetNodeId = newNode;
33648 }
33649 retVal =
33650 UA_Server_DataSetReader_createTargetVariables(server, dataSetReaderId,
33651 targetVars->targetVariablesSize, targetVarsData);
33652 for(size_t j = 0; j < targetVars->targetVariablesSize; j++)
33653 UA_FieldTargetDataType_clear(&targetVarsData[j].targetVariable);
33654 UA_free(targetVarsData);
33655
33656 return retVal;
33657}
33658
33659/**
33660 * **DataSetReader**
33661 *
33662 * DataSetReader can receive NetworkMessages with the DataSetMessage
33663 * of interest sent by the Publisher. DataSetReader provides
33664 * the configuration necessary to receive and process DataSetMessages
33665 * on the Subscriber side. DataSetReader must be linked with a
33666 * SubscribedDataSet and be contained within a ReaderGroup. */
33667/* Add DataSetReader to the ReaderGroup */
33668static UA_StatusCode
33669addDataSetReaderConfig(UA_Server *server, UA_NodeId readerGroupId,
33670 UA_DataSetReaderDataType *dataSetReaderDataType,
33671 UA_NodeId *dataSetReaderId) {
33672 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33673 UA_DataSetReaderConfig readerConfig;
33674 memset (&readerConfig, 0, sizeof(UA_DataSetReaderConfig));
33675 readerConfig.name = dataSetReaderDataType->name;
33676 /* Parameters to filter which DataSetMessage has to be processed
33677 * by the DataSetReader */
33678 if(dataSetReaderDataType->publisherId.type == &UA_TYPES[UA_TYPES_STRING]){
33679 UA_String publisherIdentifier;
33680 readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_STRING];
33681 UA_String_copy((UA_String *) dataSetReaderDataType->publisherId.data, &publisherIdentifier);
33682 readerConfig.publisherId.data = &publisherIdentifier;
33683 } else {
33684 UA_UInt16 publisherIdentifier = *(UA_UInt16*)dataSetReaderDataType->publisherId.data;
33685 readerConfig.publisherId.type = &UA_TYPES[UA_TYPES_UINT16];
33686 readerConfig.publisherId.data = &publisherIdentifier;
33687 }
33688
33689 readerConfig.writerGroupId = dataSetReaderDataType->writerGroupId;
33690 readerConfig.dataSetWriterId = dataSetReaderDataType->dataSetWriterId;
33691
33692 /* Setting up Meta data configuration in DataSetReader */
33693 UA_DataSetMetaDataType *pMetaData;
33694 pMetaData = &readerConfig.dataSetMetaData;
33695 UA_DataSetMetaDataType_init (pMetaData);
33696 pMetaData->name = dataSetReaderDataType->dataSetMetaData.name;
33697 pMetaData->fieldsSize = dataSetReaderDataType->dataSetMetaData.fieldsSize;
33698 pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (pMetaData->fieldsSize,
33699 &UA_TYPES[UA_TYPES_FIELDMETADATA]);
33700 for(size_t i = 0; i < pMetaData->fieldsSize; i++){
33701 UA_FieldMetaData_init (&pMetaData->fields[i]);
33702 UA_NodeId_copy (&dataSetReaderDataType->dataSetMetaData.fields[i].dataType,
33703 &pMetaData->fields[i].dataType);
33704 pMetaData->fields[i].builtInType = dataSetReaderDataType->dataSetMetaData.fields[i].builtInType;
33705 pMetaData->fields[i].name = dataSetReaderDataType->dataSetMetaData.fields[i].name;
33706 pMetaData->fields[i].valueRank = dataSetReaderDataType->dataSetMetaData.fields[i].valueRank;
33707 }
33708
33709 retVal |= UA_Server_addDataSetReader(server, readerGroupId, &readerConfig,
33710 dataSetReaderId);
33711 if(retVal != UA_STATUSCODE_GOOD) {
33712 UA_free(pMetaData->fields);
33713 return retVal;
33714 }
33715
33716 retVal |= addSubscribedVariables(server, *dataSetReaderId, dataSetReaderDataType, pMetaData);
33717 UA_free(pMetaData->fields);
33718 return retVal;
33719}
33720#endif
33721
33722/*************************************************/
33723/* PubSubConnection */
33724/*************************************************/
33725UA_StatusCode
33726addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection) {
33727 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33728 if(connection->config->name.length > 512)
33729 return UA_STATUSCODE_BADOUTOFMEMORY;
33730 char connectionName[513];
33731 memcpy(connectionName, connection->config->name.data, connection->config->name.length);
33732 connectionName[connection->config->name.length] = '\0';
33733
33734 UA_ObjectAttributes attr = UA_ObjectAttributes_default;
33735 attr.displayName = UA_LOCALIZEDTEXT("", connectionName);
33736 retVal |= UA_Server_addNode_begin(server, UA_NODECLASS_OBJECT,
33737 UA_NODEID_NUMERIC(1, 0), /* Generate a new id */
33738 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
33739 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPUBSUBCONNECTION),
33740 UA_QUALIFIEDNAME(0, connectionName),
33741 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE),
33742 (const UA_NodeAttributes*)&attr,
33743 &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
33744 NULL, &connection->identifier);
33745
33746 attr.displayName = UA_LOCALIZEDTEXT("", "Address");
33747 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
33748 connection->identifier,
33749 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33750 UA_QUALIFIEDNAME(0, "Address"),
33751 UA_NODEID_NUMERIC(0, UA_NS0ID_NETWORKADDRESSURLTYPE),
33752 attr, NULL, NULL);
33753
33754 UA_Server_addNode_finish(server, connection->identifier);
33755
33756 UA_NodeId addressNode, urlNode, interfaceNode, publisherIdNode,
33757 connectionPropertieNode, transportProfileUri;
33758 addressNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Address"),
33759 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33760 connection->identifier);
33761 urlNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Url"),
33762 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33763 addressNode);
33764 interfaceNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkInterface"),
33765 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33766 addressNode);
33767 publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
33768 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33769 connection->identifier);
33770 connectionPropertieNode = findSingleChildNode(server,
33771 UA_QUALIFIEDNAME(0, "ConnectionProperties"),
33772 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33773 connection->identifier);
33774 transportProfileUri = findSingleChildNode(server,
33775 UA_QUALIFIEDNAME(0, "TransportProfileUri"),
33776 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33777 connection->identifier);
33778
33779 if(UA_NodeId_isNull(&addressNode) || UA_NodeId_isNull(&urlNode) ||
33780 UA_NodeId_isNull(&interfaceNode) || UA_NodeId_isNull(&publisherIdNode) ||
33781 UA_NodeId_isNull(&connectionPropertieNode) ||
33782 UA_NodeId_isNull(&transportProfileUri)) {
33783 return UA_STATUSCODE_BADNOTFOUND;
33784 }
33785
33786 retVal |= writePubSubNs0VariableArray(server, connectionPropertieNode.identifier.numeric,
33787 connection->config->connectionProperties,
33788 connection->config->connectionPropertiesSize,
33789 &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
33790
33791 UA_NetworkAddressUrlDataType *networkAddressUrlDataType =
33792 ((UA_NetworkAddressUrlDataType*)connection->config->address.data);
33793 UA_Variant value;
33794 UA_Variant_init(&value);
33795 UA_Variant_setScalar(&value, &networkAddressUrlDataType->url,
33796 &UA_TYPES[UA_TYPES_STRING]);
33797 UA_Server_writeValue(server, urlNode, value);
33798 UA_Variant_setScalar(&value, &networkAddressUrlDataType->networkInterface,
33799 &UA_TYPES[UA_TYPES_STRING]);
33800 UA_Server_writeValue(server, interfaceNode, value);
33801 UA_Variant_setScalar(&value, &connection->config->transportProfileUri,
33802 &UA_TYPES[UA_TYPES_STRING]);
33803 UA_Server_writeValue(server, transportProfileUri, value);
33804
33805 UA_NodePropertyContext *connectionPublisherIdContext = (UA_NodePropertyContext *)
33806 UA_malloc(sizeof(UA_NodePropertyContext));
33807 connectionPublisherIdContext->parentNodeId = connection->identifier;
33808 connectionPublisherIdContext->parentClassifier = UA_NS0ID_PUBSUBCONNECTIONTYPE;
33809 connectionPublisherIdContext->elementClassiefier =
33810 UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID;
33811 UA_ValueCallback valueCallback;
33812 valueCallback.onRead = onRead;
33813 valueCallback.onWrite = NULL;
33814 retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
33815 connectionPublisherIdContext);
33816
33817#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33818 retVal |= UA_Server_addReference(server, connection->identifier,
33819 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33820 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP),
33821 true);
33822 retVal |= UA_Server_addReference(server, connection->identifier,
33823 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33824 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP),
33825 true);
33826 retVal |= UA_Server_addReference(server, connection->identifier,
33827 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
33828 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP),
33829 true);
33830#endif
33831 return retVal;
33832}
33833
33834#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33835static UA_StatusCode
33836addPubSubConnectionAction(UA_Server *server,
33837 const UA_NodeId *sessionId, void *sessionHandle,
33838 const UA_NodeId *methodId, void *methodContext,
33839 const UA_NodeId *objectId, void *objectContext,
33840 size_t inputSize, const UA_Variant *input,
33841 size_t outputSize, UA_Variant *output){
33842 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33843 UA_PubSubConnectionDataType pubSubConnectionDataType = *((UA_PubSubConnectionDataType *) input[0].data);
33844
33845 //call API function and create the connection
33846 UA_NodeId connectionId;
33847 retVal |= addPubSubConnectionConfig(server, &pubSubConnectionDataType, &connectionId);
33848 if(retVal != UA_STATUSCODE_GOOD) {
33849 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addPubSubConnection failed");
33850 return retVal;
33851 }
33852
33853 for(size_t i = 0; i < pubSubConnectionDataType.writerGroupsSize; i++){
33854 UA_NodeId writerGroupId;
33855 UA_WriterGroupDataType *writerGroupDataType = &pubSubConnectionDataType.writerGroups[i];
33856 retVal |= addWriterGroupConfig(server, connectionId, writerGroupDataType, &writerGroupId);
33857 if(retVal != UA_STATUSCODE_GOOD) {
33858 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
33859 return retVal;
33860 }
33861
33862 for (size_t j = 0; j < pubSubConnectionDataType.writerGroups[i].dataSetWritersSize; j++){
33863 UA_DataSetWriterDataType *dataSetWriterDataType = &writerGroupDataType->dataSetWriters[j];
33864 retVal |= addDataSetWriterConfig(server, &writerGroupId, dataSetWriterDataType, NULL);
33865 if(retVal != UA_STATUSCODE_GOOD) {
33866 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetWriter failed");
33867 return retVal;
33868 }
33869 }
33870
33871 //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
33872 if(pubSubConnectionDataType.enabled) {
33873 UA_Server_freezeWriterGroupConfiguration(server, writerGroupId);
33874 UA_Server_setWriterGroupOperational(server, writerGroupId);
33875 } else
33876 UA_Server_setWriterGroupDisabled(server, writerGroupId);
33877 }
33878
33879 for(size_t i = 0; i < pubSubConnectionDataType.readerGroupsSize; i++){
33880 UA_NodeId readerGroupId;
33881 UA_ReaderGroupDataType *rg = &pubSubConnectionDataType.readerGroups[i];
33882 retVal |= addReaderGroupConfig(server, connectionId, rg, &readerGroupId);
33883 if(retVal != UA_STATUSCODE_GOOD) {
33884 UA_NodeId_clear(&readerGroupId);
33885 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
33886 return retVal;
33887 }
33888
33889 for(size_t j = 0; j < rg->dataSetReadersSize; j++) {
33890 UA_NodeId dataSetReaderId;
33891 UA_DataSetReaderDataType *dataSetReaderDataType = &rg->dataSetReaders[j];
33892 retVal |= addDataSetReaderConfig(server, readerGroupId, dataSetReaderDataType, &dataSetReaderId);
33893 if(retVal != UA_STATUSCODE_GOOD) {
33894 UA_NodeId_clear(&readerGroupId);
33895 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
33896 return retVal;
33897 }
33898 }
33899
33900 //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
33901 if(pubSubConnectionDataType.enabled) {
33902 UA_Server_freezeReaderGroupConfiguration(server, readerGroupId);
33903 UA_Server_setReaderGroupOperational(server, readerGroupId);
33904 } else {
33905 UA_Server_setReaderGroupDisabled(server, readerGroupId);
33906 }
33907
33908 UA_NodeId_clear(&readerGroupId);
33909 }
33910 //set ouput value
33911 UA_Variant_setScalarCopy(output, &connectionId, &UA_TYPES[UA_TYPES_NODEID]);
33912 return UA_STATUSCODE_GOOD;
33913}
33914#endif
33915
33916UA_StatusCode
33917removePubSubConnectionRepresentation(UA_Server *server,
33918 UA_PubSubConnection *connection) {
33919 return UA_Server_deleteNode(server, connection->identifier, true);
33920}
33921
33922#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
33923static UA_StatusCode
33924removeConnectionAction(UA_Server *server,
33925 const UA_NodeId *sessionId, void *sessionHandle,
33926 const UA_NodeId *methodId, void *methodContext,
33927 const UA_NodeId *objectId, void *objectContext,
33928 size_t inputSize, const UA_Variant *input,
33929 size_t outputSize, UA_Variant *output){
33930 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33931 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
33932 retVal |= UA_Server_removePubSubConnection(server, nodeToRemove);
33933 if(retVal == UA_STATUSCODE_BADNOTFOUND)
33934 retVal = UA_STATUSCODE_BADNODEIDUNKNOWN;
33935 return retVal;
33936}
33937#endif
33938
33939/**********************************************/
33940/* DataSetReader */
33941/**********************************************/
33942UA_StatusCode
33943addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader){
33944 if(dataSetReader->config.name.length > 512)
33945 return UA_STATUSCODE_BADCONFIGURATIONERROR;
33946
33947 char dsrName[513];
33948 memcpy(dsrName, dataSetReader->config.name.data, dataSetReader->config.name.length);
33949 dsrName[dataSetReader->config.name.length] = '\0';
33950
33951 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
33952 UA_NodeId publisherIdNode, writerGroupIdNode, dataSetwriterIdNode;
33953
33954 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
33955 object_attr.displayName = UA_LOCALIZEDTEXT("", dsrName);
33956 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
33957 dataSetReader->linkedReaderGroup,
33958 UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETREADER),
33959 UA_QUALIFIEDNAME(0, dsrName),
33960 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE),
33961 object_attr, NULL, &dataSetReader->identifier);
33962
33963 /* Add childNodes such as PublisherId, WriterGroupId and DataSetWriterId in
33964 * DataSetReader object */
33965 publisherIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
33966 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33967 dataSetReader->identifier);
33968 writerGroupIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
33969 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33970 dataSetReader->identifier);
33971 dataSetwriterIdNode = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
33972 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
33973 dataSetReader->identifier);
33974
33975 if(UA_NodeId_isNull(&publisherIdNode) ||
33976 UA_NodeId_isNull(&writerGroupIdNode) ||
33977 UA_NodeId_isNull(&dataSetwriterIdNode)) {
33978 return UA_STATUSCODE_BADNOTFOUND;
33979 }
33980
33981 UA_NodePropertyContext *dataSetReaderPublisherIdContext =
33982 (UA_NodePropertyContext *) UA_malloc(sizeof(UA_NodePropertyContext));
33983 dataSetReaderPublisherIdContext->parentNodeId = dataSetReader->identifier;
33984 dataSetReaderPublisherIdContext->parentClassifier = UA_NS0ID_DATASETREADERTYPE;
33985 dataSetReaderPublisherIdContext->elementClassiefier = UA_NS0ID_DATASETREADERTYPE_PUBLISHERID;
33986 UA_ValueCallback valueCallback;
33987 valueCallback.onRead = onRead;
33988 valueCallback.onWrite = NULL;
33989 retVal |= addVariableValueSource(server, valueCallback, publisherIdNode,
33990 dataSetReaderPublisherIdContext);
33991
33992 /* Update childNode with values from Publisher */
33993 UA_Variant value;
33994 UA_Variant_init(&value);
33995 UA_Variant_setScalar(&value, &dataSetReader->config.writerGroupId,
33996 &UA_TYPES[UA_TYPES_UINT16]);
33997 UA_Server_writeValue(server, writerGroupIdNode, value);
33998 UA_Variant_setScalar(&value, &dataSetReader->config.dataSetWriterId,
33999 &UA_TYPES[UA_TYPES_UINT16]);
34000 UA_Server_writeValue(server, dataSetwriterIdNode, value);
34001 return retVal;
34002}
34003
34004#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34005static UA_StatusCode
34006addDataSetReaderAction(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 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34013 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, *objectId);
34014 if(rg->configurationFrozen) {
34015 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34016 "addDataSetReader cannot be done because ReaderGroup config frozen");
34017 return UA_STATUSCODE_BAD;
34018 }
34019
34020 UA_NodeId dataSetReaderId;
34021 UA_DataSetReaderDataType *dataSetReaderDataType = (UA_DataSetReaderDataType *) input[0].data;
34022 retVal |= addDataSetReaderConfig(server, *objectId, dataSetReaderDataType, &dataSetReaderId);
34023 if(retVal != UA_STATUSCODE_GOOD) {
34024 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addDataSetReader failed");
34025 return retVal;
34026 }
34027
34028 UA_Variant_setScalarCopy(output, &dataSetReaderId, &UA_TYPES[UA_TYPES_NODEID]);
34029 return retVal;
34030}
34031#endif
34032
34033UA_StatusCode
34034removeDataSetReaderRepresentation(UA_Server *server,
34035 UA_DataSetReader* dataSetReader) {
34036 return UA_Server_deleteNode(server, dataSetReader->identifier, true);
34037}
34038
34039#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34040static UA_StatusCode
34041removeDataSetReaderAction(UA_Server *server,
34042 const UA_NodeId *sessionId, void *sessionHandle,
34043 const UA_NodeId *methodId, void *methodContext,
34044 const UA_NodeId *objectId, void *objectContext,
34045 size_t inputSize, const UA_Variant *input,
34046 size_t outputSize, UA_Variant *output){
34047 UA_NodeId nodeToRemove = *((UA_NodeId *)input[0].data);
34048 return UA_Server_removeDataSetReader(server, nodeToRemove);
34049}
34050#endif
34051
34052/*************************************************/
34053/* PublishedDataSet */
34054/*************************************************/
34055#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34056static UA_StatusCode
34057addDataSetFolderAction(UA_Server *server,
34058 const UA_NodeId *sessionId, void *sessionHandle,
34059 const UA_NodeId *methodId, void *methodContext,
34060 const UA_NodeId *objectId, void *objectContext,
34061 size_t inputSize, const UA_Variant *input,
34062 size_t outputSize, UA_Variant *output){
34063 /* defined in R 1.04 9.1.4.5.7 */
34064 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34065 UA_String newFolderName = *((UA_String *) input[0].data);
34066 UA_NodeId generatedId;
34067 UA_ObjectAttributes objectAttributes = UA_ObjectAttributes_default;
34068 UA_LocalizedText name = {UA_STRING(""), newFolderName};
34069 objectAttributes.displayName = name;
34070 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NULL, *objectId,
34071 UA_NODEID_NUMERIC(0,UA_NS0ID_ORGANIZES),
34072 UA_QUALIFIEDNAME(0, "DataSetFolder"),
34073 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE),
34074 objectAttributes, NULL, &generatedId);
34075 UA_Variant_setScalarCopy(output, &generatedId, &UA_TYPES[UA_TYPES_NODEID]);
34076#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34077 retVal |= UA_Server_addReference(server, generatedId,
34078 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34079 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true);
34080 retVal |= UA_Server_addReference(server, generatedId,
34081 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34082 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true);
34083 retVal |= UA_Server_addReference(server, generatedId,
34084 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34085 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true);
34086 retVal |= UA_Server_addReference(server, generatedId,
34087 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34088 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true);
34089#endif
34090 return retVal;
34091}
34092#endif
34093
34094#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34095static UA_StatusCode
34096removeDataSetFolderAction(UA_Server *server,
34097 const UA_NodeId *sessionId, void *sessionHandle,
34098 const UA_NodeId *methodId, void *methodContext,
34099 const UA_NodeId *objectId, void *objectContext,
34100 size_t inputSize, const UA_Variant *input,
34101 size_t outputSize, UA_Variant *output) {
34102 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34103 return UA_Server_deleteNode(server, nodeToRemove, true);
34104}
34105#endif
34106
34107UA_StatusCode
34108addPublishedDataItemsRepresentation(UA_Server *server,
34109 UA_PublishedDataSet *publishedDataSet) {
34110 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34111 if(publishedDataSet->config.name.length > 512)
34112 return UA_STATUSCODE_BADOUTOFMEMORY;
34113 char pdsName[513];
34114 memcpy(pdsName, publishedDataSet->config.name.data, publishedDataSet->config.name.length);
34115 pdsName[publishedDataSet->config.name.length] = '\0';
34116
34117 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34118 object_attr.displayName = UA_LOCALIZEDTEXT("", pdsName);
34119 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* Create a new id */
34120 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34121 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34122 UA_QUALIFIEDNAME(0, pdsName),
34123 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE),
34124 object_attr, NULL, &publishedDataSet->identifier);
34125 UA_CHECK_STATUS(retVal, return retVal);
34126
34127 UA_ValueCallback valueCallback;
34128 valueCallback.onRead = onRead;
34129 valueCallback.onWrite = NULL;
34130 //ToDo: Need to move the browse name from namespaceindex 0 to 1
34131 UA_NodeId configurationVersionNode =
34132 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
34133 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34134 publishedDataSet->identifier);
34135 if(UA_NodeId_isNull(&configurationVersionNode))
34136 return UA_STATUSCODE_BADNOTFOUND;
34137
34138 UA_NodePropertyContext *configurationVersionContext = (UA_NodePropertyContext *)
34139 UA_malloc(sizeof(UA_NodePropertyContext));
34140 configurationVersionContext->parentNodeId = publishedDataSet->identifier;
34141 configurationVersionContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34142 configurationVersionContext->elementClassiefier =
34143 UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION;
34144 retVal |= addVariableValueSource(server, valueCallback, configurationVersionNode,
34145 configurationVersionContext);
34146
34147 UA_NodeId publishedDataNode =
34148 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
34149 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34150 publishedDataSet->identifier);
34151 if(UA_NodeId_isNull(&publishedDataNode))
34152 return UA_STATUSCODE_BADNOTFOUND;
34153
34154 UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
34155 UA_malloc(sizeof(UA_NodePropertyContext));
34156 publishingIntervalContext->parentNodeId = publishedDataSet->identifier;
34157 publishingIntervalContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34158 publishingIntervalContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA;
34159 retVal |= addVariableValueSource(server, valueCallback, publishedDataNode,
34160 publishingIntervalContext);
34161
34162 UA_NodeId dataSetMetaDataNode =
34163 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
34164 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34165 publishedDataSet->identifier);
34166 if(UA_NodeId_isNull(&dataSetMetaDataNode))
34167 return UA_STATUSCODE_BADNOTFOUND;
34168
34169 UA_NodePropertyContext *metaDataContext = (UA_NodePropertyContext *)
34170 UA_malloc(sizeof(UA_NodePropertyContext));
34171 metaDataContext->parentNodeId = publishedDataSet->identifier;
34172 metaDataContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE;
34173 metaDataContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA;
34174 retVal |= addVariableValueSource(server, valueCallback,
34175 dataSetMetaDataNode, metaDataContext);
34176
34177#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34178 retVal |= UA_Server_addReference(server, publishedDataSet->identifier,
34179 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34180 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), true);
34181 retVal |= UA_Server_addReference(server, publishedDataSet->identifier,
34182 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34183 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), true);
34184#endif
34185 return retVal;
34186}
34187
34188#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34189static UA_StatusCode
34190addPublishedDataItemsAction(UA_Server *server,
34191 const UA_NodeId *sessionId, void *sessionHandle,
34192 const UA_NodeId *methodId, void *methodContext,
34193 const UA_NodeId *objectId, void *objectContext,
34194 size_t inputSize, const UA_Variant *input,
34195 size_t outputSize, UA_Variant *output){
34196 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34197 size_t fieldNameAliasesSize = input[1].arrayLength;
34198 UA_String * fieldNameAliases = (UA_String *) input[1].data;
34199 size_t fieldFlagsSize = input[2].arrayLength;
34200 UA_DataSetFieldFlags * fieldFlags = (UA_DataSetFieldFlags *) input[2].data;
34201 size_t variablesToAddSize = input[3].arrayLength;
34202 UA_PublishedVariableDataType *variablesToAdd = NULL;
34203 UA_ExtensionObject *eoAddVar = NULL;
34204 if(input[3].type == &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE])
34205 variablesToAdd = (UA_PublishedVariableDataType*)input[3].data;
34206 else if(input[3].type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT])
34207 eoAddVar = (UA_ExtensionObject *)input[3].data;
34208 else
34209 return UA_STATUSCODE_BADINTERNALERROR;
34210
34211 if(!(fieldNameAliasesSize == fieldFlagsSize || fieldFlagsSize == variablesToAddSize))
34212 return UA_STATUSCODE_BADINVALIDARGUMENT;
34213
34214 UA_PublishedDataSetConfig publishedDataSetConfig;
34215 memset(&publishedDataSetConfig, 0, sizeof(publishedDataSetConfig));
34216 publishedDataSetConfig.name = *((UA_String *) input[0].data);
34217 publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
34218
34219 UA_NodeId dataSetItemsNodeId;
34220 retVal |= UA_Server_addPublishedDataSet(server, &publishedDataSetConfig,
34221 &dataSetItemsNodeId).addResult;
34222 if(retVal != UA_STATUSCODE_GOOD) {
34223 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34224 "addPublishedDataset failed");
34225 return retVal;
34226 }
34227
34228 UA_DataSetFieldConfig dataSetFieldConfig;
34229 for(size_t j = 0; j < variablesToAddSize; ++j) {
34230 /* Prepare the config */
34231 memset(&dataSetFieldConfig, 0, sizeof(UA_DataSetFieldConfig));
34232 dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
34233 dataSetFieldConfig.field.variable.fieldNameAlias = fieldNameAliases[j];
34234 if(fieldFlags[j] == UA_DATASETFIELDFLAGS_PROMOTEDFIELD)
34235 dataSetFieldConfig.field.variable.promotedField = true;
34236
34237 UA_PublishedVariableDataType *variableToAdd;
34238 if(variablesToAdd) {
34239 variableToAdd = &variablesToAdd[j];
34240 } else {
34241 if(eoAddVar[j].content.decoded.type !=
34242 &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE])
34243 return UA_STATUSCODE_BADINTERNALERROR;
34244 variableToAdd = (UA_PublishedVariableDataType*)
34245 eoAddVar[j].content.decoded.data;
34246 }
34247 dataSetFieldConfig.field.variable.publishParameters = *variableToAdd;
34248
34249 /* Add the dataset field */
34250 retVal |= UA_Server_addDataSetField(server, dataSetItemsNodeId,
34251 &dataSetFieldConfig, NULL).result;
34252 if(retVal != UA_STATUSCODE_GOOD) {
34253 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34254 "addDataSetField failed");
34255 return retVal;
34256 }
34257 }
34258
34259 UA_Variant_setScalarCopy(output, &dataSetItemsNodeId, &UA_TYPES[UA_TYPES_NODEID]);
34260 return retVal;
34261}
34262#endif
34263
34264#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34265static UA_StatusCode
34266addVariablesAction(UA_Server *server,
34267 const UA_NodeId *sessionId, void *sessionHandle,
34268 const UA_NodeId *methodId, void *methodContext,
34269 const UA_NodeId *objectId, void *objectContext,
34270 size_t inputSize, const UA_Variant *input,
34271 size_t outputSize, UA_Variant *output){
34272 return UA_STATUSCODE_GOOD;
34273}
34274
34275static UA_StatusCode
34276removeVariablesAction(UA_Server *server,
34277 const UA_NodeId *sessionId, void *sessionHandle,
34278 const UA_NodeId *methodId, void *methodContext,
34279 const UA_NodeId *objectId, void *objectContext,
34280 size_t inputSize, const UA_Variant *input,
34281 size_t outputSize, UA_Variant *output){
34282 return UA_STATUSCODE_GOOD;
34283}
34284#endif
34285
34286
34287UA_StatusCode
34288removePublishedDataSetRepresentation(UA_Server *server,
34289 UA_PublishedDataSet *publishedDataSet) {
34290 return UA_Server_deleteNode(server, publishedDataSet->identifier, true);
34291}
34292
34293#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34294static UA_StatusCode
34295removePublishedDataSetAction(UA_Server *server,
34296 const UA_NodeId *sessionId, void *sessionHandle,
34297 const UA_NodeId *methodId, void *methodContext,
34298 const UA_NodeId *objectId, void *objectContext,
34299 size_t inputSize, const UA_Variant *input,
34300 size_t outputSize, UA_Variant *output){
34301 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34302 return UA_Server_removePublishedDataSet(server, nodeToRemove);
34303}
34304#endif
34305
34306/**********************************************/
34307/* WriterGroup */
34308/**********************************************/
34309
34310static UA_StatusCode
34311readContentMask(UA_Server *server, const UA_NodeId *sessionId,
34312 void *sessionContext, const UA_NodeId *nodeId,
34313 void *nodeContext, UA_Boolean includeSourceTimeStamp,
34314 const UA_NumericRange *range, UA_DataValue *value) {
34315 UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext;
34316 if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED &&
34317 writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
34318 writerGroup->config.messageSettings.content.decoded.type !=
34319 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
34320 return UA_STATUSCODE_BADINTERNALERROR;
34321 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
34322 writerGroup->config.messageSettings.content.decoded.data;
34323
34324 UA_Variant_setScalarCopy(&value->value, &wgm->networkMessageContentMask,
34325 &UA_TYPES[UA_TYPES_UADPNETWORKMESSAGECONTENTMASK]);
34326 value->hasValue = true;
34327 return UA_STATUSCODE_GOOD;
34328}
34329
34330static UA_StatusCode
34331writeContentMask(UA_Server *server, const UA_NodeId *sessionId,
34332 void *sessionContext, const UA_NodeId *nodeId,
34333 void *nodeContext, const UA_NumericRange *range,
34334 const UA_DataValue *value) {
34335 UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext;
34336 if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED &&
34337 writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) ||
34338 writerGroup->config.messageSettings.content.decoded.type !=
34339 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])
34340 return UA_STATUSCODE_BADINTERNALERROR;
34341 UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*)
34342 writerGroup->config.messageSettings.content.decoded.data;
34343
34344 if(!value->value.type)
34345 return UA_STATUSCODE_BADTYPEMISMATCH;
34346 if(value->value.type->typeKind != UA_DATATYPEKIND_ENUM &&
34347 value->value.type->typeKind != UA_DATATYPEKIND_INT32)
34348 return UA_STATUSCODE_BADTYPEMISMATCH;
34349
34350 wgm->networkMessageContentMask = *(UA_UadpNetworkMessageContentMask*)value->value.data;
34351 return UA_STATUSCODE_GOOD;
34352}
34353
34354UA_StatusCode
34355addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup){
34356 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34357 if(writerGroup->config.name.length > 512)
34358 return UA_STATUSCODE_BADOUTOFMEMORY;
34359 char wgName[513];
34360 memcpy(wgName, writerGroup->config.name.data, writerGroup->config.name.length);
34361 wgName[writerGroup->config.name.length] = '\0';
34362
34363 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34364 object_attr.displayName = UA_LOCALIZEDTEXT("", wgName);
34365 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create a new id */
34366 writerGroup->linkedConnection->identifier,
34367 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34368 UA_QUALIFIEDNAME(0, wgName),
34369 UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE),
34370 object_attr, NULL, &writerGroup->identifier);
34371
34372 UA_NodeId keepAliveNode =
34373 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeepAliveTime"),
34374 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34375 writerGroup->identifier);
34376 UA_NodeId publishingIntervalNode =
34377 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
34378 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34379 writerGroup->identifier);
34380 if(UA_NodeId_isNull(&keepAliveNode) ||
34381 UA_NodeId_isNull(&publishingIntervalNode))
34382 return UA_STATUSCODE_BADNOTFOUND;
34383
34384 UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *)
34385 UA_malloc(sizeof(UA_NodePropertyContext));
34386 publishingIntervalContext->parentNodeId = writerGroup->identifier;
34387 publishingIntervalContext->parentClassifier = UA_NS0ID_WRITERGROUPTYPE;
34388 publishingIntervalContext->elementClassiefier = UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL;
34389 UA_ValueCallback valueCallback;
34390 valueCallback.onRead = onRead;
34391 valueCallback.onWrite = onWrite;
34392 retVal |= addVariableValueSource(server, valueCallback,
34393 publishingIntervalNode, publishingIntervalContext);
34394 UA_Server_writeAccessLevel(server, publishingIntervalNode,
34395 UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE);
34396
34397 UA_NodeId priorityNode =
34398 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "Priority"),
34399 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34400 writerGroup->identifier);
34401 UA_NodeId writerGroupIdNode =
34402 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "WriterGroupId"),
34403 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34404 writerGroup->identifier);
34405
34406 UA_Variant value;
34407 UA_Variant_init(&value);
34408 UA_Variant_setScalar(&value, &writerGroup->config.publishingInterval, &UA_TYPES[UA_TYPES_DURATION]);
34409 UA_Server_writeValue(server, publishingIntervalNode, value);
34410 UA_Variant_setScalar(&value, &writerGroup->config.keepAliveTime, &UA_TYPES[UA_TYPES_DURATION]);
34411 UA_Server_writeValue(server, keepAliveNode, value);
34412 UA_Variant_setScalar(&value, &writerGroup->config.priority, &UA_TYPES[UA_TYPES_BYTE]);
34413 UA_Server_writeValue(server, priorityNode, value);
34414 UA_Variant_setScalar(&value, &writerGroup->config.writerGroupId, &UA_TYPES[UA_TYPES_UINT16]);
34415 UA_Server_writeValue(server, writerGroupIdNode, value);
34416
34417 object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
34418 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
34419 writerGroup->identifier,
34420 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34421 UA_QUALIFIEDNAME(0, "MessageSettings"),
34422 UA_NODEID_NUMERIC(0, UA_NS0ID_UADPWRITERGROUPMESSAGETYPE),
34423 object_attr, NULL, NULL);
34424
34425 /* Find the variable with the content mask */
34426
34427 UA_NodeId messageSettingsId =
34428 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "MessageSettings"),
34429 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34430 writerGroup->identifier);
34431 UA_NodeId contentMaskId =
34432 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "NetworkMessageContentMask"),
34433 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), messageSettingsId);
34434 if(!UA_NodeId_isNull(&contentMaskId)) {
34435 /* Set the callback */
34436 UA_DataSource ds;
34437 ds.read = readContentMask;
34438 ds.write = writeContentMask;
34439 UA_Server_setVariableNode_dataSource(server, contentMaskId, ds);
34440 UA_Server_setNodeContext(server, contentMaskId, writerGroup);
34441
34442 /* Make writable */
34443 UA_Server_writeAccessLevel(server, contentMaskId,
34444 UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ);
34445
34446 }
34447
34448 /* Add reference to methods */
34449#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34450 retVal |= UA_Server_addReference(server, writerGroup->identifier,
34451 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34452 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), true);
34453 retVal |= UA_Server_addReference(server, writerGroup->identifier,
34454 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34455 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), true);
34456#endif
34457
34458 return retVal;
34459}
34460
34461#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34462static UA_StatusCode
34463addWriterGroupAction(UA_Server *server,
34464 const UA_NodeId *sessionId, void *sessionHandle,
34465 const UA_NodeId *methodId, void *methodContext,
34466 const UA_NodeId *objectId, void *objectContext,
34467 size_t inputSize, const UA_Variant *input,
34468 size_t outputSize, UA_Variant *output){
34469 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34470 UA_WriterGroupDataType *writerGroupDataType = ((UA_WriterGroupDataType *) input[0].data);
34471 UA_NodeId writerGroupId;
34472 retVal |= addWriterGroupConfig(server, *objectId, writerGroupDataType, &writerGroupId);
34473 if(retVal != UA_STATUSCODE_GOOD) {
34474 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addWriterGroup failed");
34475 return retVal;
34476 }
34477 //TODO: Need to handle the UA_Server_setWriterGroupOperational based on the status variable in information model
34478
34479 UA_Variant_setScalarCopy(output, &writerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
34480 return retVal;
34481}
34482#endif
34483
34484UA_StatusCode
34485removeGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) {
34486 return UA_Server_deleteNode(server, writerGroup->identifier, true);
34487}
34488
34489UA_StatusCode
34490removeReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
34491 return UA_Server_deleteNode(server, readerGroup->identifier, true);
34492}
34493
34494#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34495static UA_StatusCode
34496removeGroupAction(UA_Server *server,
34497 const UA_NodeId *sessionId, void *sessionHandle,
34498 const UA_NodeId *methodId, void *methodContext,
34499 const UA_NodeId *objectId, void *objectContext,
34500 size_t inputSize, const UA_Variant *input,
34501 size_t outputSize, UA_Variant *output){
34502 UA_NodeId nodeToRemove = *((UA_NodeId *)input->data);
34503 if(UA_WriterGroup_findWGbyId(server, nodeToRemove)) {
34504 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, nodeToRemove);
34505 if(wg->configurationFrozen)
34506 UA_Server_unfreezeWriterGroupConfiguration(server, nodeToRemove);
34507 return UA_Server_removeWriterGroup(server, nodeToRemove);
34508 } else {
34509 UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, nodeToRemove);
34510 if(rg->configurationFrozen)
34511 UA_Server_unfreezeReaderGroupConfiguration(server, nodeToRemove);
34512 return UA_Server_removeReaderGroup(server, nodeToRemove);
34513 }
34514}
34515#endif
34516
34517/**********************************************/
34518/* ReaderGroup */
34519/**********************************************/
34520
34521UA_StatusCode
34522addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) {
34523 if(readerGroup->config.name.length > 512)
34524 return UA_STATUSCODE_BADCONFIGURATIONERROR;
34525 char rgName[513];
34526 memcpy(rgName, readerGroup->config.name.data, readerGroup->config.name.length);
34527 rgName[readerGroup->config.name.length] = '\0';
34528
34529 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34530 object_attr.displayName = UA_LOCALIZEDTEXT("", rgName);
34531 UA_StatusCode retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
34532 readerGroup->linkedConnection,
34533 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34534 UA_QUALIFIEDNAME(0, rgName),
34535 UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE),
34536 object_attr, NULL, &readerGroup->identifier);
34537#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34538 retVal |= UA_Server_addReference(server, readerGroup->identifier,
34539 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34540 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), true);
34541 retVal |= UA_Server_addReference(server, readerGroup->identifier,
34542 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34543 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), true);
34544#endif
34545 return retVal;
34546}
34547
34548#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34549static UA_StatusCode
34550addReaderGroupAction(UA_Server *server,
34551 const UA_NodeId *sessionId, void *sessionHandle,
34552 const UA_NodeId *methodId, void *methodContext,
34553 const UA_NodeId *objectId, void *objectContext,
34554 size_t inputSize, const UA_Variant *input,
34555 size_t outputSize, UA_Variant *output){
34556 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34557 UA_ReaderGroupDataType *readerGroupDataType = ((UA_ReaderGroupDataType *) input->data);
34558 UA_NodeId readerGroupId;
34559 retVal |= addReaderGroupConfig(server, *objectId, readerGroupDataType, &readerGroupId);
34560 if(retVal != UA_STATUSCODE_GOOD) {
34561 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "addReaderGroup failed");
34562 return retVal;
34563 }
34564 //TODO: Need to handle the UA_Server_setReaderGroupOperational based on the status variable in information model
34565
34566 UA_Variant_setScalarCopy(output, &readerGroupId, &UA_TYPES[UA_TYPES_NODEID]);
34567 return retVal;
34568}
34569#endif
34570
34571/**********************************************/
34572/* DataSetWriter */
34573/**********************************************/
34574
34575UA_StatusCode
34576addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter){
34577 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34578 if(dataSetWriter->config.name.length > 512)
34579 return UA_STATUSCODE_BADOUTOFMEMORY;
34580 char dswName[513];
34581 memcpy(dswName, dataSetWriter->config.name.data, dataSetWriter->config.name.length);
34582 dswName[dataSetWriter->config.name.length] = '\0';
34583
34584 UA_ObjectAttributes object_attr = UA_ObjectAttributes_default;
34585 object_attr.displayName = UA_LOCALIZEDTEXT("", dswName);
34586 retVal = UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0), /* create an id */
34587 dataSetWriter->linkedWriterGroup,
34588 UA_NODEID_NUMERIC(0, UA_NS0ID_HASDATASETWRITER),
34589 UA_QUALIFIEDNAME(0, dswName),
34590 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE),
34591 object_attr, NULL, &dataSetWriter->identifier);
34592
34593 retVal |= UA_Server_addReference(server, dataSetWriter->connectedDataSet,
34594 UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETTOWRITER),
34595 UA_EXPANDEDNODEID_NODEID(dataSetWriter->identifier),
34596 true);
34597
34598 UA_NodeId dataSetWriterIdNode =
34599 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
34600 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34601 dataSetWriter->identifier);
34602 UA_NodeId keyFrameNode =
34603 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "KeyFrameCount"),
34604 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34605 dataSetWriter->identifier);
34606 UA_NodeId dataSetFieldContentMaskNode =
34607 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetFieldContentMask"),
34608 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34609 dataSetWriter->identifier);
34610
34611 UA_NodePropertyContext *dataSetWriterIdContext = (UA_NodePropertyContext *)
34612 UA_malloc(sizeof(UA_NodePropertyContext));
34613 dataSetWriterIdContext->parentNodeId = dataSetWriter->identifier;
34614 dataSetWriterIdContext->parentClassifier = UA_NS0ID_DATASETWRITERTYPE;
34615 dataSetWriterIdContext->elementClassiefier = UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID;
34616 UA_ValueCallback valueCallback;
34617 valueCallback.onRead = onRead;
34618 valueCallback.onWrite = NULL;
34619 retVal |= addVariableValueSource(server, valueCallback,
34620 dataSetWriterIdNode, dataSetWriterIdContext);
34621
34622 UA_Variant value;
34623 UA_Variant_init(&value);
34624 UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetWriterId,
34625 &UA_TYPES[UA_TYPES_UINT16]);
34626 UA_Server_writeValue(server, dataSetWriterIdNode, value);
34627 UA_Variant_setScalar(&value, &dataSetWriter->config.keyFrameCount,
34628 &UA_TYPES[UA_TYPES_UINT32]);
34629 UA_Server_writeValue(server, keyFrameNode, value);
34630 UA_Variant_setScalar(&value, &dataSetWriter->config.dataSetFieldContentMask,
34631 &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK]);
34632 UA_Server_writeValue(server, dataSetFieldContentMaskNode, value);
34633
34634 object_attr.displayName = UA_LOCALIZEDTEXT("", "MessageSettings");
34635 retVal |= UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, 0),
34636 dataSetWriter->identifier,
34637 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34638 UA_QUALIFIEDNAME(0, "MessageSettings"),
34639 UA_NODEID_NUMERIC(0, UA_NS0ID_UADPDATASETWRITERMESSAGETYPE),
34640 object_attr, NULL, NULL);
34641 return retVal;
34642}
34643
34644#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34645static UA_StatusCode
34646addDataSetWriterAction(UA_Server *server,
34647 const UA_NodeId *sessionId, void *sessionHandle,
34648 const UA_NodeId *methodId, void *methodContext,
34649 const UA_NodeId *objectId, void *objectContext,
34650 size_t inputSize, const UA_Variant *input,
34651 size_t outputSize, UA_Variant *output){
34652 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34653 UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, *objectId);
34654 if(!wg) {
34655 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34656 "Not a WriterGroup");
34657 return UA_STATUSCODE_BAD;
34658 }
34659 if(wg->configurationFrozen) {
34660 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34661 "addDataSetWriter cannot be done because writergroup config frozen");
34662 return UA_STATUSCODE_BAD;
34663 }
34664
34665 UA_NodeId dataSetWriterId;
34666 UA_DataSetWriterDataType *dataSetWriterData = (UA_DataSetWriterDataType *)input->data;
34667 retVal |= addDataSetWriterConfig(server, objectId, dataSetWriterData, &dataSetWriterId);
34668 if(retVal != UA_STATUSCODE_GOOD) {
34669 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
34670 "addDataSetWriter failed");
34671 return retVal;
34672 }
34673
34674 UA_Variant_setScalarCopy(output, &dataSetWriterId, &UA_TYPES[UA_TYPES_NODEID]);
34675 return UA_STATUSCODE_GOOD;
34676}
34677#endif
34678
34679
34680UA_StatusCode
34681removeDataSetWriterRepresentation(UA_Server *server,
34682 UA_DataSetWriter *dataSetWriter) {
34683 return UA_Server_deleteNode(server, dataSetWriter->identifier, true);
34684}
34685
34686#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34687static UA_StatusCode
34688removeDataSetWriterAction(UA_Server *server,
34689 const UA_NodeId *sessionId, void *sessionHandle,
34690 const UA_NodeId *methodId, void *methodContext,
34691 const UA_NodeId *objectId, void *objectContext,
34692 size_t inputSize, const UA_Variant *input,
34693 size_t outputSize, UA_Variant *output){
34694 UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data);
34695 return UA_Server_removeDataSetWriter(server, nodeToRemove);
34696}
34697#endif
34698
34699/**********************************************/
34700/* Destructors */
34701/**********************************************/
34702
34703static void
34704connectionTypeDestructor(UA_Server *server,
34705 const UA_NodeId *sessionId, void *sessionContext,
34706 const UA_NodeId *typeId, void *typeContext,
34707 const UA_NodeId *nodeId, void **nodeContext) {
34708 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34709 "Connection destructor called!");
34710 UA_NodeId publisherIdNode =
34711 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
34712 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34713 UA_NodePropertyContext *ctx;
34714 UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
34715 if(!UA_NodeId_isNull(&publisherIdNode))
34716 UA_free(ctx);
34717}
34718
34719static void
34720writerGroupTypeDestructor(UA_Server *server,
34721 const UA_NodeId *sessionId, void *sessionContext,
34722 const UA_NodeId *typeId, void *typeContext,
34723 const UA_NodeId *nodeId, void **nodeContext) {
34724 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34725 "WriterGroup destructor called!");
34726 UA_NodeId intervalNode =
34727 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishingInterval"),
34728 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34729 UA_NodePropertyContext *ctx;
34730 UA_Server_getNodeContext(server, intervalNode, (void **)&ctx);
34731 if(!UA_NodeId_isNull(&intervalNode))
34732 UA_free(ctx);
34733}
34734
34735static void
34736readerGroupTypeDestructor(UA_Server *server,
34737 const UA_NodeId *sessionId, void *sessionContext,
34738 const UA_NodeId *typeId, void *typeContext,
34739 const UA_NodeId *nodeId, void **nodeContext) {
34740 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34741 "ReaderGroup destructor called!");
34742}
34743
34744static void
34745dataSetWriterTypeDestructor(UA_Server *server,
34746 const UA_NodeId *sessionId, void *sessionContext,
34747 const UA_NodeId *typeId, void *typeContext,
34748 const UA_NodeId *nodeId, void **nodeContext) {
34749 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34750 "DataSetWriter destructor called!");
34751 UA_NodeId dataSetWriterIdNode =
34752 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetWriterId"),
34753 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34754 UA_NodePropertyContext *ctx;
34755 UA_Server_getNodeContext(server, dataSetWriterIdNode, (void **)&ctx);
34756 if(!UA_NodeId_isNull(&dataSetWriterIdNode))
34757 UA_free(ctx);
34758}
34759
34760static void
34761dataSetReaderTypeDestructor(UA_Server *server,
34762 const UA_NodeId *sessionId, void *sessionContext,
34763 const UA_NodeId *typeId, void *typeContext,
34764 const UA_NodeId *nodeId, void **nodeContext) {
34765 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34766 "DataSetReader destructor called!");
34767
34768 /* Deallocate the memory allocated for publisherId */
34769 UA_NodeId publisherIdNode =
34770 findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublisherId"),
34771 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34772 UA_NodePropertyContext *ctx;
34773 UA_Server_getNodeContext(server, publisherIdNode, (void **)&ctx);
34774 if(!UA_NodeId_isNull(&publisherIdNode))
34775 UA_free(ctx);
34776}
34777
34778static void
34779publishedDataItemsTypeDestructor(UA_Server *server,
34780 const UA_NodeId *sessionId, void *sessionContext,
34781 const UA_NodeId *typeId, void *typeContext,
34782 const UA_NodeId *nodeId, void **nodeContext) {
34783 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_USERLAND,
34784 "PublishedDataItems destructor called!");
34785 void *childContext;
34786 UA_NodeId node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "PublishedData"),
34787 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34788 UA_Server_getNodeContext(server, node, (void**)&childContext);
34789 if(!UA_NodeId_isNull(&node))
34790 UA_free(childContext);
34791
34792 node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "ConfigurationVersion"),
34793 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY),
34794 *nodeId);
34795 UA_Server_getNodeContext(server, node, (void**)&childContext);
34796 if(!UA_NodeId_isNull(&node))
34797 UA_free(childContext);
34798
34799 node = findSingleChildNode(server, UA_QUALIFIEDNAME(0, "DataSetMetaData"),
34800 UA_NODEID_NUMERIC(0, UA_NS0ID_HASPROPERTY), *nodeId);
34801 UA_Server_getNodeContext(server, node, (void**)&childContext);
34802 if(!UA_NodeId_isNull(&node))
34803 UA_free(childContext);
34804}
34805
34806/*************************************/
34807/* PubSub configurator */
34808/*************************************/
34809
34810#if defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG)
34811
34812/* Callback function that will be executed when the method "PubSub configurator
34813 * (replace config)" is called. */
34814static UA_StatusCode
34815UA_loadPubSubConfigMethodCallback(UA_Server *server,
34816 const UA_NodeId *sessionId, void *sessionHandle,
34817 const UA_NodeId *methodId, void *methodContext,
34818 const UA_NodeId *objectId, void *objectContext,
34819 size_t inputSize, const UA_Variant *input,
34820 size_t outputSize, UA_Variant *output) {
34821 if(inputSize == 1) {
34822 UA_ByteString *inputStr = (UA_ByteString*)input->data;
34823 return UA_PubSubManager_loadPubSubConfigFromByteString(server, *inputStr);
34824 } else if(inputSize > 1) {
34825 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
34826 } else {
34827 return UA_STATUSCODE_BADARGUMENTSMISSING;
34828 }
34829}
34830
34831/* Adds method node to server. This method is used to load binary files for
34832 * PubSub configuration and delete / replace old PubSub configurations. */
34833static UA_StatusCode
34834UA_addLoadPubSubConfigMethod(UA_Server *server) {
34835 UA_Argument inputArgument;
34836 UA_Argument_init(&inputArgument);
34837 inputArgument.description = UA_LOCALIZEDTEXT("", "PubSub config binfile");
34838 inputArgument.name = UA_STRING("BinFile");
34839 inputArgument.dataType = UA_TYPES[UA_TYPES_BYTESTRING].typeId;
34840 inputArgument.valueRank = UA_VALUERANK_SCALAR;
34841
34842 UA_MethodAttributes configAttr = UA_MethodAttributes_default;
34843 configAttr.description = UA_LOCALIZEDTEXT("","Load binary configuration file");
34844 configAttr.displayName = UA_LOCALIZEDTEXT("","LoadPubSubConfigurationFile");
34845 configAttr.executable = true;
34846 configAttr.userExecutable = true;
34847 return UA_Server_addMethodNode(server, UA_NODEID_NULL,
34848 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34849 UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
34850 UA_QUALIFIEDNAME(1, "PubSub configuration"),
34851 configAttr, &UA_loadPubSubConfigMethodCallback,
34852 1, &inputArgument, 0, NULL, NULL, NULL);
34853}
34854
34855/* Callback function that will be executed when the method "PubSub configurator
34856 * (delete config)" is called. */
34857static UA_StatusCode
34858UA_deletePubSubConfigMethodCallback(UA_Server *server,
34859 const UA_NodeId *sessionId, void *sessionHandle,
34860 const UA_NodeId *methodId, void *methodContext,
34861 const UA_NodeId *objectId, void *objectContext,
34862 size_t inputSize, const UA_Variant *input,
34863 size_t outputSize, UA_Variant *output) {
34864 UA_PubSubManager_delete(server, &(server->pubSubManager));
34865 return UA_STATUSCODE_GOOD;
34866}
34867
34868/* Adds method node to server. This method is used to delete the current PubSub
34869 * configuration. */
34870static UA_StatusCode
34871UA_addDeletePubSubConfigMethod(UA_Server *server) {
34872 UA_MethodAttributes configAttr = UA_MethodAttributes_default;
34873 configAttr.description = UA_LOCALIZEDTEXT("","Delete current PubSub configuration");
34874 configAttr.displayName = UA_LOCALIZEDTEXT("","DeletePubSubConfiguration");
34875 configAttr.executable = true;
34876 configAttr.userExecutable = true;
34877 return UA_Server_addMethodNode(server, UA_NODEID_NULL,
34878 UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34879 UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT),
34880 UA_QUALIFIEDNAME(1, "Delete PubSub config"),
34881 configAttr, &UA_deletePubSubConfigMethodCallback,
34882 0, NULL, 0, NULL, NULL, NULL);
34883}
34884
34885#endif /* defined(UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG) */
34886
34887UA_StatusCode
34888UA_Server_initPubSubNS0(UA_Server *server) {
34889 UA_StatusCode retVal = UA_STATUSCODE_GOOD;
34890 UA_String profileArray[1];
34891 profileArray[0] = UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
34892
34893 retVal |= writePubSubNs0VariableArray(server, UA_NS0ID_PUBLISHSUBSCRIBE_SUPPORTEDTRANSPORTPROFILES,
34894 profileArray, 1, &UA_TYPES[UA_TYPES_STRING]);
34895
34896#ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL_METHODS
34897 /* Add missing references */
34898 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34899 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34900 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true);
34901 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34902 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34903 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true);
34904 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34905 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34906 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true);
34907 retVal |= UA_Server_addReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS),
34908 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
34909 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true);
34910
34911 /* Set method callbacks */
34912 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), addPubSubConnectionAction);
34913 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), removeConnectionAction);
34914 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), addDataSetFolderAction);
34915 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), removeDataSetFolderAction);
34916 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), addPublishedDataItemsAction);
34917 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), removePublishedDataSetAction);
34918 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), addVariablesAction);
34919 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), removeVariablesAction);
34920 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), addWriterGroupAction);
34921 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), addReaderGroupAction);
34922 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), removeGroupAction);
34923 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), addDataSetWriterAction);
34924 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), removeDataSetWriterAction);
34925 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), addDataSetReaderAction);
34926 retVal |= UA_Server_setMethodNodeCallback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), removeDataSetReaderAction);
34927
34928#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
34929 retVal |= UA_addLoadPubSubConfigMethod(server);
34930 retVal |= UA_addDeletePubSubConfigMethod(server);
34931#endif
34932
34933#else
34934 /* Remove methods */
34935 retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34936 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
34937 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION),
34938 false);
34939 retVal |= UA_Server_deleteReference(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE),
34940 UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), true,
34941 UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION),
34942 false);
34943#endif
34944
34945 /* Set the object-type destructors */
34946 UA_NodeTypeLifecycle lifeCycle;
34947 lifeCycle.constructor = NULL;
34948
34949 lifeCycle.destructor = connectionTypeDestructor;
34950 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBSUBCONNECTIONTYPE), lifeCycle);
34951
34952 lifeCycle.destructor = writerGroupTypeDestructor;
34953 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_WRITERGROUPTYPE), lifeCycle);
34954
34955 lifeCycle.destructor = readerGroupTypeDestructor;
34956 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_READERGROUPTYPE), lifeCycle);
34957
34958 lifeCycle.destructor = dataSetWriterTypeDestructor;
34959 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETWRITERTYPE), lifeCycle);
34960
34961 lifeCycle.destructor = publishedDataItemsTypeDestructor;
34962 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), lifeCycle);
34963
34964 lifeCycle.destructor = dataSetReaderTypeDestructor;
34965 retVal |= UA_Server_setNodeTypeLifecycle(server, UA_NODEID_NUMERIC(0, UA_NS0ID_DATASETREADERTYPE), lifeCycle);
34966
34967 return retVal;
34968}
34969
34970#endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */
34971
34972/**** amalgamated original file "/src/server/ua_services_view.c" ****/
34973
34974/* This Source Code Form is subject to the terms of the Mozilla Public
34975 * License, v. 2.0. If a copy of the MPL was not distributed with this
34976 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
34977 *
34978 * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
34979 * Copyright 2014-2017 (c) Florian Palm
34980 * Copyright 2015-2016 (c) Sten Grüner
34981 * Copyright 2015 (c) LEvertz
34982 * Copyright 2015 (c) Chris Iatrou
34983 * Copyright 2015 (c) Ecosmos
34984 * Copyright 2015-2016 (c) Oleksiy Vasylyev
34985 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
34986 * Copyright 2016 (c) Lorenz Haas
34987 * Copyright 2017 (c) pschoppe
34988 * Copyright 2017 (c) Julian Grothoff
34989 * Copyright 2017 (c) Henrik Norrman
34990 */
34991
34992
34993#define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */
34994
34995UA_StatusCode
34996referenceTypeIndices(UA_Server *server, const UA_NodeId *refType,
34997 UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes) {
34998 if(UA_NodeId_isNull(p: refType)) {
34999 UA_ReferenceTypeSet_any(set: indices);
35000 return UA_STATUSCODE_GOOD;
35001 }
35002
35003 UA_ReferenceTypeSet_init(set: indices);
35004 const UA_Node *refNode = UA_NODESTORE_GET(server, refType);
35005 if(!refNode)
35006 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35007
35008 if(refNode->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
35009 UA_NODESTORE_RELEASE(server, refNode);
35010 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35011 }
35012
35013 if(!includeSubtypes)
35014 *indices = UA_REFTYPESET(index: refNode->referenceTypeNode.referenceTypeIndex);
35015 else
35016 *indices = refNode->referenceTypeNode.subTypes;
35017
35018 UA_NODESTORE_RELEASE(server, refNode);
35019 return UA_STATUSCODE_GOOD;
35020}
35021
35022static UA_Boolean
35023matchClassMask(const UA_Node *node, UA_UInt32 nodeClassMask) {
35024 if(nodeClassMask != UA_NODECLASS_UNSPECIFIED &&
35025 (node->head.nodeClass & nodeClassMask) == 0)
35026 return false;
35027 return true;
35028}
35029
35030/****************/
35031/* IsNodeInTree */
35032/****************/
35033
35034/* Internal method to check if a node is already upwards from a leaf node */
35035
35036/* Keeps track of visited nodes to detect circular references */
35037struct ref_history {
35038 struct ref_history *parent; /* the previous element */
35039 const UA_NodePointer id; /* the id of the node at this depth */
35040 UA_UInt16 depth;
35041};
35042
35043static UA_Boolean
35044isNodeInTreeNoCircular(UA_Server *server,
35045 UA_NodePointer leafNode,
35046 UA_NodePointer nodeToFind,
35047 struct ref_history *visitedRefs,
35048 const UA_ReferenceTypeSet *relevantRefs) {
35049 if(UA_NodePointer_equal(p1: nodeToFind, p2: leafNode))
35050 return true;
35051
35052 if(visitedRefs->depth >= UA_MAX_TREE_RECURSE)
35053 return false;
35054
35055 const UA_Node *node = UA_NODESTORE_GETFROMREF(server, target: leafNode);
35056 if(!node)
35057 return false;
35058
35059 for(size_t i = 0; i < node->head.referencesSize; ++i) {
35060 UA_NodeReferenceKind *rk = &node->head.references[i];
35061 /* Search upwards in the tree */
35062 if(!rk->isInverse)
35063 continue;
35064
35065 /* Consider only the indicated reference types */
35066 if(!UA_ReferenceTypeSet_contains(set: relevantRefs, index: rk->referenceTypeIndex))
35067 continue;
35068
35069 /* Match the targets or recurse */
35070 const UA_ReferenceTarget *t = NULL;
35071 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
35072 /* Don't follow remote targets */
35073 if(!UA_NodePointer_isLocal(np: t->targetId))
35074 continue;
35075
35076 /* Check if we already have seen the referenced node and skip to
35077 * avoid endless recursion. Do this only at every 5th depth to save
35078 * effort. Circular dependencies are rare and forbidden for most
35079 * reference types. */
35080 if(visitedRefs->depth % 5 == 4) {
35081 struct ref_history *last = visitedRefs;
35082 UA_Boolean skip = false;
35083 while(last) {
35084 if(UA_NodePointer_equal(p1: last->id, p2: t->targetId)) {
35085 skip = true;
35086 break;
35087 }
35088 last = last->parent;
35089 }
35090 if(skip)
35091 continue;
35092 }
35093
35094 /* Stack-allocate the visitedRefs structure for the next depth */
35095 struct ref_history nextVisitedRefs = {visitedRefs, t->targetId,
35096 (UA_UInt16)(visitedRefs->depth+1)};
35097
35098 /* Recurse */
35099 UA_Boolean foundRecursive =
35100 isNodeInTreeNoCircular(server, leafNode: t->targetId, nodeToFind,
35101 visitedRefs: &nextVisitedRefs, relevantRefs);
35102 if(foundRecursive) {
35103 UA_NODESTORE_RELEASE(server, node);
35104 return true;
35105 }
35106 }
35107 }
35108
35109 UA_NODESTORE_RELEASE(server, node);
35110 return false;
35111}
35112
35113UA_Boolean
35114isNodeInTree(UA_Server *server, const UA_NodeId *leafNode,
35115 const UA_NodeId *nodeToFind,
35116 const UA_ReferenceTypeSet *relevantRefs) {
35117 UA_NodePointer leafP = UA_NodePointer_fromNodeId(id: leafNode);
35118 UA_NodePointer targetP = UA_NodePointer_fromNodeId(id: nodeToFind);
35119 struct ref_history visitedRefs = {NULL, leafP, 0};
35120 return isNodeInTreeNoCircular(server, leafNode: leafP, nodeToFind: targetP,
35121 visitedRefs: &visitedRefs, relevantRefs);
35122}
35123
35124UA_Boolean
35125isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode,
35126 const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex) {
35127 UA_ReferenceTypeSet reftypes = UA_REFTYPESET(index: relevantRefTypeIndex);
35128 return isNodeInTree(server, leafNode, nodeToFind, relevantRefs: &reftypes);
35129}
35130
35131static enum ZIP_CMP
35132cmpTarget(const void *a, const void *b) {
35133 const RefEntry *aa = (const RefEntry*)a;
35134 const RefEntry *bb = (const RefEntry*)b;
35135 if(aa->targetHash < bb->targetHash)
35136 return ZIP_CMP_LESS;
35137 if(aa->targetHash > bb->targetHash)
35138 return ZIP_CMP_MORE;
35139 return (enum ZIP_CMP)UA_ExpandedNodeId_order(n1: aa->target, n2: bb->target);
35140}
35141
35142ZIP_FUNCTIONS(RefHead, RefEntry, zipfields, RefEntry, zipfields, cmpTarget)
35143
35144UA_StatusCode
35145RefTree_init(RefTree *rt) {
35146 rt->size = 0;
35147 rt->capacity = 0;
35148 ZIP_INIT(&rt->head);
35149 size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * UA_REFTREE_INITIAL_SIZE;
35150 rt->targets = (UA_ExpandedNodeId*)UA_malloc(size: space);
35151 if(!rt->targets)
35152 return UA_STATUSCODE_BADOUTOFMEMORY;
35153 rt->capacity = UA_REFTREE_INITIAL_SIZE;
35154 return UA_STATUSCODE_GOOD;
35155}
35156
35157void
35158RefTree_clear(RefTree *rt) {
35159 for(size_t i = 0; i < rt->size; i++)
35160 UA_ExpandedNodeId_clear(p: &rt->targets[i]);
35161 if(rt->targets)
35162 UA_free(ptr: rt->targets);
35163}
35164
35165/* Double the capacity of the reftree */
35166static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35167RefTree_double(RefTree *rt) {
35168 size_t capacity = rt->capacity * 2;
35169 UA_assert(capacity > 0);
35170 size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * capacity;
35171 UA_ExpandedNodeId *newTargets = (UA_ExpandedNodeId*)UA_realloc(ptr: rt->targets, size: space);
35172 if(!newTargets)
35173 return UA_STATUSCODE_BADOUTOFMEMORY;
35174
35175 /* Repair the pointers for the realloced array+tree */
35176 // What is this sorcery?
35177 // FIXME: This needs some cleaning up or explanation.
35178 // IMO uintptr could be completely avoided here.
35179 uintptr_t arraydiff = (uintptr_t)newTargets - (uintptr_t)rt->targets;
35180 RefEntry *reArray = (RefEntry*)
35181 ((uintptr_t)newTargets + (capacity * sizeof(UA_ExpandedNodeId)));
35182 uintptr_t entrydiff = (uintptr_t)reArray -
35183 ((uintptr_t)rt->targets + (rt->capacity * sizeof(UA_ExpandedNodeId)));
35184 RefEntry *oldReArray = (RefEntry*)
35185 ((uintptr_t)newTargets + (rt->capacity * sizeof(UA_ExpandedNodeId)));
35186 memmove(dest: reArray, src: oldReArray, n: rt->size * sizeof(RefEntry));
35187 for(size_t i = 0; i < rt->size; i++) {
35188 uintptr_t *left = (uintptr_t*)&ZIP_LEFT(&reArray[i], zipfields);
35189 uintptr_t *right = (uintptr_t*)&ZIP_RIGHT(&reArray[i], zipfields);
35190 if(*left != 0)
35191 *left += entrydiff;
35192 if(*right != 0)
35193 *right += entrydiff;
35194 reArray[i].target = (UA_ExpandedNodeId*)((uintptr_t)reArray[i].target + arraydiff);
35195 }
35196
35197 ZIP_ROOT(&rt->head) = (RefEntry*)((uintptr_t)ZIP_ROOT(&rt->head) + entrydiff);
35198 rt->capacity = capacity;
35199 rt->targets = newTargets;
35200 return UA_STATUSCODE_GOOD;
35201}
35202
35203static UA_StatusCode
35204RefTree_add(RefTree *rt, UA_NodePointer target, UA_Boolean *duplicate) {
35205 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: target);
35206
35207 /* Is the target already in the tree? */
35208 RefEntry dummy;
35209 memset(s: &dummy, c: 0, n: sizeof(RefEntry));
35210 dummy.target = &en;
35211 dummy.targetHash = UA_ExpandedNodeId_hash(n: &en);
35212 if(ZIP_FIND(RefHead, &rt->head, &dummy)) {
35213 if(duplicate)
35214 *duplicate = true;
35215 return UA_STATUSCODE_GOOD;
35216 }
35217
35218 UA_StatusCode s = UA_STATUSCODE_GOOD;
35219 if(rt->capacity <= rt->size) {
35220 s = RefTree_double(rt);
35221 if(s != UA_STATUSCODE_GOOD)
35222 return s;
35223 }
35224 s = UA_ExpandedNodeId_copy(src: &en, dst: &rt->targets[rt->size]);
35225 if(s != UA_STATUSCODE_GOOD)
35226 return s;
35227 RefEntry *re = (RefEntry*)((uintptr_t)rt->targets +
35228 (sizeof(UA_ExpandedNodeId) * rt->capacity) +
35229 (sizeof(RefEntry) * rt->size));
35230 re->target = &rt->targets[rt->size];
35231 re->targetHash = dummy.targetHash;
35232 ZIP_INSERT(RefHead, &rt->head, re, UA_UInt32_random());
35233 rt->size++;
35234 return UA_STATUSCODE_GOOD;
35235}
35236
35237UA_StatusCode
35238RefTree_addNodeId(RefTree *rt, const UA_NodeId *target,
35239 UA_Boolean *duplicate) {
35240 return RefTree_add(rt, target: UA_NodePointer_fromNodeId(id: target), duplicate);
35241}
35242
35243UA_Boolean
35244RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target) {
35245 RefEntry dummy;
35246 dummy.target = target;
35247 dummy.targetHash = UA_ExpandedNodeId_hash(n: target);
35248 return !!ZIP_FIND(RefHead, &rt->head, &dummy);
35249}
35250
35251UA_Boolean
35252RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target) {
35253 UA_ExpandedNodeId en;
35254 en.nodeId = *target;
35255 en.namespaceUri = UA_STRING_NULL;
35256 en.serverIndex = 0;
35257 return RefTree_contains(rt, target: &en);
35258}
35259
35260/********************/
35261/* Browse Recursive */
35262/********************/
35263
35264static UA_StatusCode
35265browseRecursiveInner(UA_Server *server, RefTree *rt, UA_UInt16 depth, UA_Boolean skip,
35266 UA_NodePointer nodeP, UA_BrowseDirection browseDirection,
35267 const UA_ReferenceTypeSet *refTypes, UA_UInt32 nodeClassMask) {
35268 /* Have we reached the max recursion depth? */
35269 if(depth >= UA_MAX_TREE_RECURSE)
35270 return UA_STATUSCODE_GOOD;
35271
35272 const UA_Node *node = UA_NODESTORE_GETFROMREF(server, target: nodeP);
35273 if(!node)
35274 return UA_STATUSCODE_BADNODEIDUNKNOWN;
35275
35276 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35277 const UA_NodeHead *head = &node->head;
35278
35279 /* Add the current node to the results if we don't want to skip it (i.e. for
35280 * includeStartNodes) and it matches the nodeClassMask filter. Process the
35281 * children also if the nodeClassMask does not match. */
35282 if(!skip && matchClassMask(node, nodeClassMask)) {
35283 UA_Boolean duplicate = false;
35284 retval = RefTree_addNodeId(rt, target: &head->nodeId, duplicate: &duplicate);
35285 if(duplicate || retval != UA_STATUSCODE_GOOD)
35286 goto cleanup;
35287 }
35288
35289 for(size_t i = 0; i < head->referencesSize; i++) {
35290 UA_NodeReferenceKind *rk = &head->references[i];
35291
35292 /* Reference in the right direction? */
35293 if(rk->isInverse && browseDirection == UA_BROWSEDIRECTION_FORWARD)
35294 continue;
35295 if(!rk->isInverse && browseDirection == UA_BROWSEDIRECTION_INVERSE)
35296 continue;
35297
35298 /* Is the reference part of the hierarchy of references we look for? */
35299 if(!UA_ReferenceTypeSet_contains(set: refTypes, index: rk->referenceTypeIndex))
35300 continue;
35301
35302 const UA_ReferenceTarget *target = NULL;
35303 while((target = UA_NodeReferenceKind_iterate(rk, prev: target))) {
35304 if(UA_NodePointer_isLocal(np: target->targetId)) {
35305 retval = browseRecursiveInner(server, rt, depth: (UA_UInt16)(depth+1), false,
35306 nodeP: target->targetId, browseDirection,
35307 refTypes, nodeClassMask);
35308 } else {
35309 retval = RefTree_add(rt, target: target->targetId, NULL);
35310 }
35311 if(retval != UA_STATUSCODE_GOOD)
35312 goto cleanup;
35313 }
35314 }
35315
35316 cleanup:
35317 UA_NODESTORE_RELEASE(server, node);
35318 return retval;
35319}
35320
35321UA_StatusCode
35322browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes,
35323 UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes,
35324 UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes,
35325 size_t *resultsSize, UA_ExpandedNodeId **results) {
35326 RefTree rt;
35327 UA_StatusCode retval = RefTree_init(rt: &rt);
35328 if(retval != UA_STATUSCODE_GOOD)
35329 return retval;
35330
35331 for(size_t i = 0; i < startNodesSize; i++) {
35332 /* Call the inner recursive browse separately for the search direction.
35333 * Otherwise we might take one step up and another step down in the
35334 * search tree. */
35335 if(browseDirection == UA_BROWSEDIRECTION_FORWARD ||
35336 browseDirection == UA_BROWSEDIRECTION_BOTH)
35337 retval |= browseRecursiveInner(server, rt: &rt, depth: 0, skip: !includeStartNodes,
35338 nodeP: UA_NodePointer_fromNodeId(id: &startNodes[i]),
35339 browseDirection: UA_BROWSEDIRECTION_FORWARD,
35340 refTypes, nodeClassMask);
35341 if(browseDirection == UA_BROWSEDIRECTION_INVERSE ||
35342 browseDirection == UA_BROWSEDIRECTION_BOTH)
35343 retval |= browseRecursiveInner(server, rt: &rt, depth: 0, skip: !includeStartNodes,
35344 nodeP: UA_NodePointer_fromNodeId(id: &startNodes[i]),
35345 browseDirection: UA_BROWSEDIRECTION_INVERSE,
35346 refTypes, nodeClassMask);
35347 if(retval != UA_STATUSCODE_GOOD)
35348 break;
35349 }
35350
35351 if(rt.size > 0 && retval == UA_STATUSCODE_GOOD) {
35352 *results = rt.targets;
35353 *resultsSize = rt.size;
35354 } else {
35355 RefTree_clear(rt: &rt);
35356 }
35357 return retval;
35358}
35359
35360UA_StatusCode
35361UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd,
35362 size_t *resultsSize, UA_ExpandedNodeId **results) {
35363 UA_LOCK(&server->serviceMutex);
35364
35365 /* Set the list of relevant reference types */
35366 UA_ReferenceTypeSet refTypes;
35367 UA_StatusCode retval = referenceTypeIndices(server, refType: &bd->referenceTypeId,
35368 indices: &refTypes, includeSubtypes: bd->includeSubtypes);
35369 if(retval != UA_STATUSCODE_GOOD) {
35370 UA_UNLOCK(&server->serviceMutex);
35371 return retval;
35372 }
35373
35374 /* Browse */
35375 retval = browseRecursive(server, startNodesSize: 1, startNodes: &bd->nodeId, browseDirection: bd->browseDirection,
35376 refTypes: &refTypes, nodeClassMask: bd->nodeClassMask, false, resultsSize, results);
35377
35378 UA_UNLOCK(&server->serviceMutex);
35379 return retval;
35380}
35381
35382/**********/
35383/* Browse */
35384/**********/
35385
35386typedef struct {
35387 size_t size;
35388 size_t capacity;
35389 UA_ReferenceDescription *descr;
35390} RefResult;
35391
35392static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35393RefResult_init(RefResult *rr) {
35394 memset(s: rr, c: 0, n: sizeof(RefResult));
35395 rr->descr = (UA_ReferenceDescription*)
35396 UA_Array_new(UA_REFTREE_INITIAL_SIZE, type: &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]);
35397 if(!rr->descr)
35398 return UA_STATUSCODE_BADOUTOFMEMORY;
35399 rr->capacity = UA_REFTREE_INITIAL_SIZE;
35400 rr->size = 0;
35401 return UA_STATUSCODE_GOOD;
35402}
35403
35404static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35405RefResult_double(RefResult *rr) {
35406 size_t newSize = rr->capacity * 2;
35407 UA_ReferenceDescription *rd = (UA_ReferenceDescription*)
35408 UA_realloc(ptr: rr->descr, size: newSize * sizeof(UA_ReferenceDescription));
35409 if(!rd)
35410 return UA_STATUSCODE_BADOUTOFMEMORY;
35411 memset(s: &rd[rr->size], c: 0, n: sizeof(UA_ReferenceDescription) * (newSize - rr->size));
35412 rr->descr = rd;
35413 rr->capacity = newSize;
35414 return UA_STATUSCODE_GOOD;
35415}
35416
35417static void
35418RefResult_clear(RefResult *rr) {
35419 UA_assert(rr->descr != NULL);
35420 for(size_t i = 0; i < rr->size; i++)
35421 UA_ReferenceDescription_clear(p: &rr->descr[i]);
35422 UA_free(ptr: rr->descr);
35423}
35424
35425struct ContinuationPoint {
35426 ContinuationPoint *next;
35427 UA_ByteString identifier;
35428
35429 /* Parameters of the Browse Request */
35430 UA_BrowseDescription browseDescription;
35431 UA_UInt32 maxReferences;
35432 UA_ReferenceTypeSet relevantReferences;
35433
35434 /* The next target to be transmitted to the client */
35435 UA_ExpandedNodeId nextTarget;
35436 UA_Byte nextRefKindIndex;
35437};
35438
35439ContinuationPoint *
35440ContinuationPoint_clear(ContinuationPoint *cp) {
35441 UA_ByteString_clear(p: &cp->identifier);
35442 UA_BrowseDescription_clear(p: &cp->browseDescription);
35443 UA_ExpandedNodeId_clear(p: &cp->nextTarget);
35444 return cp->next;
35445}
35446
35447/* Target node on top of the stack */
35448static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT
35449addReferenceDescription(UA_Server *server, RefResult *rr,
35450 const UA_NodeReferenceKind *ref, UA_UInt32 mask,
35451 UA_NodePointer nodeP, const UA_Node *curr) {
35452 /* Ensure capacity is left */
35453 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35454 if(rr->size >= rr->capacity) {
35455 retval = RefResult_double(rr);
35456 if(retval != UA_STATUSCODE_GOOD)
35457 return retval;
35458 }
35459
35460 UA_ReferenceDescription *descr = &rr->descr[rr->size];
35461
35462 /* Fields without access to the actual node */
35463 UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: nodeP);
35464 retval = UA_ExpandedNodeId_copy(src: &en, dst: &descr->nodeId);
35465 if(mask & UA_BROWSERESULTMASK_REFERENCETYPEID) {
35466 const UA_NodeId *refTypeId =
35467 UA_NODESTORE_GETREFERENCETYPEID(server, ref->referenceTypeIndex);
35468 retval |= UA_NodeId_copy(src: refTypeId, dst: &descr->referenceTypeId);
35469 }
35470 if(mask & UA_BROWSERESULTMASK_ISFORWARD)
35471 descr->isForward = !ref->isInverse;
35472
35473 /* Remote references (ExpandedNodeId) are not further looked up here */
35474 if(!curr) {
35475 UA_ReferenceDescription_clear(p: descr);
35476 return retval;
35477 }
35478
35479 /* Fields that require the actual node */
35480 if(mask & UA_BROWSERESULTMASK_NODECLASS)
35481 descr->nodeClass = curr->head.nodeClass;
35482 if(mask & UA_BROWSERESULTMASK_BROWSENAME)
35483 retval |= UA_QualifiedName_copy(src: &curr->head.browseName, dst: &descr->browseName);
35484 if(mask & UA_BROWSERESULTMASK_DISPLAYNAME)
35485 retval |= UA_LocalizedText_copy(src: &curr->head.displayName, dst: &descr->displayName);
35486 if(mask & UA_BROWSERESULTMASK_TYPEDEFINITION) {
35487 if(curr->head.nodeClass == UA_NODECLASS_OBJECT ||
35488 curr->head.nodeClass == UA_NODECLASS_VARIABLE) {
35489 const UA_Node *type = getNodeType(server, head: &curr->head);
35490 if(type) {
35491 retval |= UA_NodeId_copy(src: &type->head.nodeId, dst: &descr->typeDefinition.nodeId);
35492 UA_NODESTORE_RELEASE(server, type);
35493 }
35494 }
35495 }
35496
35497 if(retval == UA_STATUSCODE_GOOD)
35498 rr->size++; /* Increase the counter */
35499 else
35500 UA_ReferenceDescription_clear(p: descr);
35501 return retval;
35502}
35503
35504/* Returns whether the node / continuationpoint is done */
35505static UA_StatusCode
35506browseReferences(UA_Server *server, const UA_NodeHead *head,
35507 ContinuationPoint *cp, RefResult *rr, UA_Boolean *done) {
35508 UA_assert(cp);
35509 const UA_BrowseDescription *bd = &cp->browseDescription;
35510
35511 size_t i = 0;
35512 const UA_ReferenceTarget *ref = NULL;
35513
35514 /* If the cp was previously used, skip forward to the next ReferenceType to
35515 * be transmitted. */
35516 if(cp->identifier.length > 0) {
35517 for(; i < head->referencesSize; ++i) {
35518 UA_NodeReferenceKind *rk = &head->references[i];
35519
35520 /* Was this the last transmitted ReferenceType? */
35521 if(head->references[i].referenceTypeIndex != cp->nextRefKindIndex)
35522 continue;
35523
35524 /* Reference in the right direction? */
35525 if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
35526 continue;
35527 if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE)
35528 continue;
35529
35530 /* Get the next target */
35531 ref = UA_NodeReferenceKind_findTarget(rk, targetId: &cp->nextTarget);
35532 if(ref)
35533 break;
35534
35535 /* The target no longer exists for this ReferenceType (and
35536 * direction). Continue to iterate for the case that a nodestore has
35537 * a duplicate UA_NodeReferenceKind (should not happen though). */
35538 }
35539
35540 /* Fail with an error if the reference no longer exists. */
35541 if(!ref)
35542 return UA_STATUSCODE_BADINTERNALERROR;
35543 }
35544
35545 /* Loop over the ReferenceTypes */
35546 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35547 for(; i < head->referencesSize; ++i) {
35548 UA_NodeReferenceKind *rk = &head->references[i];
35549
35550 /* Reference in the right direction? */
35551 if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD)
35552 continue;
35553 if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE)
35554 continue;
35555
35556 /* Is the reference part of the hierarchy of references we look for? */
35557 if(!UA_ReferenceTypeSet_contains(set: &cp->relevantReferences,
35558 index: rk->referenceTypeIndex))
35559 continue;
35560
35561 /* We have a matching ReferenceType! */
35562
35563 /* Loop over the targets for the ReferenceType. Start with the first
35564 * entry if we don't have a known entry-point from the cp. */
35565 if(!ref)
35566 ref = UA_NodeReferenceKind_iterate(rk, prev: ref);
35567 for(;ref; ref = UA_NodeReferenceKind_iterate(rk, prev: ref)) {
35568 /* Get the node if it is not a remote reference */
35569 const UA_Node *target =
35570 UA_NODESTORE_GETFROMREF(server, target: ref->targetId);
35571
35572 /* Test if the node class matches */
35573 if(target && !matchClassMask(node: target, nodeClassMask: bd->nodeClassMask)) {
35574 UA_NODESTORE_RELEASE(server, target);
35575 continue;
35576 }
35577
35578 /* We have a matching target! */
35579
35580 /* Reached maxrefs. Update the cp and bail. */
35581 if(rr->size >= cp->maxReferences) {
35582 if(target)
35583 UA_NODESTORE_RELEASE(server, target);
35584 cp->nextRefKindIndex = rk->referenceTypeIndex;
35585 /* Make a deep copy */
35586 UA_ExpandedNodeId tmpEn =
35587 UA_NodePointer_toExpandedNodeId(np: ref->targetId);
35588 UA_ExpandedNodeId_clear(p: &cp->nextTarget);
35589 return UA_ExpandedNodeId_copy(src: &tmpEn, dst: &cp->nextTarget);
35590 }
35591
35592 /* Copy the node description. Target is on top of the stack */
35593 retval = addReferenceDescription(server, rr, ref: rk, mask: bd->resultMask,
35594 nodeP: ref->targetId, curr: target);
35595 if(target)
35596 UA_NODESTORE_RELEASE(server, target);
35597 if(retval != UA_STATUSCODE_GOOD)
35598 return retval;
35599 }
35600 }
35601
35602 /* The node is done */
35603 *done = true;
35604 return UA_STATUSCODE_GOOD;
35605}
35606
35607/* Results for a single browsedescription. This is the inner loop for both
35608 * Browse and BrowseNext. The ContinuationPoint contains all the data used.
35609 * Including the BrowseDescription. Returns whether there are remaining
35610 * references. */
35611static UA_Boolean
35612browseWithContinuation(UA_Server *server, UA_Session *session,
35613 ContinuationPoint *cp, UA_BrowseResult *result) {
35614 UA_assert(cp);
35615 const UA_BrowseDescription *descr = &cp->browseDescription;
35616
35617 /* Is the browsedirection valid? */
35618 if(descr->browseDirection != UA_BROWSEDIRECTION_BOTH &&
35619 descr->browseDirection != UA_BROWSEDIRECTION_FORWARD &&
35620 descr->browseDirection != UA_BROWSEDIRECTION_INVERSE) {
35621 result->statusCode = UA_STATUSCODE_BADBROWSEDIRECTIONINVALID;
35622 return true;
35623 }
35624
35625 /* Is the reference type valid? */
35626 if(!UA_NodeId_isNull(p: &descr->referenceTypeId)) {
35627 const UA_Node *reftype = UA_NODESTORE_GET(server, &descr->referenceTypeId);
35628 if(!reftype) {
35629 result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35630 return true;
35631 }
35632
35633 UA_Boolean isRef = (reftype->head.nodeClass == UA_NODECLASS_REFERENCETYPE);
35634 UA_NODESTORE_RELEASE(server, reftype);
35635
35636 if(!isRef) {
35637 result->statusCode = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
35638 return true;
35639 }
35640 }
35641
35642 const UA_Node *node = UA_NODESTORE_GET(server, &descr->nodeId);
35643 if(!node) {
35644 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
35645 return true;
35646 }
35647
35648 if(session != &server->adminSession &&
35649 !server->config.accessControl.
35650 allowBrowseNode(server, &server->config.accessControl,
35651 &session->sessionId, session->sessionHandle,
35652 &descr->nodeId, node->head.context)) {
35653 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
35654 UA_NODESTORE_RELEASE(server, node);
35655 return true;
35656 }
35657
35658 RefResult rr;
35659 result->statusCode = RefResult_init(rr: &rr);
35660 if(result->statusCode != UA_STATUSCODE_GOOD) {
35661 UA_NODESTORE_RELEASE(server, node);
35662 return true;
35663 }
35664
35665 /* Browse the references */
35666 UA_Boolean done = false;
35667 result->statusCode = browseReferences(server, head: &node->head, cp, rr: &rr, done: &done);
35668 UA_NODESTORE_RELEASE(server, node);
35669 if(result->statusCode != UA_STATUSCODE_GOOD) {
35670 RefResult_clear(rr: &rr);
35671 return true;
35672 }
35673
35674 /* Move results */
35675 if(rr.size > 0) {
35676 result->references = rr.descr;
35677 result->referencesSize = rr.size;
35678 } else {
35679 /* No relevant references, return array of length zero */
35680 RefResult_clear(rr: &rr);
35681 result->references = (UA_ReferenceDescription*)UA_EMPTY_ARRAY_SENTINEL;
35682 }
35683
35684 return done;
35685}
35686
35687/* Start to browse with no previous cp */
35688void
35689Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs,
35690 const UA_BrowseDescription *descr, UA_BrowseResult *result) {
35691 /* Stack-allocate a temporary cp */
35692 ContinuationPoint cp;
35693 memset(s: &cp, c: 0, n: sizeof(ContinuationPoint));
35694 cp.maxReferences = *maxrefs;
35695 cp.browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */
35696
35697 /* How many references can we return at most? */
35698 if(cp.maxReferences == 0) {
35699 if(server->config.maxReferencesPerNode != 0) {
35700 cp.maxReferences = server->config.maxReferencesPerNode;
35701 } else {
35702 cp.maxReferences = UA_INT32_MAX;
35703 }
35704 } else {
35705 if(server->config.maxReferencesPerNode != 0 &&
35706 cp.maxReferences > server->config.maxReferencesPerNode) {
35707 cp.maxReferences= server->config.maxReferencesPerNode;
35708 }
35709 }
35710
35711 /* Get the list of relevant reference types */
35712 result->statusCode =
35713 referenceTypeIndices(server, refType: &descr->referenceTypeId,
35714 indices: &cp.relevantReferences, includeSubtypes: descr->includeSubtypes);
35715 if(result->statusCode != UA_STATUSCODE_GOOD)
35716 return;
35717
35718 UA_Boolean done = browseWithContinuation(server, session, cp: &cp, result);
35719
35720 /* Exit early if done or an error occurred */
35721 if(done || result->statusCode != UA_STATUSCODE_GOOD)
35722 return;
35723
35724 /* Persist the new continuation point */
35725
35726 ContinuationPoint *cp2 = NULL;
35727 UA_Guid *ident = NULL;
35728 UA_StatusCode retval = UA_STATUSCODE_GOOD;
35729
35730 /* Enough space for the continuation point? */
35731 if(session->availableContinuationPoints == 0) {
35732 retval = UA_STATUSCODE_BADNOCONTINUATIONPOINTS;
35733 goto cleanup;
35734 }
35735
35736 /* Allocate and fill the data structure */
35737 cp2 = (ContinuationPoint*)UA_malloc(size: sizeof(ContinuationPoint));
35738 if(!cp2) {
35739 retval = UA_STATUSCODE_BADOUTOFMEMORY;
35740 goto cleanup;
35741 }
35742
35743 memset(s: cp2, c: 0, n: sizeof(ContinuationPoint));
35744 /* The BrowseDescription is only a shallow copy in cp */
35745 retval = UA_BrowseDescription_copy(src: descr, dst: &cp2->browseDescription);
35746 if(retval != UA_STATUSCODE_GOOD)
35747 goto cleanup;
35748 cp2->maxReferences = cp.maxReferences;
35749 cp2->relevantReferences = cp.relevantReferences;
35750 cp2->nextTarget = cp.nextTarget;
35751 cp2->nextRefKindIndex = cp.nextRefKindIndex;
35752
35753 /* Create a random bytestring via a Guid */
35754 ident = UA_Guid_new();
35755 if(!ident) {
35756 retval = UA_STATUSCODE_BADOUTOFMEMORY;
35757 goto cleanup;
35758 }
35759 *ident = UA_Guid_random();
35760 cp2->identifier.data = (UA_Byte*)ident;
35761 cp2->identifier.length = sizeof(UA_Guid);
35762
35763 /* Return the cp identifier */
35764 retval = UA_ByteString_copy(src: &cp2->identifier, dst: &result->continuationPoint);
35765 if(retval != UA_STATUSCODE_GOOD)
35766 goto cleanup;
35767
35768 /* Attach the cp to the session */
35769 cp2->next = session->continuationPoints;
35770 session->continuationPoints = cp2;
35771 --session->availableContinuationPoints;
35772 return;
35773
35774 cleanup:
35775 if(cp2) {
35776 ContinuationPoint_clear(cp: cp2);
35777 UA_free(ptr: cp2);
35778 }
35779 UA_BrowseResult_clear(p: result);
35780 result->statusCode = retval;
35781}
35782
35783void Service_Browse(UA_Server *server, UA_Session *session,
35784 const UA_BrowseRequest *request, UA_BrowseResponse *response) {
35785 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing BrowseRequest");
35786 UA_LOCK_ASSERT(&server->serviceMutex, 1);
35787
35788 /* Test the number of operations in the request */
35789 if(server->config.maxNodesPerBrowse != 0 &&
35790 request->nodesToBrowseSize > server->config.maxNodesPerBrowse) {
35791 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
35792 return;
35793 }
35794
35795 /* No views supported at the moment */
35796 if(!UA_NodeId_isNull(p: &request->view.viewId)) {
35797 response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN;
35798 return;
35799 }
35800
35801 response->responseHeader.serviceResult =
35802 UA_Server_processServiceOperations(server, session,
35803 operationCallback: (UA_ServiceOperation)Operation_Browse,
35804 context: &request->requestedMaxReferencesPerNode,
35805 requestOperations: &request->nodesToBrowseSize,
35806 requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION],
35807 responseOperations: &response->resultsSize,
35808 responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]);
35809}
35810
35811UA_BrowseResult
35812UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences,
35813 const UA_BrowseDescription *bd) {
35814 UA_BrowseResult result;
35815 UA_BrowseResult_init(p: &result);
35816 UA_LOCK(&server->serviceMutex);
35817 Operation_Browse(server, session: &server->adminSession, maxrefs: &maxReferences, descr: bd, result: &result);
35818 UA_UNLOCK(&server->serviceMutex);
35819 return result;
35820}
35821
35822static void
35823Operation_BrowseNext(UA_Server *server, UA_Session *session,
35824 const UA_Boolean *releaseContinuationPoints,
35825 const UA_ByteString *continuationPoint, UA_BrowseResult *result) {
35826 /* Find the continuation point */
35827 ContinuationPoint **prev = &session->continuationPoints;
35828 ContinuationPoint *cp;
35829 while((cp = *prev)) {
35830 if(UA_ByteString_equal(string1: &cp->identifier, string2: continuationPoint))
35831 break;
35832 prev = &cp->next;
35833 }
35834 if(!cp) {
35835 result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
35836 return;
35837 }
35838
35839 /* Remove the cp */
35840 if(*releaseContinuationPoints) {
35841 *prev = ContinuationPoint_clear(cp);
35842 UA_free(ptr: cp);
35843 ++session->availableContinuationPoints;
35844 return;
35845 }
35846
35847 /* Continue browsing */
35848 UA_Boolean done = browseWithContinuation(server, session, cp, result);
35849
35850 if(done) {
35851 /* Remove the cp if there are no references left */
35852 *prev = ContinuationPoint_clear(cp);
35853 UA_free(ptr: cp);
35854 ++session->availableContinuationPoints;
35855 } else {
35856 /* Return the cp identifier */
35857 UA_StatusCode retval =
35858 UA_ByteString_copy(src: &cp->identifier, dst: &result->continuationPoint);
35859 if(retval != UA_STATUSCODE_GOOD) {
35860 UA_BrowseResult_clear(p: result);
35861 result->statusCode = retval;
35862 }
35863 }
35864}
35865
35866void
35867Service_BrowseNext(UA_Server *server, UA_Session *session,
35868 const UA_BrowseNextRequest *request,
35869 UA_BrowseNextResponse *response) {
35870 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
35871 "Processing BrowseNextRequest");
35872 UA_LOCK_ASSERT(&server->serviceMutex, 1);
35873
35874 UA_Boolean releaseContinuationPoints =
35875 request->releaseContinuationPoints; /* request is const */
35876 response->responseHeader.serviceResult =
35877 UA_Server_processServiceOperations(server, session,
35878 operationCallback: (UA_ServiceOperation)Operation_BrowseNext,
35879 context: &releaseContinuationPoints,
35880 requestOperations: &request->continuationPointsSize,
35881 requestOperationsType: &UA_TYPES[UA_TYPES_BYTESTRING],
35882 responseOperations: &response->resultsSize,
35883 responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]);
35884}
35885
35886UA_BrowseResult
35887UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint,
35888 const UA_ByteString *continuationPoint) {
35889 UA_BrowseResult result;
35890 UA_BrowseResult_init(p: &result);
35891 UA_LOCK(&server->serviceMutex);
35892 Operation_BrowseNext(server, session: &server->adminSession, releaseContinuationPoints: &releaseContinuationPoint,
35893 continuationPoint, result: &result);
35894 UA_UNLOCK(&server->serviceMutex);
35895 return result;
35896}
35897
35898/***********************/
35899/* TranslateBrowsePath */
35900/***********************/
35901
35902/* Find all entries for that hash. There are duplicate for the possible hash
35903 * collisions. The exact browsename is checked afterwards. */
35904static UA_StatusCode
35905recursiveAddBrowseHashTarget(RefTree *results, struct aa_head *head,
35906 const UA_ReferenceTarget *rt) {
35907 UA_assert(rt);
35908 UA_StatusCode res = RefTree_add(rt: results, target: rt->targetId, NULL);
35909 UA_ReferenceTarget *prev = (UA_ReferenceTarget*)aa_prev(head, elem: rt);
35910 while(prev && prev->targetNameHash == rt->targetNameHash) {
35911 res |= RefTree_add(rt: results, target: prev->targetId, NULL);
35912 prev = (UA_ReferenceTarget*)aa_prev(head, elem: prev);
35913 }
35914 UA_ReferenceTarget *next= (UA_ReferenceTarget*)aa_next(head, elem: rt);
35915 while(next && next->targetNameHash == rt->targetNameHash) {
35916 res |= RefTree_add(rt: results, target: next->targetId, NULL);
35917 next = (UA_ReferenceTarget*)aa_next(head, elem: next);
35918 }
35919 return res;
35920}
35921
35922static UA_StatusCode
35923walkBrowsePathElement(UA_Server *server, UA_Session *session,
35924 const UA_RelativePath *path, const size_t pathIndex,
35925 UA_UInt32 nodeClassMask, const UA_QualifiedName *lastBrowseName,
35926 UA_BrowsePathResult *result, RefTree *current, RefTree *next) {
35927 /* For the next level. Note the difference from lastBrowseName */
35928 const UA_RelativePathElement *elem = &path->elements[pathIndex];
35929 UA_UInt32 browseNameHash = UA_QualifiedName_hash(q: &elem->targetName);
35930
35931 /* Get the relevant ReferenceTypes */
35932 UA_ReferenceTypeSet refTypes;
35933 UA_StatusCode res =
35934 referenceTypeIndices(server, refType: &elem->referenceTypeId,
35935 indices: &refTypes, includeSubtypes: elem->includeSubtypes);
35936 if(res != UA_STATUSCODE_GOOD)
35937 return UA_STATUSCODE_BADNOMATCH;
35938
35939 struct aa_head _refNameTree = refNameTree;
35940
35941 /* Loop over all Nodes in the current depth level */
35942 for(size_t i = 0; i < current->size; i++) {
35943 /* Remote Node. Immediately add to the results with the
35944 * RemainingPathIndex set. */
35945 if(!UA_ExpandedNodeId_isLocal(n: &current->targets[i])) {
35946 /* Increase the size of the results array */
35947 UA_BrowsePathTarget *tmpResults = (UA_BrowsePathTarget*)
35948 UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) *
35949 (result->targetsSize + 1));
35950 if(!tmpResults)
35951 return UA_STATUSCODE_BADOUTOFMEMORY;
35952 result->targets = tmpResults;
35953
35954 /* Copy over the result */
35955 res = UA_ExpandedNodeId_copy(src: &current->targets[i],
35956 dst: &result->targets[result->targetsSize].targetId);
35957 result->targets[result->targetsSize].remainingPathIndex = (UA_UInt32)pathIndex;
35958 result->targetsSize++;
35959 if(res != UA_STATUSCODE_GOOD)
35960 break;
35961 continue;
35962 }
35963
35964 /* Local Node. Add to the tree of results at the next depth. */
35965 const UA_Node *node = UA_NODESTORE_GET(server, &current->targets[i].nodeId);
35966 if(!node)
35967 continue;
35968
35969 /* Test whether the node fits the class mask */
35970 UA_Boolean skip = !matchClassMask(node, nodeClassMask);
35971
35972 /* Does the BrowseName match for the current node (not the references
35973 * going out here) */
35974 skip |= (lastBrowseName &&
35975 !UA_QualifiedName_equal(qn1: lastBrowseName, qn2: &node->head.browseName));
35976
35977 if(skip) {
35978 UA_NODESTORE_RELEASE(server, node);
35979 continue;
35980 }
35981
35982 /* Loop over the ReferenceKinds */
35983 for(size_t j = 0; j < node->head.referencesSize; j++) {
35984 UA_NodeReferenceKind *rk = &node->head.references[j];
35985
35986 /* Does the direction of the reference match? */
35987 if(rk->isInverse != elem->isInverse)
35988 continue;
35989
35990 /* Does the reference type match? */
35991 if(!UA_ReferenceTypeSet_contains(set: &refTypes, index: rk->referenceTypeIndex))
35992 continue;
35993
35994 if(rk->hasRefTree) {
35995 /* Retrieve by BrowseName hash. We might have several nodes where
35996 * the hash matches. The exact BrowseName will be verified in the
35997 * next iteration of the outer loop. So we only have to retrieve
35998 * every node just once. */
35999 _refNameTree.root = rk->targets.tree.nameTreeRoot;
36000 UA_ReferenceTarget *rt = (UA_ReferenceTarget*)
36001 aa_find(head: &_refNameTree, key: &browseNameHash);
36002 if(!rt)
36003 continue;
36004
36005 res = recursiveAddBrowseHashTarget(results: next, head: &_refNameTree, rt);
36006 if(res != UA_STATUSCODE_GOOD)
36007 break;
36008 } else {
36009 /* The array entries don't have a BrowseName hash. Add all of
36010 * them at this level to be checked with a full string
36011 * comparison. */
36012 for(size_t k = 0; k < rk->targetsSize; k++) {
36013 if(rk->targets.array[k].targetNameHash != browseNameHash)
36014 continue;
36015 res = RefTree_add(rt: next, target: rk->targets.array[k].targetId, NULL);
36016 if(res != UA_STATUSCODE_GOOD)
36017 break;
36018 }
36019 if(res != UA_STATUSCODE_GOOD)
36020 break;
36021 }
36022 }
36023
36024 UA_NODESTORE_RELEASE(server, node);
36025 }
36026 return res;
36027}
36028
36029static void
36030Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session,
36031 const UA_UInt32 *nodeClassMask,
36032 const UA_BrowsePath *path,
36033 UA_BrowsePathResult *result) {
36034 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36035
36036 if(path->relativePath.elementsSize == 0) {
36037 result->statusCode = UA_STATUSCODE_BADNOTHINGTODO;
36038 return;
36039 }
36040
36041 /* RelativePath elements must not have an empty targetName */
36042 for(size_t i = 0; i < path->relativePath.elementsSize; ++i) {
36043 if(UA_QualifiedName_isNull(q: &path->relativePath.elements[i].targetName)) {
36044 result->statusCode = UA_STATUSCODE_BADBROWSENAMEINVALID;
36045 return;
36046 }
36047 }
36048
36049 /* Check if the starting node exists */
36050 const UA_Node *startingNode = UA_NODESTORE_GET(server, &path->startingNode);
36051 if(!startingNode) {
36052 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36053 return;
36054 }
36055 UA_NODESTORE_RELEASE(server, startingNode);
36056
36057 /* Create two RefTrees that are alternated between path elements */
36058 RefTree rt1;
36059 RefTree rt2;
36060 RefTree *current = &rt1;
36061 RefTree *next = &rt2;
36062 RefTree *tmp;
36063 result->statusCode |= RefTree_init(rt: &rt1);
36064 result->statusCode |= RefTree_init(rt: &rt2);
36065 UA_BrowsePathTarget *tmpResults = NULL;
36066 UA_QualifiedName *browseNameFilter = NULL;
36067 if(result->statusCode != UA_STATUSCODE_GOOD)
36068 goto cleanup;
36069
36070 /* Copy the starting node into next */
36071 result->statusCode = RefTree_addNodeId(rt: next, target: &path->startingNode, NULL);
36072 if(result->statusCode != UA_STATUSCODE_GOOD)
36073 goto cleanup;
36074
36075 /* Walk the path elements. Retrieve the nodes only once from the NodeStore.
36076 * Hence the BrowseName is checked with one element "delay". */
36077 for(size_t i = 0; i < path->relativePath.elementsSize; i++) {
36078 /* Switch the trees */
36079 tmp = current;
36080 current = next;
36081 next = tmp;
36082
36083 /* Clear up current, keep the capacity */
36084 for(size_t j = 0; j < next->size; j++)
36085 UA_ExpandedNodeId_clear(p: &next->targets[j]);
36086 next->size = 0;
36087 ZIP_INIT(&next->head);
36088
36089 /* Do this check after next->size has been set to zero */
36090 if(current->size == 0)
36091 break;
36092
36093 /* Walk element for all NodeIds in the "current" tree.
36094 * Puts new results in the "next" tree. */
36095 result->statusCode =
36096 walkBrowsePathElement(server, session, path: &path->relativePath, pathIndex: i,
36097 nodeClassMask: *nodeClassMask, lastBrowseName: browseNameFilter, result, current, next);
36098 if(result->statusCode != UA_STATUSCODE_GOOD)
36099 goto cleanup;
36100
36101 browseNameFilter = &path->relativePath.elements[i].targetName;
36102 }
36103
36104 /* Allocate space for the results array */
36105 tmpResults = (UA_BrowsePathTarget*)
36106 UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) *
36107 (result->targetsSize + next->size));
36108 if(!tmpResults && next->size > 0) {
36109 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36110 goto cleanup;
36111 }
36112 result->targets = tmpResults;
36113
36114 for(size_t k = 0; k < next->size; k++) {
36115 /* Check the BrowseName. It has been filtered only via its hash so far. */
36116 const UA_Node *node = UA_NODESTORE_GET(server, &next->targets[k].nodeId);
36117 if(!node)
36118 continue;
36119 UA_Boolean match = UA_QualifiedName_equal(qn1: browseNameFilter, qn2: &node->head.browseName);
36120 UA_NODESTORE_RELEASE(server, node);
36121 if(!match)
36122 continue;
36123
36124 /* Move to the target to the results array */
36125 result->targets[result->targetsSize].targetId = next->targets[k];
36126 result->targets[result->targetsSize].remainingPathIndex = UA_UINT32_MAX;
36127 UA_ExpandedNodeId_init(p: &next->targets[k]);
36128 result->targetsSize++;
36129 }
36130
36131 /* No results => BadNoMatch status code */
36132 if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD)
36133 result->statusCode = UA_STATUSCODE_BADNOMATCH;
36134
36135 /* Clean up the temporary arrays and the targets */
36136 cleanup:
36137 RefTree_clear(rt: &rt1);
36138 RefTree_clear(rt: &rt2);
36139 if(result->statusCode != UA_STATUSCODE_GOOD) {
36140 for(size_t i = 0; i < result->targetsSize; ++i)
36141 UA_BrowsePathTarget_clear(p: &result->targets[i]);
36142 if(result->targets)
36143 UA_free(ptr: result->targets);
36144 result->targets = NULL;
36145 result->targetsSize = 0;
36146 }
36147}
36148
36149UA_BrowsePathResult
36150translateBrowsePathToNodeIds(UA_Server *server,
36151 const UA_BrowsePath *browsePath) {
36152 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36153 UA_BrowsePathResult result;
36154 UA_BrowsePathResult_init(p: &result);
36155 UA_UInt32 nodeClassMask = 0; /* All node classes */
36156 Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask,
36157 path: browsePath, result: &result);
36158 return result;
36159}
36160
36161UA_BrowsePathResult
36162UA_Server_translateBrowsePathToNodeIds(UA_Server *server,
36163 const UA_BrowsePath *browsePath) {
36164 UA_LOCK(&server->serviceMutex);
36165 UA_BrowsePathResult result = translateBrowsePathToNodeIds(server, browsePath);
36166 UA_UNLOCK(&server->serviceMutex);
36167 return result;
36168}
36169
36170void
36171Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session,
36172 const UA_TranslateBrowsePathsToNodeIdsRequest *request,
36173 UA_TranslateBrowsePathsToNodeIdsResponse *response) {
36174 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36175 "Processing TranslateBrowsePathsToNodeIdsRequest");
36176 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36177
36178 /* Test the number of operations in the request */
36179 if(server->config.maxNodesPerTranslateBrowsePathsToNodeIds != 0 &&
36180 request->browsePathsSize > server->config.maxNodesPerTranslateBrowsePathsToNodeIds) {
36181 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36182 return;
36183 }
36184
36185 UA_UInt32 nodeClassMask = 0; /* All node classes */
36186 response->responseHeader.serviceResult =
36187 UA_Server_processServiceOperations(server, session,
36188 operationCallback: (UA_ServiceOperation)Operation_TranslateBrowsePathToNodeIds,
36189 context: &nodeClassMask,
36190 requestOperations: &request->browsePathsSize, requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATH],
36191 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]);
36192}
36193
36194UA_BrowsePathResult
36195browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
36196 size_t browsePathSize, const UA_QualifiedName *browsePath) {
36197 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36198
36199 UA_BrowsePathResult bpr;
36200 UA_BrowsePathResult_init(p: &bpr);
36201 if(browsePathSize > UA_MAX_TREE_RECURSE) {
36202 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
36203 msg: "Simplified Browse Path too long");
36204 bpr.statusCode = UA_STATUSCODE_BADINTERNALERROR;
36205 return bpr;
36206 }
36207
36208 /* Construct the BrowsePath */
36209 UA_BrowsePath bp;
36210 UA_BrowsePath_init(p: &bp);
36211 bp.startingNode = origin;
36212
36213 UA_RelativePathElement rpe[UA_MAX_TREE_RECURSE];
36214 memset(s: rpe, c: 0, n: sizeof(UA_RelativePathElement) * browsePathSize);
36215 for(size_t j = 0; j < browsePathSize; j++) {
36216 rpe[j].referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
36217 rpe[j].includeSubtypes = true;
36218 rpe[j].targetName = browsePath[j];
36219 }
36220 bp.relativePath.elements = rpe;
36221 bp.relativePath.elementsSize = browsePathSize;
36222
36223 /* Browse */
36224 UA_UInt32 nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_OBJECTTYPE;
36225
36226 Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask, path: &bp, result: &bpr);
36227 return bpr;
36228}
36229
36230UA_BrowsePathResult
36231UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin,
36232 size_t browsePathSize, const UA_QualifiedName *browsePath) {
36233 UA_LOCK(&server->serviceMutex);
36234 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin, browsePathSize, browsePath);
36235 UA_UNLOCK(&server->serviceMutex);
36236 return bpr;
36237}
36238
36239/************/
36240/* Register */
36241/************/
36242
36243void Service_RegisterNodes(UA_Server *server, UA_Session *session,
36244 const UA_RegisterNodesRequest *request,
36245 UA_RegisterNodesResponse *response) {
36246 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36247 "Processing RegisterNodesRequest");
36248 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36249
36250 //TODO: hang the nodeids to the session if really needed
36251 if(request->nodesToRegisterSize == 0) {
36252 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
36253 return;
36254 }
36255
36256 /* Test the number of operations in the request */
36257 if(server->config.maxNodesPerRegisterNodes != 0 &&
36258 request->nodesToRegisterSize > server->config.maxNodesPerRegisterNodes) {
36259 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36260 return;
36261 }
36262
36263 response->responseHeader.serviceResult =
36264 UA_Array_copy(src: request->nodesToRegister, size: request->nodesToRegisterSize,
36265 dst: (void**)&response->registeredNodeIds, type: &UA_TYPES[UA_TYPES_NODEID]);
36266 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
36267 response->registeredNodeIdsSize = request->nodesToRegisterSize;
36268}
36269
36270void Service_UnregisterNodes(UA_Server *server, UA_Session *session,
36271 const UA_UnregisterNodesRequest *request,
36272 UA_UnregisterNodesResponse *response) {
36273 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
36274 "Processing UnRegisterNodesRequest");
36275 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36276
36277 //TODO: remove the nodeids from the session if really needed
36278 if(request->nodesToUnregisterSize == 0)
36279 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
36280
36281 /* Test the number of operations in the request */
36282 if(server->config.maxNodesPerRegisterNodes != 0 &&
36283 request->nodesToUnregisterSize > server->config.maxNodesPerRegisterNodes) {
36284 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36285 return;
36286 }
36287}
36288
36289/**** amalgamated original file "/src/server/ua_services_method.c" ****/
36290
36291/* This Source Code Form is subject to the terms of the Mozilla Public
36292 * License, v. 2.0. If a copy of the MPL was not distributed with this
36293 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
36294 *
36295 * Copyright 2015 (c) Chris Iatrou
36296 * Copyright 2015-2017 (c) Florian Palm
36297 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
36298 * Copyright 2015-2016 (c) Sten Grüner
36299 * Copyright 2015 (c) Oleksiy Vasylyev
36300 * Copyright 2016 (c) LEvertz
36301 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
36302 * Copyright 2017 (c) Julian Grothoff
36303 * Copyright 2020 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
36304 */
36305
36306
36307#ifdef UA_ENABLE_METHODCALLS /* conditional compilation */
36308
36309static const UA_VariableNode *
36310getArgumentsVariableNode(UA_Server *server, const UA_NodeHead *head,
36311 UA_String withBrowseName) {
36312 for(size_t i = 0; i < head->referencesSize; ++i) {
36313 const UA_NodeReferenceKind *rk = &head->references[i];
36314 if(rk->isInverse != false)
36315 continue;
36316 if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASPROPERTY)
36317 continue;
36318 const UA_ReferenceTarget *t = NULL;
36319 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36320 const UA_Node *refTarget =
36321 UA_NODESTORE_GETFROMREF(server, target: t->targetId);
36322 if(!refTarget)
36323 continue;
36324 if(refTarget->head.nodeClass == UA_NODECLASS_VARIABLE &&
36325 refTarget->head.browseName.namespaceIndex == 0 &&
36326 UA_String_equal(s1: &withBrowseName, s2: &refTarget->head.browseName.name)) {
36327 return &refTarget->variableNode;
36328 }
36329 UA_NODESTORE_RELEASE(server, refTarget);
36330 }
36331 }
36332 return NULL;
36333}
36334
36335/* inputArgumentResults has the length request->inputArgumentsSize */
36336static UA_StatusCode
36337typeCheckArguments(UA_Server *server, UA_Session *session,
36338 const UA_VariableNode *argRequirements, size_t argsSize,
36339 UA_Variant *args, UA_StatusCode *inputArgumentResults) {
36340 /* Verify that we have a Variant containing UA_Argument (scalar or array) in
36341 * the "InputArguments" node */
36342 if(argRequirements->valueSource != UA_VALUESOURCE_DATA)
36343 return UA_STATUSCODE_BADINTERNALERROR;
36344 if(!argRequirements->value.data.value.hasValue)
36345 return UA_STATUSCODE_BADINTERNALERROR;
36346 if(argRequirements->value.data.value.value.type != &UA_TYPES[UA_TYPES_ARGUMENT])
36347 return UA_STATUSCODE_BADINTERNALERROR;
36348
36349 /* Verify the number of arguments. A scalar argument value is interpreted as
36350 * an array of length 1. */
36351 size_t argReqsSize = argRequirements->value.data.value.value.arrayLength;
36352 if(UA_Variant_isScalar(v: &argRequirements->value.data.value.value))
36353 argReqsSize = 1;
36354 if(argReqsSize > argsSize)
36355 return UA_STATUSCODE_BADARGUMENTSMISSING;
36356 if(argReqsSize < argsSize)
36357 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
36358
36359 /* Type-check every argument against the definition */
36360 UA_StatusCode retval = UA_STATUSCODE_GOOD;
36361 UA_Argument *argReqs = (UA_Argument*)argRequirements->value.data.value.value.data;
36362 const char *reason;
36363 for(size_t i = 0; i < argReqsSize; ++i) {
36364 if(compatibleValue(server, session, targetDataTypeId: &argReqs[i].dataType, targetValueRank: argReqs[i].valueRank,
36365 targetArrayDimensionsSize: argReqs[i].arrayDimensionsSize, targetArrayDimensions: argReqs[i].arrayDimensions,
36366 value: &args[i], NULL, reason: &reason))
36367 continue;
36368
36369 /* Incompatible value. Try to correct the type if possible. */
36370 adjustValueType(server, value: &args[i], targetDataTypeId: &argReqs[i].dataType);
36371
36372 /* Recheck */
36373 if(!compatibleValue(server, session, targetDataTypeId: &argReqs[i].dataType, targetValueRank: argReqs[i].valueRank,
36374 targetArrayDimensionsSize: argReqs[i].arrayDimensionsSize, targetArrayDimensions: argReqs[i].arrayDimensions,
36375 value: &args[i], NULL, reason: &reason)) {
36376 inputArgumentResults[i] = UA_STATUSCODE_BADTYPEMISMATCH;
36377 retval = UA_STATUSCODE_BADINVALIDARGUMENT;
36378 }
36379 }
36380 return retval;
36381}
36382
36383/* inputArgumentResults has the length request->inputArgumentsSize */
36384static UA_StatusCode
36385validMethodArguments(UA_Server *server, UA_Session *session, const UA_MethodNode *method,
36386 const UA_CallMethodRequest *request,
36387 UA_StatusCode *inputArgumentResults) {
36388 /* Get the input arguments node */
36389 const UA_VariableNode *inputArguments =
36390 getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "InputArguments"));
36391 if(!inputArguments) {
36392 if(request->inputArgumentsSize > 0)
36393 return UA_STATUSCODE_BADTOOMANYARGUMENTS;
36394 return UA_STATUSCODE_GOOD;
36395 }
36396
36397 /* Verify the request */
36398 UA_StatusCode retval =
36399 typeCheckArguments(server, session, argRequirements: inputArguments, argsSize: request->inputArgumentsSize,
36400 args: request->inputArguments, inputArgumentResults);
36401
36402 /* Release the input arguments node */
36403 UA_NODESTORE_RELEASE(server, (const UA_Node*)inputArguments);
36404 return retval;
36405}
36406
36407static const UA_NodeId hasComponentNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}};
36408static const UA_NodeId organizedByNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}};
36409static const UA_String namespaceDiModel = UA_STRING_STATIC("http://opcfoundation.org/UA/DI/");
36410static const UA_NodeId hasTypeDefinitionNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}};
36411// ns=0 will be replace dynamically. DI-Spec. 1.01: <UAObjectType NodeId="ns=1;i=1005" BrowseName="1:FunctionalGroupType">
36412static UA_NodeId functionGroupNodeId = {0, UA_NODEIDTYPE_NUMERIC, {1005}};
36413
36414static void
36415callWithMethodAndObject(UA_Server *server, UA_Session *session,
36416 const UA_CallMethodRequest *request, UA_CallMethodResult *result,
36417 const UA_MethodNode *method, const UA_ObjectNode *object) {
36418 /* Verify the object's NodeClass */
36419 if(object->head.nodeClass != UA_NODECLASS_OBJECT &&
36420 object->head.nodeClass != UA_NODECLASS_OBJECTTYPE) {
36421 result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
36422 return;
36423 }
36424
36425 /* Verify the method's NodeClass */
36426 if(method->head.nodeClass != UA_NODECLASS_METHOD) {
36427 result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID;
36428 return;
36429 }
36430
36431 /* Is there a method to execute? */
36432 if(!method->method) {
36433 result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
36434 return;
36435 }
36436
36437 UA_NodePointer methodP = UA_NodePointer_fromNodeId(id: &request->methodId);
36438
36439 /* Verify method/object relations. Object must have a hasComponent or a
36440 * subtype of hasComponent reference to the method node. Therefore, check
36441 * every reference between the parent object and the method node if there is
36442 * a hasComponent (or subtype) reference */
36443 UA_ReferenceTypeSet hasComponentRefs;
36444 result->statusCode =
36445 referenceTypeIndices(server, refType: &hasComponentNodeId, indices: &hasComponentRefs, true);
36446 if(result->statusCode != UA_STATUSCODE_GOOD)
36447 return;
36448
36449 UA_Boolean found = false;
36450 for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
36451 const UA_NodeReferenceKind *rk = &object->head.references[i];
36452 if(rk->isInverse)
36453 continue;
36454 if(!UA_ReferenceTypeSet_contains(set: &hasComponentRefs, index: rk->referenceTypeIndex))
36455 continue;
36456 const UA_ReferenceTarget *t = NULL;
36457 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36458 if(UA_NodePointer_equal(p1: t->targetId, p2: methodP)) {
36459 found = true;
36460 break;
36461 }
36462 }
36463 }
36464
36465 if(!found) {
36466 /* The following ParentObject evaluation is a workaround only to fulfill
36467 * the OPC UA Spec. Part 100 - Devices requirements regarding functional
36468 * groups. Compare OPC UA Spec. Part 100 - Devices, Release 1.02
36469 * - 5.4 FunctionalGroupType
36470 * - B.1 Functional Group Usages
36471 * A functional group is a sub-type of the FolderType and is used to
36472 * organize the Parameters and Methods from the complete set (named
36473 * ParameterSet and MethodSet) in (Functional) groups for instance
36474 * Configuration or Identification. The same Property, Parameter or
36475 * Method can be referenced from more than one FunctionalGroup. */
36476
36477 /* Check whether the DI namespace is available */
36478 size_t foundNamespace = 0;
36479 UA_StatusCode res = getNamespaceByName(server, namespaceUri: namespaceDiModel, foundIndex: &foundNamespace);
36480 if(res != UA_STATUSCODE_GOOD) {
36481 result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
36482 return;
36483 }
36484 functionGroupNodeId.namespaceIndex = (UA_UInt16)foundNamespace;
36485
36486 UA_ReferenceTypeSet hasTypeDefinitionRefs;
36487 result->statusCode =
36488 referenceTypeIndices(server, refType: &hasTypeDefinitionNodeId,
36489 indices: &hasTypeDefinitionRefs, true);
36490 if(result->statusCode != UA_STATUSCODE_GOOD)
36491 return;
36492
36493 /* Search for a HasTypeDefinition (or sub-) reference in the parent object */
36494 for(size_t i = 0; i < object->head.referencesSize && !found; ++i) {
36495 const UA_NodeReferenceKind *rk = &object->head.references[i];
36496 if(rk->isInverse)
36497 continue;
36498 if(!UA_ReferenceTypeSet_contains(set: &hasTypeDefinitionRefs, index: rk->referenceTypeIndex))
36499 continue;
36500
36501 /* Verify that the HasTypeDefinition is equal to FunctionGroupType
36502 * (or sub-type) from the DI model */
36503 const UA_ReferenceTarget *t = NULL;
36504 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
36505 if(!UA_NodePointer_isLocal(np: t->targetId))
36506 continue;
36507
36508 UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId);
36509 if(!isNodeInTree_singleRef(server, leafNode: &tmpId, nodeToFind: &functionGroupNodeId,
36510 UA_REFERENCETYPEINDEX_HASSUBTYPE))
36511 continue;
36512
36513 /* Search for the called method with reference Organize (or
36514 * sub-type) from the parent object */
36515 for(size_t k = 0; k < object->head.referencesSize && !found; ++k) {
36516 const UA_NodeReferenceKind *rkInner = &object->head.references[k];
36517 if(rkInner->isInverse)
36518 continue;
36519 const UA_NodeId * refId =
36520 UA_NODESTORE_GETREFERENCETYPEID(server, rkInner->referenceTypeIndex);
36521 if(!isNodeInTree_singleRef(server, leafNode: refId, nodeToFind: &organizedByNodeId,
36522 UA_REFERENCETYPEINDEX_HASSUBTYPE))
36523 continue;
36524
36525 const UA_ReferenceTarget *t2 = NULL;
36526 while((t2 = UA_NodeReferenceKind_iterate(rk: rkInner, prev: t2))) {
36527 if(UA_NodePointer_equal(p1: t2->targetId, p2: methodP)) {
36528 found = true;
36529 break;
36530 }
36531 }
36532 }
36533 }
36534 }
36535 if(!found) {
36536 result->statusCode = UA_STATUSCODE_BADMETHODINVALID;
36537 return;
36538 }
36539 }
36540
36541 /* Verify access rights */
36542 UA_Boolean executable = method->executable;
36543 if(session != &server->adminSession) {
36544 UA_UNLOCK(&server->serviceMutex);
36545 executable = executable && server->config.accessControl.
36546 getUserExecutableOnObject(server, &server->config.accessControl, &session->sessionId,
36547 session->sessionHandle, &request->methodId, method->head.context,
36548 &request->objectId, object->head.context);
36549 UA_LOCK(&server->serviceMutex);
36550 }
36551
36552 if(!executable) {
36553 result->statusCode = UA_STATUSCODE_BADNOTEXECUTABLE;
36554 return;
36555 }
36556
36557 /* Allocate the inputArgumentResults array */
36558 result->inputArgumentResults = (UA_StatusCode*)
36559 UA_Array_new(size: request->inputArgumentsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
36560 if(!result->inputArgumentResults) {
36561 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36562 return;
36563 }
36564 result->inputArgumentResultsSize = request->inputArgumentsSize;
36565
36566 /* Verify Input Arguments */
36567 result->statusCode = validMethodArguments(server, session, method, request,
36568 inputArgumentResults: result->inputArgumentResults);
36569
36570 /* Return inputArgumentResults only for BADINVALIDARGUMENT */
36571 if(result->statusCode != UA_STATUSCODE_BADINVALIDARGUMENT) {
36572 UA_Array_delete(p: result->inputArgumentResults, size: result->inputArgumentResultsSize,
36573 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
36574 result->inputArgumentResults = NULL;
36575 result->inputArgumentResultsSize = 0;
36576 }
36577
36578 /* Error during type-checking? */
36579 if(result->statusCode != UA_STATUSCODE_GOOD)
36580 return;
36581
36582 /* Get the output arguments node */
36583 const UA_VariableNode *outputArguments =
36584 getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "OutputArguments"));
36585
36586 /* Allocate the output arguments array */
36587 size_t outputArgsSize = 0;
36588 if(outputArguments)
36589 outputArgsSize = outputArguments->value.data.value.value.arrayLength;
36590 result->outputArguments = (UA_Variant*)
36591 UA_Array_new(size: outputArgsSize, type: &UA_TYPES[UA_TYPES_VARIANT]);
36592 if(!result->outputArguments) {
36593 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
36594 return;
36595 }
36596 result->outputArgumentsSize = outputArgsSize;
36597
36598 /* Release the output arguments node */
36599 UA_NODESTORE_RELEASE(server, (const UA_Node*)outputArguments);
36600
36601 /* Call the method */
36602 UA_UNLOCK(&server->serviceMutex);
36603 result->statusCode = method->method(server, &session->sessionId, session->sessionHandle,
36604 &method->head.nodeId, method->head.context,
36605 &object->head.nodeId, object->head.context,
36606 request->inputArgumentsSize, request->inputArguments,
36607 result->outputArgumentsSize, result->outputArguments);
36608 UA_LOCK(&server->serviceMutex);
36609 /* TODO: Verify Output matches the argument definition */
36610}
36611
36612#if UA_MULTITHREADING >= 100
36613
36614static void
36615Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
36616 UA_UInt32 requestHandle, size_t opIndex,
36617 UA_CallMethodRequest *opRequest, UA_CallMethodResult *opResult,
36618 UA_AsyncResponse **ar) {
36619 /* Get the method node */
36620 const UA_Node *method = UA_NODESTORE_GET(server, &opRequest->methodId);
36621 if(!method) {
36622 opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36623 return;
36624 }
36625
36626 /* Get the object node */
36627 const UA_Node *object = UA_NODESTORE_GET(server, &opRequest->objectId);
36628 if(!object) {
36629 opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36630 UA_NODESTORE_RELEASE(server, method);
36631 return;
36632 }
36633
36634 /* Synchronous execution */
36635 if(!method->methodNode.async) {
36636 callWithMethodAndObject(server, session, opRequest, opResult,
36637 &method->methodNode, &object->objectNode);
36638 goto cleanup;
36639 }
36640
36641 /* <-- Async method call --> */
36642
36643 /* No AsyncResponse allocated so far */
36644 if(!*ar) {
36645 opResult->statusCode =
36646 UA_AsyncManager_createAsyncResponse(&server->asyncManager, server,
36647 &session->sessionId, requestId, requestHandle,
36648 UA_ASYNCOPERATIONTYPE_CALL, ar);
36649 if(opResult->statusCode != UA_STATUSCODE_GOOD)
36650 goto cleanup;
36651 }
36652
36653 /* Create the Async Request to be taken by workers */
36654 opResult->statusCode =
36655 UA_AsyncManager_createAsyncOp(&server->asyncManager,
36656 server, *ar, opIndex, opRequest);
36657
36658 cleanup:
36659 /* Release the method and object node */
36660 UA_NODESTORE_RELEASE(server, method);
36661 UA_NODESTORE_RELEASE(server, object);
36662}
36663
36664void
36665Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId,
36666 const UA_CallRequest *request, UA_CallResponse *response,
36667 UA_Boolean *finished) {
36668 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CallRequestAsync");
36669 if(server->config.maxNodesPerMethodCall != 0 &&
36670 request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
36671 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36672 return;
36673 }
36674
36675 UA_AsyncResponse *ar = NULL;
36676 response->responseHeader.serviceResult =
36677 UA_Server_processServiceOperationsAsync(server, session, requestId,
36678 request->requestHeader.requestHandle,
36679 (UA_AsyncServiceOperation)Operation_CallMethodAsync,
36680 &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
36681 &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], &ar);
36682
36683 if(ar) {
36684 if(ar->opCountdown > 0) {
36685 /* Move all results to the AsyncResponse. The async operation
36686 * results will be overwritten when the workers return results. */
36687 ar->response.callResponse = *response;
36688 UA_CallResponse_init(response);
36689 *finished = false;
36690 } else {
36691 /* If there is a new AsyncResponse, ensure it has at least one
36692 * pending operation */
36693 UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar);
36694 }
36695 }
36696}
36697#endif
36698
36699static void
36700Operation_CallMethod(UA_Server *server, UA_Session *session, void *context,
36701 const UA_CallMethodRequest *request, UA_CallMethodResult *result) {
36702 /* Get the method node */
36703 const UA_Node *method = UA_NODESTORE_GET(server, &request->methodId);
36704 if(!method) {
36705 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36706 return;
36707 }
36708
36709 /* Get the object node */
36710 const UA_Node *object = UA_NODESTORE_GET(server, &request->objectId);
36711 if(!object) {
36712 result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN;
36713 UA_NODESTORE_RELEASE(server, method);
36714 return;
36715 }
36716
36717 /* Continue with method and object as context */
36718 callWithMethodAndObject(server, session, request, result,
36719 method: &method->methodNode, object: &object->objectNode);
36720
36721 /* Release the method and object node */
36722 UA_NODESTORE_RELEASE(server, method);
36723 UA_NODESTORE_RELEASE(server, object);
36724}
36725
36726void Service_Call(UA_Server *server, UA_Session *session,
36727 const UA_CallRequest *request, UA_CallResponse *response) {
36728 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing CallRequest");
36729 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36730
36731 if(server->config.maxNodesPerMethodCall != 0 &&
36732 request->methodsToCallSize > server->config.maxNodesPerMethodCall) {
36733 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
36734 return;
36735 }
36736
36737 response->responseHeader.serviceResult =
36738 UA_Server_processServiceOperations(server, session,
36739 operationCallback: (UA_ServiceOperation)Operation_CallMethod, NULL,
36740 requestOperations: &request->methodsToCallSize, requestOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODREQUEST],
36741 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
36742}
36743
36744UA_CallMethodResult
36745UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
36746 UA_CallMethodResult result;
36747 UA_CallMethodResult_init(p: &result);
36748 UA_LOCK(&server->serviceMutex);
36749 Operation_CallMethod(server, session: &server->adminSession, NULL, request, result: &result);
36750 UA_UNLOCK(&server->serviceMutex);
36751 return result;
36752}
36753
36754#endif /* UA_ENABLE_METHODCALLS */
36755
36756/**** amalgamated original file "/src/server/ua_services_session.c" ****/
36757
36758/* This Source Code Form is subject to the terms of the Mozilla Public
36759 * License, v. 2.0. If a copy of the MPL was not distributed with this
36760 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
36761 *
36762 * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
36763 * Copyright 2014-2017 (c) Florian Palm
36764 * Copyright 2014-2016 (c) Sten Grüner
36765 * Copyright 2015 (c) Chris Iatrou
36766 * Copyright 2015 (c) Oleksiy Vasylyev
36767 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
36768 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
36769 * Copyright 2019 (c) Kalycito Infotech Private Limited
36770 * Copyright 2018-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
36771 */
36772
36773
36774/* Delayed callback to free the session memory */
36775static void
36776removeSessionCallback(UA_Server *server, session_list_entry *entry) {
36777 UA_LOCK(&server->serviceMutex);
36778 UA_Session_clear(session: &entry->session, server);
36779 UA_UNLOCK(&server->serviceMutex);
36780}
36781
36782void
36783UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
36784 UA_DiagnosticEvent event) {
36785 UA_Session *session = &sentry->session;
36786
36787 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36788
36789 /* Remove the Subscriptions */
36790#ifdef UA_ENABLE_SUBSCRIPTIONS
36791 UA_Subscription *sub, *tempsub;
36792 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
36793 UA_Subscription_delete(server, sub);
36794 }
36795
36796 UA_PublishResponseEntry *entry;
36797 while((entry = UA_Session_dequeuePublishReq(session))) {
36798 UA_PublishResponse_clear(p: &entry->response);
36799 UA_free(ptr: entry);
36800 }
36801#endif
36802
36803 /* Callback into userland access control */
36804 if(server->config.accessControl.closeSession) {
36805 UA_UNLOCK(&server->serviceMutex);
36806 server->config.accessControl.closeSession(server, &server->config.accessControl,
36807 &session->sessionId, session->sessionHandle);
36808 UA_LOCK(&server->serviceMutex);
36809 }
36810
36811 /* Detach the Session from the SecureChannel */
36812 UA_Session_detachFromSecureChannel(session);
36813
36814 /* Deactivate the session */
36815 if(sentry->session.activated) {
36816 sentry->session.activated = false;
36817 server->activeSessionCount--;
36818 }
36819
36820 /* Detach the session from the session manager and make the capacity
36821 * available */
36822 LIST_REMOVE(sentry, pointers);
36823 server->sessionCount--;
36824
36825 switch(event) {
36826 case UA_DIAGNOSTICEVENT_CLOSE:
36827 case UA_DIAGNOSTICEVENT_PURGE:
36828 break;
36829 case UA_DIAGNOSTICEVENT_TIMEOUT:
36830 server->serverDiagnosticsSummary.sessionTimeoutCount++;
36831 break;
36832 case UA_DIAGNOSTICEVENT_REJECT:
36833 server->serverDiagnosticsSummary.rejectedSessionCount++;
36834 break;
36835 case UA_DIAGNOSTICEVENT_SECURITYREJECT:
36836 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
36837 break;
36838 case UA_DIAGNOSTICEVENT_ABORT:
36839 server->serverDiagnosticsSummary.sessionAbortCount++;
36840 break;
36841 default:
36842 UA_assert(false);
36843 break;
36844 }
36845
36846 /* Add a delayed callback to remove the session when the currently
36847 * scheduled jobs have completed */
36848 sentry->cleanupCallback.callback = (UA_ApplicationCallback)removeSessionCallback;
36849 sentry->cleanupCallback.application = server;
36850 sentry->cleanupCallback.data = sentry;
36851 sentry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
36852 sentry->cleanupCallback.interval = 0; /* Remove the structure */
36853 UA_Timer_addTimerEntry(t: &server->timer, te: &sentry->cleanupCallback, NULL);
36854}
36855
36856UA_StatusCode
36857UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token,
36858 UA_DiagnosticEvent event) {
36859 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36860 session_list_entry *entry;
36861 LIST_FOREACH(entry, &server->sessions, pointers) {
36862 if(UA_NodeId_equal(n1: &entry->session.header.authenticationToken, n2: token)) {
36863 UA_Server_removeSession(server, sentry: entry, event);
36864 return UA_STATUSCODE_GOOD;
36865 }
36866 }
36867 return UA_STATUSCODE_BADSESSIONIDINVALID;
36868}
36869
36870void
36871UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) {
36872 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36873 session_list_entry *sentry, *temp;
36874 LIST_FOREACH_SAFE(sentry, &server->sessions, pointers, temp) {
36875 /* Session has timed out? */
36876 if(sentry->session.validTill >= nowMonotonic)
36877 continue;
36878 UA_LOG_INFO_SESSION(&server->config.logger, &sentry->session, "Session has timed out");
36879 UA_Server_removeSession(server, sentry, event: UA_DIAGNOSTICEVENT_TIMEOUT);
36880 }
36881}
36882
36883/************/
36884/* Services */
36885/************/
36886
36887UA_Session *
36888getSessionByToken(UA_Server *server, const UA_NodeId *token) {
36889 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36890
36891 session_list_entry *current = NULL;
36892 LIST_FOREACH(current, &server->sessions, pointers) {
36893 /* Token does not match */
36894 if(!UA_NodeId_equal(n1: &current->session.header.authenticationToken, n2: token))
36895 continue;
36896
36897 /* Session has timed out */
36898 if(UA_DateTime_nowMonotonic() > current->session.validTill) {
36899 UA_LOG_INFO_SESSION(&server->config.logger, &current->session,
36900 "Client tries to use a session that has timed out");
36901 return NULL;
36902 }
36903
36904 return &current->session;
36905 }
36906
36907 return NULL;
36908}
36909
36910UA_Session *
36911UA_Server_getSessionById(UA_Server *server, const UA_NodeId *sessionId) {
36912 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36913
36914 session_list_entry *current = NULL;
36915 LIST_FOREACH(current, &server->sessions, pointers) {
36916 /* Token does not match */
36917 if(!UA_NodeId_equal(n1: &current->session.sessionId, n2: sessionId))
36918 continue;
36919
36920 /* Session has timed out */
36921 if(UA_DateTime_nowMonotonic() > current->session.validTill) {
36922 UA_LOG_INFO_SESSION(&server->config.logger, &current->session,
36923 "Client tries to use a session that has timed out");
36924 return NULL;
36925 }
36926
36927 return &current->session;
36928 }
36929
36930 return NULL;
36931}
36932
36933static UA_StatusCode
36934signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
36935 const UA_CreateSessionRequest *request,
36936 UA_CreateSessionResponse *response) {
36937 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
36938 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
36939 return UA_STATUSCODE_GOOD;
36940
36941 const UA_SecurityPolicy *securityPolicy = channel->securityPolicy;
36942 UA_SignatureData *signatureData = &response->serverSignature;
36943
36944 /* Prepare the signature */
36945 size_t signatureSize = securityPolicy->certificateSigningAlgorithm.
36946 getLocalSignatureSize(channel->channelContext);
36947 UA_StatusCode retval = UA_String_copy(src: &securityPolicy->certificateSigningAlgorithm.uri,
36948 dst: &signatureData->algorithm);
36949 retval |= UA_ByteString_allocBuffer(bs: &signatureData->signature, length: signatureSize);
36950 if(retval != UA_STATUSCODE_GOOD)
36951 return retval;
36952
36953 /* Allocate a temp buffer */
36954 size_t dataToSignSize = request->clientCertificate.length + request->clientNonce.length;
36955 UA_ByteString dataToSign;
36956 retval = UA_ByteString_allocBuffer(bs: &dataToSign, length: dataToSignSize);
36957 if(retval != UA_STATUSCODE_GOOD)
36958 return retval; /* signatureData->signature is cleaned up with the response */
36959
36960 /* Sign the signature */
36961 memcpy(dest: dataToSign.data, src: request->clientCertificate.data, n: request->clientCertificate.length);
36962 memcpy(dest: dataToSign.data + request->clientCertificate.length,
36963 src: request->clientNonce.data, n: request->clientNonce.length);
36964 retval = securityPolicy->certificateSigningAlgorithm.
36965 sign(channel->channelContext, &dataToSign, &signatureData->signature);
36966
36967 /* Clean up */
36968 UA_ByteString_clear(p: &dataToSign);
36969 return retval;
36970}
36971
36972/* Creates and adds a session. But it is not yet attached to a secure channel. */
36973UA_StatusCode
36974UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
36975 const UA_CreateSessionRequest *request, UA_Session **session) {
36976 UA_LOCK_ASSERT(&server->serviceMutex, 1);
36977
36978 if(server->sessionCount >= server->config.maxSessions) {
36979 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
36980 "Could not create a Session - Server limits reached");
36981 return UA_STATUSCODE_BADTOOMANYSESSIONS;
36982 }
36983
36984 session_list_entry *newentry = (session_list_entry*)
36985 UA_malloc(size: sizeof(session_list_entry));
36986 if(!newentry)
36987 return UA_STATUSCODE_BADOUTOFMEMORY;
36988
36989 /* Initialize the Session */
36990 UA_Session_init(session: &newentry->session);
36991 newentry->session.sessionId = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random());
36992 newentry->session.header.authenticationToken = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random());
36993
36994 newentry->session.timeout = server->config.maxSessionTimeout;
36995 if(request->requestedSessionTimeout <= server->config.maxSessionTimeout &&
36996 request->requestedSessionTimeout > 0)
36997 newentry->session.timeout = request->requestedSessionTimeout;
36998
36999 /* Attach the session to the channel. But don't activate for now. */
37000 if(channel)
37001 UA_Session_attachToSecureChannel(session: &newentry->session, channel);
37002 UA_Session_updateLifetime(session: &newentry->session);
37003
37004 /* Add to the server */
37005 LIST_INSERT_HEAD(&server->sessions, newentry, pointers);
37006 server->sessionCount++;
37007
37008 *session = &newentry->session;
37009 return UA_STATUSCODE_GOOD;
37010}
37011
37012void
37013Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
37014 const UA_CreateSessionRequest *request,
37015 UA_CreateSessionResponse *response) {
37016 UA_LOCK_ASSERT(&server->serviceMutex, 1);
37017 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel, "Trying to create session");
37018
37019 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
37020 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
37021 /* Compare the clientCertificate with the remoteCertificate of the channel.
37022 * Both the clientCertificate of this request and the remoteCertificate
37023 * of the channel may contain a partial or a complete certificate chain.
37024 * The compareCertificate function of the channelModule will compare the
37025 * first certificate of each chain. The end certificate shall be located
37026 * first in the chain according to the OPC UA specification Part 6 (1.04),
37027 * chapter 6.2.3.*/
37028 UA_StatusCode retval = channel->securityPolicy->channelModule.
37029 compareCertificate(channel->channelContext, &request->clientCertificate);
37030 if(retval != UA_STATUSCODE_GOOD) {
37031 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37032 "The client certificate did not validate");
37033 response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID;
37034 return;
37035 }
37036 }
37037
37038 UA_assert(channel->securityToken.channelId != 0);
37039
37040 if(!UA_ByteString_equal(string1: &channel->securityPolicy->policyUri,
37041 string2: &UA_SECURITY_POLICY_NONE_URI) &&
37042 request->clientNonce.length < 32) {
37043 response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID;
37044 return;
37045 }
37046
37047 if(request->clientCertificate.length > 0) {
37048 UA_CertificateVerification *cv = &server->config.certificateVerification;
37049 response->responseHeader.serviceResult =
37050 cv->verifyApplicationURI(cv->context, &request->clientCertificate,
37051 &request->clientDescription.applicationUri);
37052 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37053 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37054 "The client's ApplicationURI did not match the certificate");
37055 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
37056 server->serverDiagnosticsSummary.rejectedSessionCount++;
37057 return;
37058 }
37059 }
37060
37061 UA_Session *newSession = NULL;
37062 response->responseHeader.serviceResult =
37063 UA_Server_createSession(server, channel, request, session: &newSession);
37064 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37065 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37066 "Processing CreateSessionRequest failed");
37067 server->serverDiagnosticsSummary.rejectedSessionCount++;
37068 return;
37069 }
37070
37071 UA_assert(newSession != NULL);
37072
37073 /* Allocate the response */
37074 response->serverEndpoints = (UA_EndpointDescription *)
37075 UA_Array_new(size: server->config.endpointsSize, type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
37076 if(!response->serverEndpoints) {
37077 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
37078 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37079 event: UA_DIAGNOSTICEVENT_REJECT);
37080 return;
37081 }
37082 response->serverEndpointsSize = server->config.endpointsSize;
37083
37084 /* Copy the server's endpointdescriptions into the response */
37085 for(size_t i = 0; i < server->config.endpointsSize; ++i)
37086 response->responseHeader.serviceResult |=
37087 UA_EndpointDescription_copy(src: &server->config.endpoints[i],
37088 dst: &response->serverEndpoints[i]);
37089 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37090 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37091 event: UA_DIAGNOSTICEVENT_REJECT);
37092 return;
37093 }
37094
37095 /* Mirror back the endpointUrl */
37096 for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
37097 UA_String_clear(p: &response->serverEndpoints[i].endpointUrl);
37098 response->responseHeader.serviceResult |=
37099 UA_String_copy(src: &request->endpointUrl,
37100 dst: &response->serverEndpoints[i].endpointUrl);
37101 }
37102
37103 /* Fill the session information */
37104 newSession->maxResponseMessageSize = request->maxResponseMessageSize;
37105 newSession->maxRequestMessageSize = channel->config.localMaxMessageSize;
37106 response->responseHeader.serviceResult |=
37107 UA_ApplicationDescription_copy(src: &request->clientDescription,
37108 dst: &newSession->clientDescription);
37109
37110 /* Prepare the response */
37111 response->sessionId = newSession->sessionId;
37112 response->revisedSessionTimeout = (UA_Double)newSession->timeout;
37113 response->authenticationToken = newSession->header.authenticationToken;
37114 response->responseHeader.serviceResult |=
37115 UA_String_copy(src: &request->sessionName, dst: &newSession->sessionName);
37116
37117#ifdef UA_ENABLE_DIAGNOSTICS
37118 response->responseHeader.serviceResult |=
37119 UA_String_copy(&request->serverUri, &newSession->diagnostics.serverUri);
37120 response->responseHeader.serviceResult |=
37121 UA_String_copy(&request->endpointUrl, &newSession->diagnostics.endpointUrl);
37122#endif
37123
37124 UA_ByteString_init(p: &response->serverCertificate);
37125
37126 if(server->config.endpointsSize > 0)
37127 for(size_t i = 0; i < response->serverEndpointsSize; ++i) {
37128 if(response->serverEndpoints[i].securityMode==channel->securityMode &&
37129 UA_ByteString_equal(string1: &response->serverEndpoints[i].securityPolicyUri,
37130 string2: &channel->securityPolicy->policyUri) &&
37131 UA_String_equal(s1: &response->serverEndpoints[i].endpointUrl,
37132 s2: &request->endpointUrl))
37133 {
37134 response->responseHeader.serviceResult |=
37135 UA_ByteString_copy(src: &response->serverEndpoints[i].serverCertificate,
37136 dst: &response->serverCertificate);
37137 }
37138 }
37139
37140 /* Create a session nonce */
37141 response->responseHeader.serviceResult |= UA_Session_generateNonce(session: newSession);
37142 response->responseHeader.serviceResult |=
37143 UA_ByteString_copy(src: &newSession->serverNonce, dst: &response->serverNonce);
37144
37145 /* Sign the signature */
37146 response->responseHeader.serviceResult |=
37147 signCreateSessionResponse(server, channel, request, response);
37148
37149 /* Failure -> remove the session */
37150 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37151 UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken,
37152 event: UA_DIAGNOSTICEVENT_REJECT);
37153 return;
37154 }
37155
37156#ifdef UA_ENABLE_DIAGNOSTICS
37157 newSession->diagnostics.clientConnectionTime = UA_DateTime_now();
37158 newSession->diagnostics.clientLastContactTime =
37159 newSession->diagnostics.clientConnectionTime;
37160
37161 /* Create the object in the information model */
37162 createSessionObject(server, newSession);
37163#endif
37164
37165 UA_LOG_INFO_SESSION(&server->config.logger, newSession, "Session created");
37166}
37167
37168static UA_StatusCode
37169checkSignature(const UA_Server *server, const UA_SecurityPolicy *securityPolicy,
37170 void *channelContext, const UA_ByteString *serverNonce,
37171 const UA_SignatureData *signature) {
37172 /* Check for zero signature length */
37173 if(signature->signature.length == 0)
37174 return UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
37175
37176 if(!securityPolicy)
37177 return UA_STATUSCODE_BADINTERNALERROR;
37178
37179 const UA_ByteString *localCertificate = &securityPolicy->localCertificate;
37180 /* Data to verify is calculated by appending the serverNonce to the local certificate */
37181 UA_ByteString dataToVerify;
37182 size_t dataToVerifySize = localCertificate->length + serverNonce->length;
37183 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize);
37184 if(retval != UA_STATUSCODE_GOOD)
37185 return retval;
37186
37187 memcpy(dest: dataToVerify.data, src: localCertificate->data, n: localCertificate->length);
37188 memcpy(dest: dataToVerify.data + localCertificate->length,
37189 src: serverNonce->data, n: serverNonce->length);
37190 retval = securityPolicy->certificateSigningAlgorithm.
37191 verify(channelContext, &dataToVerify, &signature->signature);
37192 UA_ByteString_clear(p: &dataToVerify);
37193 return retval;
37194}
37195
37196#ifdef UA_ENABLE_ENCRYPTION
37197
37198static UA_StatusCode
37199decryptPassword(UA_SecurityPolicy *securityPolicy, void *tempChannelContext,
37200 const UA_ByteString *serverNonce, UA_UserNameIdentityToken *userToken) {
37201 UA_SecurityPolicyEncryptionAlgorithm *asymEnc =
37202 &securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm;
37203 if(!UA_String_equal(s1: &userToken->encryptionAlgorithm, s2: &asymEnc->uri))
37204 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37205
37206 UA_UInt32 tokenSecretLength;
37207 UA_ByteString decryptedTokenSecret, tokenServerNonce;
37208 size_t tokenpos = 0;
37209 size_t offset = 0;
37210 if(UA_ByteString_copy(src: &userToken->password, dst: &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
37211 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37212
37213 UA_StatusCode retval = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37214 if(asymEnc->decrypt(tempChannelContext, &decryptedTokenSecret) != UA_STATUSCODE_GOOD)
37215 goto cleanup;
37216
37217 UA_UInt32_decodeBinary(src: &decryptedTokenSecret, offset: &offset, dst: &tokenSecretLength);
37218
37219 /* The decrypted data must be large enough to include the Encrypted Token
37220 * Secret Format and the length field must indicate enough data to include
37221 * the server nonce. */
37222 if(decryptedTokenSecret.length < sizeof(UA_UInt32) + serverNonce->length ||
37223 decryptedTokenSecret.length < sizeof(UA_UInt32) + tokenSecretLength ||
37224 tokenSecretLength < serverNonce->length)
37225 goto cleanup;
37226
37227 /* If the Encrypted Token Secret contains padding, the padding must be
37228 * zeroes according to the 1.04.1 specification errata, chapter 3. */
37229 for(size_t i = sizeof(UA_UInt32) + tokenSecretLength; i < decryptedTokenSecret.length; i++) {
37230 if(decryptedTokenSecret.data[i] != 0)
37231 goto cleanup;
37232 }
37233
37234 /* The server nonce must match according to the 1.04.1 specification errata,
37235 * chapter 3. */
37236 tokenpos = sizeof(UA_UInt32) + tokenSecretLength - serverNonce->length;
37237 tokenServerNonce.length = serverNonce->length;
37238 tokenServerNonce.data = &decryptedTokenSecret.data[tokenpos];
37239 if(!UA_ByteString_equal(string1: serverNonce, string2: &tokenServerNonce))
37240 goto cleanup;
37241
37242 /* The password was decrypted successfully. Replace usertoken with the
37243 * decrypted password. The encryptionAlgorithm and policyId fields are left
37244 * in the UserToken as an indication for the AccessControl plugin that
37245 * evaluates the decrypted content. */
37246 memcpy(dest: userToken->password.data, src: &decryptedTokenSecret.data[sizeof(UA_UInt32)],
37247 n: tokenSecretLength - serverNonce->length);
37248 userToken->password.length = tokenSecretLength - serverNonce->length;
37249 retval = UA_STATUSCODE_GOOD;
37250
37251 cleanup:
37252 UA_ByteString_clear(p: &decryptedTokenSecret);
37253 return retval;
37254}
37255#endif
37256
37257static void
37258selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
37259 const UA_ExtensionObject *identityToken,
37260 const UA_EndpointDescription **ed,
37261 const UA_UserTokenPolicy **utp) {
37262 for(size_t i = 0; i < server->config.endpointsSize; ++i) {
37263 const UA_EndpointDescription *desc = &server->config.endpoints[i];
37264
37265 /* Match the Security Mode */
37266 if(desc->securityMode != channel->securityMode)
37267 continue;
37268
37269 /* Match the SecurityPolicy of the endpoint with the current channel */
37270 if(!UA_String_equal(s1: &desc->securityPolicyUri, s2: &channel->securityPolicy->policyUri))
37271 continue;
37272
37273 /* Match the UserTokenType */
37274 const UA_DataType *tokenDataType = identityToken->content.decoded.type;
37275 for(size_t j = 0; j < desc->userIdentityTokensSize; j++) {
37276 const UA_UserTokenPolicy *pol = &desc->userIdentityTokens[j];
37277
37278 /* Part 4, Section 5.6.3.2, Table 17: A NULL or empty
37279 * UserIdentityToken should be treated as Anonymous */
37280 if(identityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
37281 pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
37282 *ed = desc;
37283 *utp = pol;
37284 return;
37285 }
37286
37287 /* Expect decoded content */
37288 if(!tokenDataType)
37289 continue;
37290
37291 if(pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
37292 if(tokenDataType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN])
37293 continue;
37294 } else if(pol->tokenType == UA_USERTOKENTYPE_USERNAME) {
37295 if(tokenDataType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN])
37296 continue;
37297 } else if(pol->tokenType == UA_USERTOKENTYPE_CERTIFICATE) {
37298 if(tokenDataType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN])
37299 continue;
37300 } else if(pol->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN) {
37301 if(tokenDataType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN])
37302 continue;
37303 } else {
37304 continue;
37305 }
37306
37307 /* All valid token data types start with a string policyId */
37308 UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
37309 identityToken->content.decoded.data;
37310
37311 if(!UA_String_equal(s1: &pol->policyId, s2: &token->policyId))
37312 continue;
37313
37314 /* Match found */
37315 *ed = desc;
37316 *utp = pol;
37317 return;
37318 }
37319 }
37320}
37321
37322#ifdef UA_ENABLE_DIAGNOSTICS
37323static UA_StatusCode
37324saveClientUserId(const UA_ExtensionObject *userIdentityToken,
37325 UA_SessionSecurityDiagnosticsDataType *diag) {
37326 UA_StatusCode res = UA_STATUSCODE_GOOD;
37327
37328 UA_String_clear(&diag->clientUserIdOfSession);
37329 if(userIdentityToken->encoding != UA_EXTENSIONOBJECT_DECODED)
37330 return UA_STATUSCODE_GOOD;
37331
37332 if(userIdentityToken->content.decoded.type ==
37333 &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
37334 /* String of length 0 */
37335 } else if(userIdentityToken->content.decoded.type ==
37336 &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
37337 const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
37338 userIdentityToken->content.decoded.data;
37339 res = UA_String_copy(&userToken->userName, &diag->clientUserIdOfSession);
37340 } else if(userIdentityToken->content.decoded.type ==
37341 &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
37342 /* TODO: return the X509 Subject Name of the certificate */
37343 } else {
37344 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37345 }
37346
37347 if(res != UA_STATUSCODE_GOOD)
37348 return res;
37349
37350 return UA_Array_appendCopy((void**)&diag->clientUserIdHistory,
37351 &diag->clientUserIdHistorySize,
37352 &diag->clientUserIdOfSession,
37353 &UA_TYPES[UA_TYPES_STRING]);
37354}
37355#endif
37356
37357
37358/* TODO: Check all of the following: The Server shall verify that the
37359 * Certificate the Client used to create the new SecureChannel is the same as
37360 * the Certificate used to create the original SecureChannel. In addition, the
37361 * Server shall verify that the Client supplied a UserIdentityToken that is
37362 * identical to the token currently associated with the Session. Once the Server
37363 * accepts the new SecureChannel it shall reject requests sent via the old
37364 * SecureChannel. */
37365
37366void
37367Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
37368 const UA_ActivateSessionRequest *request,
37369 UA_ActivateSessionResponse *response) {
37370 const UA_EndpointDescription *ed = NULL;
37371 const UA_UserTokenPolicy *utp = NULL;
37372 UA_String *tmpLocaleIds;
37373 UA_LOCK_ASSERT(&server->serviceMutex, 1);
37374
37375 UA_Session *session = getSessionByToken(server, token: &request->requestHeader.authenticationToken);
37376 if(!session) {
37377 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37378 "ActivateSession: Session not found");
37379 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37380 goto rejected;
37381 }
37382
37383 /* Part 4, §5.6.3: When the ActivateSession Service is called for the
37384 * first time then the Server shall reject the request if the
37385 * SecureChannel is not same as the one associated with the
37386 * CreateSession request. Subsequent calls to ActivateSession may be
37387 * associated with different SecureChannels. */
37388 if(!session->activated && session->header.channel != channel) {
37389 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37390 "ActivateSession: The Session has to be initially activated "
37391 "on the SecureChannel that created it");
37392 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37393 goto rejected;
37394 }
37395
37396 /* Has the session timed out? */
37397 if(session->validTill < UA_DateTime_nowMonotonic()) {
37398 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37399 "ActivateSession: The Session has timed out");
37400 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37401 goto rejected;
37402 }
37403
37404 /* Check the client signature */
37405 if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
37406 channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
37407 response->responseHeader.serviceResult =
37408 checkSignature(server, securityPolicy: channel->securityPolicy, channelContext: channel->channelContext,
37409 serverNonce: &session->serverNonce, signature: &request->clientSignature);
37410 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37411 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37412 "ActivateSession: Client signature check failed with StatusCode %s",
37413 UA_StatusCode_name(response->responseHeader.serviceResult));
37414 goto securityRejected;
37415 }
37416 }
37417
37418 /* Find the matching Endpoint with UserTokenPolicy */
37419 selectEndpointAndTokenPolicy(server, channel, identityToken: &request->userIdentityToken, ed: &ed, utp: &utp);
37420 if(!ed) {
37421 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37422 goto rejected;
37423 }
37424
37425 /* If it is a UserNameIdentityToken, the password may be encrypted */
37426 if(utp->tokenType == UA_USERTOKENTYPE_USERNAME) {
37427 UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken *)
37428 request->userIdentityToken.content.decoded.data;
37429
37430 /* If the userTokenPolicy doesn't specify a security policy the security
37431 * policy of the secure channel is used. */
37432 UA_SecurityPolicy* securityPolicy;
37433 if(!utp->securityPolicyUri.data)
37434 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &ed->securityPolicyUri);
37435 else
37436 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &utp->securityPolicyUri);
37437 if(!securityPolicy) {
37438 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
37439 goto securityRejected;
37440 }
37441
37442 /* Test if the encryption algorithm is correctly specified */
37443 if(!UA_String_equal(s1: &userToken->encryptionAlgorithm,
37444 s2: &securityPolicy->asymmetricModule.cryptoModule.encryptionAlgorithm.uri)) {
37445 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37446 goto securityRejected;
37447 }
37448
37449#ifdef UA_ENABLE_ENCRYPTION
37450 /* Encrypted password? */
37451 if(!UA_String_equal(s1: &securityPolicy->policyUri, s2: &UA_SECURITY_POLICY_NONE_URI)) {
37452 /* Create a temporary channel context if a different SecurityPolicy is
37453 * used for the password from the SecureChannel */
37454 void *tempChannelContext = channel->channelContext;
37455 if(securityPolicy != channel->securityPolicy) {
37456 /* We use our own certificate to create a temporary channel
37457 * context. Because the client does not provide one in a #None
37458 * SecureChannel. We should not need a ChannelContext at all for
37459 * asymmetric decryption where the remote certificate is not
37460 * used. */
37461 UA_UNLOCK(&server->serviceMutex);
37462 response->responseHeader.serviceResult = securityPolicy->channelModule.
37463 newContext(securityPolicy, &securityPolicy->localCertificate,
37464 &tempChannelContext);
37465 UA_LOCK(&server->serviceMutex);
37466 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37467 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37468 "Failed to create a context for the SecurityPolicy %.*s",
37469 (int)securityPolicy->policyUri.length,
37470 securityPolicy->policyUri.data);
37471 goto securityRejected;
37472 }
37473 }
37474
37475 /* Decrypt */
37476 response->responseHeader.serviceResult =
37477 decryptPassword(securityPolicy, tempChannelContext, serverNonce: &session->serverNonce, userToken);
37478
37479 /* Remove the temporary channel context */
37480 if(securityPolicy != channel->securityPolicy) {
37481 UA_UNLOCK(&server->serviceMutex);
37482 securityPolicy->channelModule.deleteContext(tempChannelContext);
37483 UA_LOCK(&server->serviceMutex);
37484 }
37485 } else if(userToken->encryptionAlgorithm.length != 0) {
37486 /* If SecurityPolicy is None there shall be no EncryptionAlgorithm */
37487 response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
37488 goto securityRejected;
37489 }
37490
37491 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37492 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37493 "Failed to decrypt the password with the StatusCode %s",
37494 UA_StatusCode_name(response->responseHeader.serviceResult));
37495 goto securityRejected;
37496 }
37497#endif
37498 }
37499
37500#ifdef UA_ENABLE_ENCRYPTION
37501 /* If it is a X509IdentityToken, check the userTokenSignature. Note this
37502 * only validates that the user has the corresponding private key for the
37503 * given user cetificate. Checking whether the user certificate is trusted
37504 * has to be implemented in the access control plugin. The entire token is
37505 * forwarded in the call to ActivateSession. */
37506 if(utp->tokenType == UA_USERTOKENTYPE_CERTIFICATE) {
37507 UA_X509IdentityToken* userCertToken = (UA_X509IdentityToken*)
37508 request->userIdentityToken.content.decoded.data;
37509
37510 /* If the userTokenPolicy doesn't specify a security policy the security
37511 * policy of the secure channel is used. */
37512 UA_SecurityPolicy* securityPolicy;
37513 if(!utp->securityPolicyUri.data)
37514 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &ed->securityPolicyUri);
37515 else
37516 securityPolicy = getSecurityPolicyByUri(server, securityPolicyUri: &utp->securityPolicyUri);
37517 if(!securityPolicy) {
37518 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
37519 goto securityRejected;
37520 }
37521
37522 /* We need a channel context with the user certificate in order to reuse
37523 * the signature checking code. */
37524 void *tempChannelContext;
37525 UA_UNLOCK(&server->serviceMutex);
37526 response->responseHeader.serviceResult = securityPolicy->channelModule.
37527 newContext(securityPolicy, &userCertToken->certificateData, &tempChannelContext);
37528 UA_LOCK(&server->serviceMutex);
37529 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37530 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: "
37531 "Failed to create a context for the SecurityPolicy %.*s",
37532 (int)securityPolicy->policyUri.length,
37533 securityPolicy->policyUri.data);
37534 goto securityRejected;
37535 }
37536
37537 /* Check the user token signature */
37538 response->responseHeader.serviceResult =
37539 checkSignature(server, securityPolicy: channel->securityPolicy, channelContext: tempChannelContext,
37540 serverNonce: &session->serverNonce, signature: &request->userTokenSignature);
37541
37542 /* Delete the temporary channel context */
37543 UA_UNLOCK(&server->serviceMutex);
37544 securityPolicy->channelModule.deleteContext(tempChannelContext);
37545 UA_LOCK(&server->serviceMutex);
37546 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37547 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37548 "ActivateSession: User token signature check failed with StatusCode %s",
37549 UA_StatusCode_name(response->responseHeader.serviceResult));
37550 goto securityRejected;
37551 }
37552 }
37553#endif
37554
37555 /* Callback into userland access control */
37556 UA_UNLOCK(&server->serviceMutex);
37557 response->responseHeader.serviceResult = server->config.accessControl.
37558 activateSession(server, &server->config.accessControl, ed, &channel->remoteCertificate,
37559 &session->sessionId, &request->userIdentityToken, &session->sessionHandle);
37560 UA_LOCK(&server->serviceMutex);
37561 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37562 UA_LOG_WARNING_SESSION(&server->config.logger, session, "ActivateSession: The AccessControl "
37563 "plugin denied the activation with the StatusCode %s",
37564 UA_StatusCode_name(response->responseHeader.serviceResult));
37565 goto securityRejected;
37566 }
37567
37568 /* Attach the session to the currently used channel if the session isn't
37569 * attached to a channel or if the session is activated on a different
37570 * channel than it is attached to. */
37571 if(!session->header.channel || session->header.channel != channel) {
37572 /* Attach the new SecureChannel, the old channel will be detached if present */
37573 UA_Session_attachToSecureChannel(session, channel);
37574 UA_LOG_INFO_SESSION(&server->config.logger, session,
37575 "ActivateSession: Session attached to new channel");
37576 }
37577
37578 /* Generate a new session nonce for the next time ActivateSession is called */
37579 response->responseHeader.serviceResult = UA_Session_generateNonce(session);
37580 response->responseHeader.serviceResult |=
37581 UA_ByteString_copy(src: &session->serverNonce, dst: &response->serverNonce);
37582 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37583 UA_Session_detachFromSecureChannel(session);
37584 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37585 "ActivateSession: Could not generate the server nonce");
37586 goto rejected;
37587 }
37588
37589 /* Set the locale */
37590 response->responseHeader.serviceResult |=
37591 UA_Array_copy(src: request->localeIds, size: request->localeIdsSize,
37592 dst: (void**)&tmpLocaleIds, type: &UA_TYPES[UA_TYPES_STRING]);
37593 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37594 UA_Session_detachFromSecureChannel(session);
37595 UA_LOG_WARNING_SESSION(&server->config.logger, session,
37596 "ActivateSession: Could not store the Session LocaleIds");
37597 goto rejected;
37598 }
37599 UA_Array_delete(p: session->localeIds, size: session->localeIdsSize,
37600 type: &UA_TYPES[UA_TYPES_STRING]);
37601 session->localeIds = tmpLocaleIds;
37602 session->localeIdsSize = request->localeIdsSize;
37603
37604 UA_Session_updateLifetime(session);
37605
37606 /* Activate the session */
37607 if(!session->activated) {
37608 session->activated = true;
37609 server->activeSessionCount++;
37610 server->serverDiagnosticsSummary.cumulatedSessionCount++;
37611 }
37612
37613#ifdef UA_ENABLE_DIAGNOSTICS
37614 saveClientUserId(&request->userIdentityToken,
37615 &session->securityDiagnostics);
37616 UA_String_clear(&session->securityDiagnostics.authenticationMechanism);
37617 switch(utp->tokenType) {
37618 case UA_USERTOKENTYPE_ANONYMOUS:
37619 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Anonymous");
37620 break;
37621 case UA_USERTOKENTYPE_USERNAME:
37622 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("UserName");
37623 break;
37624 case UA_USERTOKENTYPE_CERTIFICATE:
37625 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("Certificate");
37626 break;
37627 case UA_USERTOKENTYPE_ISSUEDTOKEN:
37628 session->securityDiagnostics.authenticationMechanism = UA_STRING_ALLOC("IssuedToken");
37629 break;
37630 default: break;
37631 }
37632#endif
37633
37634 UA_LOG_INFO_SESSION(&server->config.logger, session, "ActivateSession: Session activated");
37635 return;
37636
37637securityRejected:
37638 server->serverDiagnosticsSummary.securityRejectedSessionCount++;
37639rejected:
37640 server->serverDiagnosticsSummary.rejectedSessionCount++;
37641}
37642
37643void
37644Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
37645 const UA_CloseSessionRequest *request,
37646 UA_CloseSessionResponse *response) {
37647 UA_LOCK_ASSERT(&server->serviceMutex, 1);
37648
37649 /* Part 4, 5.6.4: When the CloseSession Service is called before the Session
37650 * is successfully activated, the Server shall reject the request if the
37651 * SecureChannel is not the same as the one associated with the
37652 * CreateSession request.
37653 *
37654 * A non-activated Session is already bound to the SecureChannel that
37655 * created the Session. */
37656 UA_Session *session = NULL;
37657 response->responseHeader.serviceResult =
37658 getBoundSession(server, channel, token: &request->requestHeader.authenticationToken, session: &session);
37659 if(!session && response->responseHeader.serviceResult == UA_STATUSCODE_GOOD)
37660 response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
37661 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
37662 UA_LOG_WARNING_CHANNEL(&server->config.logger, channel,
37663 "CloseSession: No Session activated to the SecureChannel");
37664 return;
37665 }
37666
37667 UA_assert(session); /* Assured by the previous section */
37668 UA_LOG_INFO_SESSION(&server->config.logger, session, "Closing the Session");
37669
37670#ifdef UA_ENABLE_SUBSCRIPTIONS
37671 /* If Subscriptions are not deleted, detach them from the Session */
37672 if(!request->deleteSubscriptions) {
37673 UA_Subscription *sub, *sub_tmp;
37674 TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, sub_tmp) {
37675 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
37676 "Detaching the Subscription from the Session");
37677 UA_Session_detachSubscription(server, session, sub, true);
37678 }
37679 }
37680#endif
37681
37682 /* Remove the sesison */
37683 response->responseHeader.serviceResult =
37684 UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken,
37685 event: UA_DIAGNOSTICEVENT_CLOSE);
37686}
37687
37688/**** amalgamated original file "/src/server/ua_services_attribute.c" ****/
37689
37690/* This Source Code Form is subject to the terms of the Mozilla Public
37691 * License, v. 2.0. If a copy of the MPL was not distributed with this
37692 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
37693 *
37694 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
37695 * Copyright 2015-2016 (c) Sten Grüner
37696 * Copyright 2014-2017 (c) Florian Palm
37697 * Copyright 2015 (c) Christian Fimmers
37698 * Copyright 2015-2016 (c) Chris Iatrou
37699 * Copyright 2015-2016 (c) Oleksiy Vasylyev
37700 * Copyright 2015 (c) wuyangtang
37701 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
37702 * Copyright 2016 (c) Lorenz Haas
37703 * Copyright 2017 (c) frax2222
37704 * Copyright 2017 (c) Thomas Bender
37705 * Copyright 2017 (c) Julian Grothoff
37706 * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
37707 * Copyright 2017 (c) Henrik Norrman
37708 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
37709 */
37710
37711
37712#ifdef UA_ENABLE_HISTORIZING
37713#endif
37714
37715/******************/
37716/* Access Control */
37717/******************/
37718
37719/* Session for read operations can be NULL. For example for a MonitoredItem
37720 * where the underlying Subscription was detached during CloseSession. */
37721
37722static UA_UInt32
37723getUserWriteMask(UA_Server *server, const UA_Session *session,
37724 const UA_NodeHead *head) {
37725 if(session == &server->adminSession)
37726 return 0xFFFFFFFF; /* the local admin user has all rights */
37727 UA_UInt32 mask = head->writeMask;
37728 UA_UNLOCK(&server->serviceMutex);
37729 mask &= server->config.accessControl.
37730 getUserRightsMask(server, &server->config.accessControl,
37731 session ? &session->sessionId : NULL,
37732 session ? session->sessionHandle : NULL,
37733 &head->nodeId, head->context);
37734 UA_LOCK(&server->serviceMutex);
37735 return mask;
37736}
37737
37738static UA_Byte
37739getAccessLevel(UA_Server *server, const UA_Session *session,
37740 const UA_VariableNode *node) {
37741 if(session == &server->adminSession)
37742 return 0xFF; /* the local admin user has all rights */
37743 return node->accessLevel;
37744}
37745
37746static UA_Byte
37747getUserAccessLevel(UA_Server *server, const UA_Session *session,
37748 const UA_VariableNode *node) {
37749 if(session == &server->adminSession)
37750 return 0xFF; /* the local admin user has all rights */
37751 UA_Byte retval = node->accessLevel;
37752 UA_UNLOCK(&server->serviceMutex);
37753 retval &= server->config.accessControl.
37754 getUserAccessLevel(server, &server->config.accessControl,
37755 session ? &session->sessionId : NULL,
37756 session ? session->sessionHandle : NULL,
37757 &node->head.nodeId, node->head.context);
37758 UA_LOCK(&server->serviceMutex);
37759 return retval;
37760}
37761
37762static UA_Boolean
37763getUserExecutable(UA_Server *server, const UA_Session *session,
37764 const UA_MethodNode *node) {
37765 if(session == &server->adminSession)
37766 return true; /* the local admin user has all rights */
37767 UA_UNLOCK(&server->serviceMutex);
37768 UA_Boolean userExecutable = node->executable;
37769 userExecutable &=
37770 server->config.accessControl.
37771 getUserExecutable(server, &server->config.accessControl,
37772 session ? &session->sessionId : NULL,
37773 session ? session->sessionHandle : NULL,
37774 &node->head.nodeId, node->head.context);
37775 UA_LOCK(&server->serviceMutex);
37776 return userExecutable;
37777}
37778
37779/****************/
37780/* Read Service */
37781/****************/
37782
37783static UA_StatusCode
37784readIsAbstractAttribute(const UA_Node *node, UA_Variant *v) {
37785 const UA_Boolean *isAbstract;
37786 switch(node->head.nodeClass) {
37787 case UA_NODECLASS_REFERENCETYPE:
37788 isAbstract = &node->referenceTypeNode.isAbstract;
37789 break;
37790 case UA_NODECLASS_OBJECTTYPE:
37791 isAbstract = &node->objectTypeNode.isAbstract;
37792 break;
37793 case UA_NODECLASS_VARIABLETYPE:
37794 isAbstract = &node->variableTypeNode.isAbstract;
37795 break;
37796 case UA_NODECLASS_DATATYPE:
37797 isAbstract = &node->dataTypeNode.isAbstract;
37798 break;
37799 default:
37800 return UA_STATUSCODE_BADATTRIBUTEIDINVALID;
37801 }
37802
37803 return UA_Variant_setScalarCopy(v, p: isAbstract, type: &UA_TYPES[UA_TYPES_BOOLEAN]);
37804}
37805
37806static UA_StatusCode
37807readValueAttributeFromNode(UA_Server *server, UA_Session *session,
37808 const UA_VariableNode *vn, UA_DataValue *v,
37809 UA_NumericRange *rangeptr) {
37810 /* Update the value by the user callback */
37811 if(vn->value.data.callback.onRead) {
37812 UA_UNLOCK(&server->serviceMutex);
37813 vn->value.data.callback.onRead(server,
37814 session ? &session->sessionId : NULL,
37815 session ? session->sessionHandle : NULL,
37816 &vn->head.nodeId, vn->head.context, rangeptr,
37817 &vn->value.data.value);
37818 UA_LOCK(&server->serviceMutex);
37819 vn = (const UA_VariableNode*)UA_NODESTORE_GET(server, &vn->head.nodeId);
37820 if(!vn)
37821 return UA_STATUSCODE_BADNODEIDUNKNOWN;
37822 }
37823
37824 /* Set the result */
37825 if(rangeptr)
37826 return UA_Variant_copyRange(src: &vn->value.data.value.value, dst: &v->value, range: *rangeptr);
37827 UA_StatusCode retval = UA_DataValue_copy(src: &vn->value.data.value, dst: v);
37828
37829 /* Clean up */
37830 if(vn->value.data.callback.onRead)
37831 UA_NODESTORE_RELEASE(server, (const UA_Node *)vn);
37832 return retval;
37833}
37834
37835static UA_StatusCode
37836readValueAttributeFromDataSource(UA_Server *server, UA_Session *session,
37837 const UA_VariableNode *vn, UA_DataValue *v,
37838 UA_TimestampsToReturn timestamps,
37839 UA_NumericRange *rangeptr) {
37840 if(!vn->value.dataSource.read)
37841 return UA_STATUSCODE_BADINTERNALERROR;
37842 UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE ||
37843 timestamps == UA_TIMESTAMPSTORETURN_BOTH);
37844 UA_DataValue v2;
37845 UA_DataValue_init(p: &v2);
37846 UA_UNLOCK(&server->serviceMutex);
37847 UA_StatusCode retval = vn->value.dataSource.
37848 read(server,
37849 session ? &session->sessionId : NULL,
37850 session ? session->sessionHandle : NULL,
37851 &vn->head.nodeId, vn->head.context,
37852 sourceTimeStamp, rangeptr, &v2);
37853 UA_LOCK(&server->serviceMutex);
37854 if(v2.hasValue && v2.value.storageType == UA_VARIANT_DATA_NODELETE) {
37855 retval = UA_DataValue_copy(src: &v2, dst: v);
37856 UA_DataValue_clear(p: &v2);
37857 } else {
37858 *v = v2;
37859 }
37860 return retval;
37861}
37862
37863static UA_StatusCode
37864readValueAttributeComplete(UA_Server *server, UA_Session *session,
37865 const UA_VariableNode *vn, UA_TimestampsToReturn timestamps,
37866 const UA_String *indexRange, UA_DataValue *v) {
37867 /* Compute the index range */
37868 UA_NumericRange range;
37869 UA_NumericRange *rangeptr = NULL;
37870 UA_StatusCode retval = UA_STATUSCODE_GOOD;
37871 if(indexRange && indexRange->length > 0) {
37872 retval = UA_NumericRange_parse(range: &range, str: *indexRange);
37873 if(retval != UA_STATUSCODE_GOOD)
37874 return retval;
37875 rangeptr = &range;
37876 }
37877
37878 switch(vn->valueBackend.backendType) {
37879 case UA_VALUEBACKENDTYPE_INTERNAL:
37880 retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
37881 //TODO change old structure to value backend
37882 break;
37883 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
37884 retval = readValueAttributeFromDataSource(server, session, vn, v,
37885 timestamps, rangeptr);
37886 //TODO change old structure to value backend
37887 break;
37888 case UA_VALUEBACKENDTYPE_EXTERNAL:
37889 if(vn->valueBackend.backend.external.callback.notificationRead){
37890 retval = vn->valueBackend.backend.external.callback.
37891 notificationRead(server,
37892 session ? &session->sessionId : NULL,
37893 session ? session->sessionHandle : NULL,
37894 &vn->head.nodeId, vn->head.context, rangeptr);
37895 } else {
37896 retval = UA_STATUSCODE_BADNOTREADABLE;
37897 }
37898 if(retval != UA_STATUSCODE_GOOD){
37899 break;
37900 }
37901 /* Set the result */
37902 if(rangeptr)
37903 retval = UA_DataValue_copyVariantRange(
37904 src: *vn->valueBackend.backend.external.value, dst: v, range: *rangeptr);
37905 else
37906 retval = UA_DataValue_copy(src: *vn->valueBackend.backend.external.value, dst: v);
37907 break;
37908 case UA_VALUEBACKENDTYPE_NONE:
37909 /* Read the value */
37910 if(vn->valueSource == UA_VALUESOURCE_DATA)
37911 retval = readValueAttributeFromNode(server, session, vn, v, rangeptr);
37912 else
37913 retval = readValueAttributeFromDataSource(server, session, vn, v,
37914 timestamps, rangeptr);
37915 /* end lagacy */
37916 break;
37917 }
37918
37919 /* Static Variables and VariableTypes have timestamps of "now". Will be set
37920 * below in the absence of predefined timestamps. */
37921 if(vn->head.nodeClass == UA_NODECLASS_VARIABLE) {
37922 if(!vn->isDynamic) {
37923 v->hasServerTimestamp = false;
37924 v->hasSourceTimestamp = false;
37925 }
37926 } else {
37927 v->hasServerTimestamp = false;
37928 v->hasSourceTimestamp = false;
37929 }
37930
37931 /* Clean up */
37932 if(rangeptr)
37933 UA_free(ptr: range.dimensions);
37934 return retval;
37935}
37936
37937UA_StatusCode
37938readValueAttribute(UA_Server *server, UA_Session *session,
37939 const UA_VariableNode *vn, UA_DataValue *v) {
37940 return readValueAttributeComplete(server, session, vn,
37941 timestamps: UA_TIMESTAMPSTORETURN_NEITHER, NULL, v);
37942}
37943
37944static const UA_String binEncoding = {sizeof("Default Binary")-1, (UA_Byte*)"Default Binary"};
37945static const UA_String xmlEncoding = {sizeof("Default XML")-1, (UA_Byte*)"Default XML"};
37946static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*)"Default JSON"};
37947
37948#define CHECK_NODECLASS(CLASS) \
37949 if(!(node->head.nodeClass & (CLASS))) { \
37950 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \
37951 break; \
37952 }
37953
37954#ifdef UA_ENABLE_TYPEDESCRIPTION
37955static const UA_DataType *
37956findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) {
37957 for(size_t i = 0; i < UA_TYPES_COUNT; ++i) {
37958 if(UA_NodeId_equal(n1: &UA_TYPES[i].typeId, n2: &node->head.nodeId)) {
37959 return &UA_TYPES[i];
37960 }
37961 }
37962
37963 // lookup custom type
37964 while(customTypes) {
37965 for(size_t i = 0; i < customTypes->typesSize; ++i) {
37966 if(UA_NodeId_equal(n1: &customTypes->types[i].typeId, n2: &node->head.nodeId))
37967 return &customTypes->types[i];
37968 }
37969 customTypes = customTypes->next;
37970 }
37971 return NULL;
37972}
37973
37974static UA_StatusCode
37975getStructureDefinition(const UA_DataType *type, UA_StructureDefinition *def) {
37976 UA_StatusCode retval =
37977 UA_NodeId_copy(src: &type->binaryEncodingId, dst: &def->defaultEncodingId);
37978 if(retval != UA_STATUSCODE_GOOD)
37979 return retval;
37980 switch(type->typeKind) {
37981 case UA_DATATYPEKIND_STRUCTURE:
37982 def->structureType = UA_STRUCTURETYPE_STRUCTURE;
37983 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
37984 break;
37985 case UA_DATATYPEKIND_OPTSTRUCT:
37986 def->structureType = UA_STRUCTURETYPE_STRUCTUREWITHOPTIONALFIELDS;
37987 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
37988 break;
37989 case UA_DATATYPEKIND_UNION:
37990 def->structureType = UA_STRUCTURETYPE_UNION;
37991 def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_UNION);
37992 break;
37993 default:
37994 return UA_STATUSCODE_BADENCODINGERROR;
37995 }
37996 def->fieldsSize = type->membersSize;
37997 def->fields = (UA_StructureField *)
37998 UA_calloc(nmemb: def->fieldsSize, size: sizeof(UA_StructureField));
37999 if(!def->fields) {
38000 UA_NodeId_clear(p: &def->defaultEncodingId);
38001 return UA_STATUSCODE_BADOUTOFMEMORY;
38002 }
38003
38004 for(size_t cnt = 0; cnt < def->fieldsSize; cnt++) {
38005 const UA_DataTypeMember *m = &type->members[cnt];
38006 def->fields[cnt].valueRank = UA_TRUE == m->isArray ? 1 : -1;
38007 def->fields[cnt].arrayDimensions = NULL;
38008 def->fields[cnt].arrayDimensionsSize = 0;
38009 def->fields[cnt].name = UA_STRING(chars: (char *)(uintptr_t)m->memberName);
38010 def->fields[cnt].description.locale = UA_STRING_NULL;
38011 def->fields[cnt].description.text = UA_STRING_NULL;
38012 def->fields[cnt].dataType = m->memberType->typeId;
38013 def->fields[cnt].maxStringLength = 0;
38014 def->fields[cnt].isOptional = m->isOptional;
38015 }
38016 return UA_STATUSCODE_GOOD;
38017}
38018#endif
38019
38020/* Returns a datavalue that may point into the node via the
38021 * UA_VARIANT_DATA_NODELETE tag. Don't access the returned DataValue once the
38022 * node has been released! */
38023void
38024ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session,
38025 UA_TimestampsToReturn timestampsToReturn,
38026 const UA_ReadValueId *id, UA_DataValue *v) {
38027 UA_LOG_NODEID_DEBUG(&node->head.nodeId,
38028 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
38029 "Read attribute %"PRIi32 " of Node %.*s",
38030 id->attributeId, (int)nodeIdStr.length,
38031 nodeIdStr.data));
38032
38033 /* Only Binary Encoding is supported */
38034 if(id->dataEncoding.name.length > 0 &&
38035 !UA_String_equal(s1: &binEncoding, s2: &id->dataEncoding.name)) {
38036 if(UA_String_equal(s1: &xmlEncoding, s2: &id->dataEncoding.name) ||
38037 UA_String_equal(s1: &jsonEncoding, s2: &id->dataEncoding.name))
38038 v->status = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
38039 else
38040 v->status = UA_STATUSCODE_BADDATAENCODINGINVALID;
38041 v->hasStatus = true;
38042 return;
38043 }
38044
38045 /* Index range for an attribute other than value */
38046 if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE) {
38047 v->hasStatus = true;
38048 v->status = UA_STATUSCODE_BADINDEXRANGENODATA;
38049 return;
38050 }
38051
38052 /* Read the attribute */
38053 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38054 switch(id->attributeId) {
38055 case UA_ATTRIBUTEID_NODEID:
38056 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeId,
38057 type: &UA_TYPES[UA_TYPES_NODEID]);
38058 break;
38059 case UA_ATTRIBUTEID_NODECLASS:
38060 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeClass,
38061 type: &UA_TYPES[UA_TYPES_NODECLASS]);
38062 break;
38063 case UA_ATTRIBUTEID_BROWSENAME:
38064 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.browseName,
38065 type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
38066 break;
38067 case UA_ATTRIBUTEID_DISPLAYNAME:
38068 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.displayName,
38069 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38070 break;
38071 case UA_ATTRIBUTEID_DESCRIPTION:
38072 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.description,
38073 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38074 break;
38075 case UA_ATTRIBUTEID_WRITEMASK:
38076 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.writeMask,
38077 type: &UA_TYPES[UA_TYPES_UINT32]);
38078 break;
38079 case UA_ATTRIBUTEID_USERWRITEMASK: {
38080 UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head);
38081 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userWriteMask,
38082 type: &UA_TYPES[UA_TYPES_UINT32]);
38083 break; }
38084 case UA_ATTRIBUTEID_ISABSTRACT:
38085 retval = readIsAbstractAttribute(node, v: &v->value);
38086 break;
38087 case UA_ATTRIBUTEID_SYMMETRIC:
38088 CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
38089 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.symmetric,
38090 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38091 break;
38092 case UA_ATTRIBUTEID_INVERSENAME:
38093 CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE);
38094 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.inverseName,
38095 type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
38096 break;
38097 case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
38098 CHECK_NODECLASS(UA_NODECLASS_VIEW);
38099 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.containsNoLoops,
38100 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38101 break;
38102 case UA_ATTRIBUTEID_EVENTNOTIFIER:
38103 CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
38104 if(node->head.nodeClass == UA_NODECLASS_VIEW) {
38105 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.eventNotifier,
38106 type: &UA_TYPES[UA_TYPES_BYTE]);
38107 } else {
38108 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->objectNode.eventNotifier,
38109 type: &UA_TYPES[UA_TYPES_BYTE]);
38110 }
38111 break;
38112 case UA_ATTRIBUTEID_VALUE: {
38113 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38114 /* VariableTypes don't have the AccessLevel concept. Always allow
38115 * reading the value. */
38116 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
38117 /* The access to a value variable is granted via the AccessLevel
38118 * and UserAccessLevel attributes */
38119 UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode);
38120 if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
38121 retval = UA_STATUSCODE_BADNOTREADABLE;
38122 break;
38123 }
38124 accessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
38125 if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) {
38126 retval = UA_STATUSCODE_BADUSERACCESSDENIED;
38127 break;
38128 }
38129 }
38130 retval = readValueAttributeComplete(server, session, vn: &node->variableNode,
38131 timestamps: timestampsToReturn, indexRange: &id->indexRange, v);
38132 break;
38133 }
38134 case UA_ATTRIBUTEID_DATATYPE:
38135 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38136 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.dataType,
38137 type: &UA_TYPES[UA_TYPES_NODEID]);
38138 break;
38139 case UA_ATTRIBUTEID_VALUERANK:
38140 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38141 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.valueRank,
38142 type: &UA_TYPES[UA_TYPES_INT32]);
38143 break;
38144 case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
38145 CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
38146 retval = UA_Variant_setArrayCopy(v: &v->value, array: node->variableTypeNode.arrayDimensions,
38147 arraySize: node->variableTypeNode.arrayDimensionsSize,
38148 type: &UA_TYPES[UA_TYPES_UINT32]);
38149 break;
38150 case UA_ATTRIBUTEID_ACCESSLEVEL:
38151 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38152 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.accessLevel,
38153 type: &UA_TYPES[UA_TYPES_BYTE]);
38154 break;
38155 case UA_ATTRIBUTEID_USERACCESSLEVEL: {
38156 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38157 UA_Byte userAccessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
38158 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userAccessLevel,
38159 type: &UA_TYPES[UA_TYPES_BYTE]);
38160 break; }
38161 case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
38162 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38163 retval = UA_Variant_setScalarCopy(v: &v->value,
38164 p: &node->variableNode.minimumSamplingInterval,
38165 type: &UA_TYPES[UA_TYPES_DOUBLE]);
38166 break;
38167 case UA_ATTRIBUTEID_HISTORIZING:
38168 CHECK_NODECLASS(UA_NODECLASS_VARIABLE);
38169 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.historizing,
38170 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38171 break;
38172 case UA_ATTRIBUTEID_EXECUTABLE:
38173 CHECK_NODECLASS(UA_NODECLASS_METHOD);
38174 retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->methodNode.executable,
38175 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38176 break;
38177 case UA_ATTRIBUTEID_USEREXECUTABLE: {
38178 CHECK_NODECLASS(UA_NODECLASS_METHOD);
38179 UA_Boolean userExecutable =
38180 getUserExecutable(server, session, node: &node->methodNode);
38181 retval = UA_Variant_setScalarCopy(v: &v->value, p: &userExecutable,
38182 type: &UA_TYPES[UA_TYPES_BOOLEAN]);
38183 break; }
38184 case UA_ATTRIBUTEID_DATATYPEDEFINITION: {
38185 CHECK_NODECLASS(UA_NODECLASS_DATATYPE);
38186
38187#ifdef UA_ENABLE_TYPEDESCRIPTION
38188 const UA_DataType *type =
38189 findDataType(node, customTypes: server->config.customDataTypes);
38190 if(!type) {
38191 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38192 break;
38193 }
38194
38195 if(UA_DATATYPEKIND_STRUCTURE == type->typeKind ||
38196 UA_DATATYPEKIND_OPTSTRUCT == type->typeKind ||
38197 UA_DATATYPEKIND_UNION == type->typeKind) {
38198 UA_StructureDefinition def;
38199 retval = getStructureDefinition(type, def: &def);
38200 if(UA_STATUSCODE_GOOD!=retval)
38201 break;
38202 retval = UA_Variant_setScalarCopy(v: &v->value, p: &def,
38203 type: &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]);
38204 UA_free(ptr: def.fields);
38205 break;
38206 }
38207#endif
38208 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38209 break; }
38210 default:
38211 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
38212 }
38213
38214 if(retval != UA_STATUSCODE_GOOD) {
38215 /* Reading has failed but can not return because we may need to add timestamp */
38216 v->hasStatus = true;
38217 v->status = retval;
38218 } else {
38219 v->hasValue = true;
38220 }
38221
38222 /* Create server timestamp */
38223 if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
38224 timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH) {
38225 if(!v->hasServerTimestamp) {
38226 v->serverTimestamp = UA_DateTime_now();
38227 v->hasServerTimestamp = true;
38228 }
38229 } else {
38230 /* In case the ServerTimestamp has been set manually */
38231 v->hasServerTimestamp = false;
38232 }
38233
38234 /* Handle source time stamp */
38235 if(id->attributeId == UA_ATTRIBUTEID_VALUE) {
38236 if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER ||
38237 timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER) {
38238 v->hasSourceTimestamp = false;
38239 v->hasSourcePicoseconds = false;
38240 } else if(!v->hasSourceTimestamp) {
38241 v->sourceTimestamp = UA_DateTime_now();
38242 v->hasSourceTimestamp = true;
38243 }
38244 }
38245}
38246
38247static void
38248Operation_Read(UA_Server *server, UA_Session *session, UA_ReadRequest *request,
38249 UA_ReadValueId *rvi, UA_DataValue *result) {
38250 /* Get the node */
38251 const UA_Node *node = UA_NODESTORE_GET(server, &rvi->nodeId);
38252
38253 /* Perform the read operation */
38254 if(node) {
38255 ReadWithNode(node, server, session, timestampsToReturn: request->timestampsToReturn, id: rvi, v: result);
38256 UA_NODESTORE_RELEASE(server, node);
38257 } else {
38258 result->hasStatus = true;
38259 result->status = UA_STATUSCODE_BADNODEIDUNKNOWN;
38260 }
38261}
38262
38263void
38264Service_Read(UA_Server *server, UA_Session *session,
38265 const UA_ReadRequest *request, UA_ReadResponse *response) {
38266 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing ReadRequest");
38267 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38268
38269 /* Check if the timestampstoreturn is valid */
38270 if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
38271 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
38272 return;
38273 }
38274
38275 /* Check if maxAge is valid */
38276 if(request->maxAge < 0) {
38277 response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID;
38278 return;
38279 }
38280
38281 /* Check if there are too many operations */
38282 if(server->config.maxNodesPerRead != 0 &&
38283 request->nodesToReadSize > server->config.maxNodesPerRead) {
38284 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
38285 return;
38286 }
38287
38288 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38289
38290 response->responseHeader.serviceResult =
38291 UA_Server_processServiceOperations(server, session,
38292 operationCallback: (UA_ServiceOperation)Operation_Read,
38293 context: request, requestOperations: &request->nodesToReadSize,
38294 requestOperationsType: &UA_TYPES[UA_TYPES_READVALUEID],
38295 responseOperations: &response->resultsSize,
38296 responseOperationsType: &UA_TYPES[UA_TYPES_DATAVALUE]);
38297}
38298
38299UA_DataValue
38300UA_Server_readWithSession(UA_Server *server, UA_Session *session,
38301 const UA_ReadValueId *item,
38302 UA_TimestampsToReturn timestampsToReturn) {
38303 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38304
38305 UA_DataValue dv;
38306 UA_DataValue_init(p: &dv);
38307
38308 /* Get the node */
38309 const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
38310 if(!node) {
38311 dv.hasStatus = true;
38312 dv.status = UA_STATUSCODE_BADNODEIDUNKNOWN;
38313 return dv;
38314 }
38315
38316 /* Perform the read operation */
38317 ReadWithNode(node, server, session, timestampsToReturn, id: item, v: &dv);
38318
38319 /* Release the node and return */
38320 UA_NODESTORE_RELEASE(server, node);
38321 return dv;
38322}
38323
38324UA_DataValue
38325readAttribute(UA_Server *server, const UA_ReadValueId *item,
38326 UA_TimestampsToReturn timestamps) {
38327 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38328 return UA_Server_readWithSession(server, session: &server->adminSession, item, timestampsToReturn: timestamps);
38329}
38330
38331UA_StatusCode
38332readWithReadValue(UA_Server *server, const UA_NodeId *nodeId,
38333 const UA_AttributeId attributeId, void *v) {
38334 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38335
38336 /* Call the read service */
38337 UA_ReadValueId item;
38338 UA_ReadValueId_init(p: &item);
38339 item.nodeId = *nodeId;
38340 item.attributeId = attributeId;
38341 UA_DataValue dv = readAttribute(server, item: &item, timestamps: UA_TIMESTAMPSTORETURN_NEITHER);
38342
38343 /* Check the return value */
38344 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38345 if(dv.hasStatus)
38346 retval = dv.status;
38347 else if(!dv.hasValue)
38348 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
38349 if(retval != UA_STATUSCODE_GOOD) {
38350 UA_DataValue_clear(p: &dv);
38351 return retval;
38352 }
38353
38354 if(attributeId == UA_ATTRIBUTEID_VALUE ||
38355 attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS) {
38356 /* Return the entire variant */
38357 memcpy(dest: v, src: &dv.value, n: sizeof(UA_Variant));
38358 } else {
38359 /* Return the variant content only */
38360 memcpy(dest: v, src: dv.value.data, n: dv.value.type->memSize);
38361 UA_free(ptr: dv.value.data);
38362 }
38363 return retval;
38364}
38365
38366/* Exposes the Read service to local users */
38367UA_DataValue
38368UA_Server_read(UA_Server *server, const UA_ReadValueId *item,
38369 UA_TimestampsToReturn timestamps) {
38370 UA_LOCK(&server->serviceMutex);
38371 UA_DataValue dv = readAttribute(server, item, timestamps);
38372 UA_UNLOCK(&server->serviceMutex);
38373 return dv;
38374}
38375
38376/* Used in inline functions exposing the Read service with more syntactic sugar
38377 * for individual attributes */
38378UA_StatusCode
38379__UA_Server_read(UA_Server *server, const UA_NodeId *nodeId,
38380 const UA_AttributeId attributeId, void *v) {
38381 UA_LOCK(&server->serviceMutex);
38382 UA_StatusCode retval = readWithReadValue(server, nodeId, attributeId, v);
38383 UA_UNLOCK(&server->serviceMutex);
38384 return retval;
38385}
38386
38387UA_StatusCode
38388readObjectProperty(UA_Server *server, const UA_NodeId objectId,
38389 const UA_QualifiedName propertyName,
38390 UA_Variant *value) {
38391 UA_LOCK_ASSERT(&server->serviceMutex, 1);
38392
38393 /* Create a BrowsePath to get the target NodeId */
38394 UA_RelativePathElement rpe;
38395 UA_RelativePathElement_init(p: &rpe);
38396 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
38397 rpe.isInverse = false;
38398 rpe.includeSubtypes = false;
38399 rpe.targetName = propertyName;
38400
38401 UA_BrowsePath bp;
38402 UA_BrowsePath_init(p: &bp);
38403 bp.startingNode = objectId;
38404 bp.relativePath.elementsSize = 1;
38405 bp.relativePath.elements = &rpe;
38406
38407 UA_StatusCode retval;
38408 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
38409 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
38410 retval = bpr.statusCode;
38411 UA_BrowsePathResult_clear(p: &bpr);
38412 return retval;
38413 }
38414
38415 /* Use the first result from the BrowsePath */
38416 retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId,
38417 attributeId: UA_ATTRIBUTEID_VALUE, v: value);
38418
38419 UA_BrowsePathResult_clear(p: &bpr);
38420 return retval;
38421}
38422
38423
38424UA_StatusCode
38425UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId,
38426 const UA_QualifiedName propertyName,
38427 UA_Variant *value) {
38428 UA_LOCK(&server->serviceMutex);
38429 UA_StatusCode retval = readObjectProperty(server, objectId, propertyName, value);
38430 UA_UNLOCK(&server->serviceMutex);
38431 return retval;
38432}
38433
38434/*****************/
38435/* Type Checking */
38436/*****************/
38437
38438static UA_DataTypeKind
38439typeEquivalence(const UA_DataType *t) {
38440 UA_DataTypeKind k = (UA_DataTypeKind)t->typeKind;
38441 if(k == UA_DATATYPEKIND_ENUM)
38442 return UA_DATATYPEKIND_INT32;
38443 return k;
38444}
38445
38446static const UA_NodeId enumNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ENUMERATION}};
38447
38448UA_Boolean
38449compatibleValueDataType(UA_Server *server, const UA_DataType *dataType,
38450 const UA_NodeId *constraintDataType) {
38451 if(compatibleDataTypes(server, dataType: &dataType->typeId, constraintDataType))
38452 return true;
38453
38454 /* For actual values, the constraint DataType may be a subtype of the
38455 * DataType of the value. E.g. UtcTime is subtype of DateTime. But it still
38456 * is a DateTime value when transferred over the wire. */
38457 if(isNodeInTree_singleRef(server, leafNode: constraintDataType, nodeToFind: &dataType->typeId,
38458 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38459 return true;
38460
38461 return false;
38462}
38463
38464UA_Boolean
38465compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType,
38466 const UA_NodeId *constraintDataType) {
38467 /* Do not allow empty datatypes */
38468 if(UA_NodeId_isNull(p: dataType))
38469 return false;
38470
38471 /* No constraint or Variant / BaseDataType which allows any content */
38472 if(UA_NodeId_isNull(p: constraintDataType) ||
38473 UA_NodeId_equal(n1: constraintDataType, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId))
38474 return true;
38475
38476 /* Same datatypes */
38477 if(UA_NodeId_equal(n1: dataType, n2: constraintDataType))
38478 return true;
38479
38480 /* Is the DataType a subtype of the constraint type? */
38481 if(isNodeInTree_singleRef(server, leafNode: dataType, nodeToFind: constraintDataType,
38482 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38483 return true;
38484
38485 /* The constraint is an enum -> allow writing Int32 */
38486 if(UA_NodeId_equal(n1: dataType, n2: &UA_TYPES[UA_TYPES_INT32].typeId) &&
38487 isNodeInTree_singleRef(server, leafNode: constraintDataType, nodeToFind: &enumNodeId,
38488 UA_REFERENCETYPEINDEX_HASSUBTYPE))
38489 return true;
38490
38491 return false;
38492}
38493
38494/* Test whether a ValueRank and the given arraydimensions are compatible.
38495 *
38496 * 5.6.2 Variable NodeClass: If the maximum is unknown the value shall be 0. The
38497 * number of elements shall be equal to the value of the ValueRank Attribute.
38498 * This Attribute shall be null if ValueRank <= 0. */
38499UA_Boolean
38500compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session,
38501 UA_Int32 valueRank, size_t arrayDimensionsSize) {
38502 /* ValueRank invalid */
38503 if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION) {
38504 UA_LOG_INFO_SESSION(&server->config.logger, session,
38505 "The ValueRank is invalid (< -3)");
38506 return false;
38507 }
38508
38509 /* case -3, UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: the value can be a scalar
38510 * or a one dimensional array
38511 * case -2, UA_VALUERANK_ANY: the value can be a scalar or an array with any
38512 * number of dimensions
38513 * case -1, UA_VALUERANK_SCALAR: the value is a scalar
38514 * case 0, UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: the value is an array with
38515 * one or more dimensions */
38516 if(valueRank <= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) {
38517 if(arrayDimensionsSize > 0) {
38518 UA_LOG_INFO_SESSION(&server->config.logger, session,
38519 "No ArrayDimensions can be defined for a ValueRank <= 0");
38520 return false;
38521 }
38522 return true;
38523 }
38524
38525 /* case >= 1, UA_VALUERANK_ONE_DIMENSION: the value is an array with the
38526 specified number of dimensions */
38527 if(arrayDimensionsSize != (size_t)valueRank) {
38528 UA_LOG_INFO_SESSION(&server->config.logger, session,
38529 "The number of ArrayDimensions is not equal to "
38530 "the (positive) ValueRank");
38531 return false;
38532 }
38533 return true;
38534}
38535
38536UA_Boolean
38537compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank) {
38538 /* Check if the valuerank of the variabletype allows the change. */
38539 switch(constraintValueRank) {
38540 case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* the value can be a scalar or a
38541 one dimensional array */
38542 if(valueRank != UA_VALUERANK_SCALAR && valueRank != UA_VALUERANK_ONE_DIMENSION)
38543 return false;
38544 break;
38545 case UA_VALUERANK_ANY: /* the value can be a scalar or an array with any
38546 number of dimensions */
38547 break;
38548 case UA_VALUERANK_SCALAR: /* the value is a scalar */
38549 if(valueRank != UA_VALUERANK_SCALAR)
38550 return false;
38551 break;
38552 case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: /* the value is an array with one
38553 or more dimensions */
38554 if(valueRank < (UA_Int32) UA_VALUERANK_ONE_OR_MORE_DIMENSIONS)
38555 return false;
38556 break;
38557 default: /* >= 1: the value is an array with the specified number of
38558 dimensions */
38559 if(valueRank != constraintValueRank)
38560 return false;
38561 break;
38562 }
38563 return true;
38564}
38565
38566/* Check if the ValueRank allows for the value dimension. This is more
38567 * permissive than checking for the ArrayDimensions attribute. Because the value
38568 * can have dimensions if the ValueRank < 0 */
38569static UA_Boolean
38570compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) {
38571 /* Invalid ValueRank */
38572 if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION)
38573 return false;
38574
38575 /* Empty arrays (-1) always match */
38576 if(!value->data)
38577 return true;
38578
38579 size_t arrayDims = value->arrayDimensionsSize;
38580 if(arrayDims == 0 && !UA_Variant_isScalar(v: value))
38581 arrayDims = 1; /* array but no arraydimensions -> implicit array dimension 1 */
38582
38583 /* We cannot simply use compatibleValueRankArrayDimensions since we can have
38584 * defined ArrayDimensions for the value if the ValueRank is -2 */
38585 switch(valueRank) {
38586 case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* The value can be a scalar or a
38587 one dimensional array */
38588 return (arrayDims <= 1);
38589 case UA_VALUERANK_ANY: /* The value can be a scalar or an array with any
38590 number of dimensions */
38591 return true;
38592 case UA_VALUERANK_SCALAR: /* The value is a scalar */
38593 return (arrayDims == 0);
38594 case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS:
38595 return (arrayDims >= 1);
38596 default:
38597 break;
38598 }
38599
38600 UA_assert(valueRank >= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS);
38601
38602 /* case 0: the value is an array with one or more dimensions */
38603 return (arrayDims == (UA_UInt32)valueRank);
38604}
38605
38606UA_Boolean
38607compatibleArrayDimensions(size_t constraintArrayDimensionsSize,
38608 const UA_UInt32 *constraintArrayDimensions,
38609 size_t testArrayDimensionsSize,
38610 const UA_UInt32 *testArrayDimensions) {
38611 /* No array dimensions defined -> everything is permitted if the value rank fits */
38612 if(constraintArrayDimensionsSize == 0)
38613 return true;
38614
38615 /* Dimension count must match */
38616 if(testArrayDimensionsSize != constraintArrayDimensionsSize)
38617 return false;
38618
38619 /* Dimension lengths must not be larger than the constraint. Zero in the
38620 * constraint indicates a wildcard. */
38621 for(size_t i = 0; i < constraintArrayDimensionsSize; ++i) {
38622 if(constraintArrayDimensions[i] < testArrayDimensions[i] &&
38623 constraintArrayDimensions[i] != 0)
38624 return false;
38625 }
38626 return true;
38627}
38628
38629UA_Boolean
38630compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize,
38631 const UA_UInt32 *targetArrayDimensions) {
38632 size_t valueArrayDimensionsSize = value->arrayDimensionsSize;
38633 UA_UInt32 *valueArrayDimensions = value->arrayDimensions;
38634 UA_UInt32 tempArrayDimensions;
38635 if(!valueArrayDimensions && !UA_Variant_isScalar(v: value)) {
38636 valueArrayDimensionsSize = 1;
38637 tempArrayDimensions = (UA_UInt32)value->arrayLength;
38638 valueArrayDimensions = &tempArrayDimensions;
38639 }
38640 UA_assert(valueArrayDimensionsSize == 0 || valueArrayDimensions != NULL);
38641 return compatibleArrayDimensions(constraintArrayDimensionsSize: targetArrayDimensionsSize, constraintArrayDimensions: targetArrayDimensions,
38642 testArrayDimensionsSize: valueArrayDimensionsSize, testArrayDimensions: valueArrayDimensions);
38643}
38644
38645const char *reason_EmptyType = "Empty value only allowed for BaseDataType";
38646const char *reason_ValueDataType = "DataType of the value is incompatible";
38647const char *reason_ValueArrayDimensions = "ArrayDimensions of the value are incompatible";
38648const char *reason_ValueValueRank = "ValueRank of the value is incompatible";
38649
38650UA_Boolean
38651compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId,
38652 UA_Int32 targetValueRank, size_t targetArrayDimensionsSize,
38653 const UA_UInt32 *targetArrayDimensions, const UA_Variant *value,
38654 const UA_NumericRange *range, const char **reason) {
38655 /* Empty value */
38656 if(!value->type) {
38657 /* Empty value is allowed for BaseDataType */
38658 if(UA_NodeId_equal(n1: targetDataTypeId, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId) ||
38659 UA_NodeId_equal(n1: targetDataTypeId, n2: &UA_NODEID_NULL))
38660 return true;
38661
38662 /* Ignore if that is configured */
38663 if(server->bootstrapNS0 ||
38664 server->config.allowEmptyVariables == UA_RULEHANDLING_ACCEPT)
38665 return true;
38666
38667 UA_LOG_INFO_SESSION(&server->config.logger, session,
38668 "Only Variables with data type BaseDataType "
38669 "can contain an empty value");
38670
38671 /* Ignore if that is configured */
38672 if(server->config.allowEmptyVariables == UA_RULEHANDLING_WARN)
38673 return true;
38674
38675 /* Default handling is to abort */
38676 *reason = reason_EmptyType;
38677 return false;
38678 }
38679
38680 /* Is the datatype compatible? */
38681 if(!compatibleValueDataType(server, dataType: value->type, constraintDataType: targetDataTypeId)) {
38682 *reason = reason_ValueDataType;
38683 return false;
38684 }
38685
38686 /* Array dimensions are checked later when writing the range */
38687 if(range)
38688 return true;
38689
38690 /* See if the array dimensions match. */
38691 if(!compatibleValueArrayDimensions(value, targetArrayDimensionsSize,
38692 targetArrayDimensions)) {
38693 *reason = reason_ValueArrayDimensions;
38694 return false;
38695 }
38696
38697 /* Check if the valuerank allows for the value dimension */
38698 if(!compatibleValueRankValue(valueRank: targetValueRank, value)) {
38699 *reason = reason_ValueValueRank;
38700 return false;
38701 }
38702
38703 return true;
38704}
38705
38706/*****************/
38707/* Write Service */
38708/*****************/
38709
38710void
38711adjustValueType(UA_Server *server, UA_Variant *value,
38712 const UA_NodeId *targetDataTypeId) {
38713 /* If the value is empty, there is nothing we can do here */
38714 if(!value->type)
38715 return;
38716
38717 const UA_DataType *targetDataType = UA_findDataType(typeId: targetDataTypeId);
38718 if(!targetDataType)
38719 return;
38720
38721 /* A string is written to a byte array. the valuerank and array dimensions
38722 * are checked later */
38723 if(targetDataType == &UA_TYPES[UA_TYPES_BYTE] &&
38724 value->type == &UA_TYPES[UA_TYPES_BYTESTRING] &&
38725 UA_Variant_isScalar(v: value)) {
38726 UA_ByteString *str = (UA_ByteString*)value->data;
38727 value->type = &UA_TYPES[UA_TYPES_BYTE];
38728 value->arrayLength = str->length;
38729 value->data = str->data;
38730 return;
38731 }
38732
38733 /* An enum was sent as an int32, or an opaque type as a bytestring. This
38734 * is detected with the typeKind indicating the "true" datatype. */
38735 UA_DataTypeKind te1 = typeEquivalence(t: targetDataType);
38736 UA_DataTypeKind te2 = typeEquivalence(t: value->type);
38737 if(te1 == te2 && te1 <= UA_DATATYPEKIND_ENUM) {
38738 value->type = targetDataType;
38739 return;
38740 }
38741
38742 /* No more possible equivalencies */
38743}
38744
38745static UA_StatusCode
38746writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session,
38747 UA_VariableNode *node, const UA_VariableTypeNode *type,
38748 size_t arrayDimensionsSize, UA_UInt32 *arrayDimensions) {
38749 UA_assert(node != NULL);
38750 UA_assert(type != NULL);
38751
38752 /* If this is a variabletype, there must be no instances or subtypes of it
38753 * when we do the change */
38754 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38755 UA_Node_hasSubTypeOrInstances(head: &node->head)) {
38756 UA_LOG_INFO(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38757 msg: "Cannot change a variable type with existing instances");
38758 return UA_STATUSCODE_BADINTERNALERROR;
38759 }
38760
38761 /* Check that the array dimensions match with the valuerank */
38762 if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank,
38763 arrayDimensionsSize)) {
38764 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38765 msg: "Cannot write the ArrayDimensions. The ValueRank does not match.");
38766 return UA_STATUSCODE_BADTYPEMISMATCH;
38767 }
38768
38769 /* Check if the array dimensions match with the wildcards in the
38770 * variabletype (dimension length 0) */
38771 if(type->arrayDimensions &&
38772 !compatibleArrayDimensions(constraintArrayDimensionsSize: type->arrayDimensionsSize, constraintArrayDimensions: type->arrayDimensions,
38773 testArrayDimensionsSize: arrayDimensionsSize, testArrayDimensions: arrayDimensions)) {
38774 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38775 msg: "Array dimensions in the variable type do not match");
38776 return UA_STATUSCODE_BADTYPEMISMATCH;
38777 }
38778
38779 /* Check if the current value is compatible with the array dimensions */
38780 UA_DataValue value;
38781 UA_DataValue_init(p: &value);
38782 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38783 if(retval != UA_STATUSCODE_GOOD)
38784 return retval;
38785 if(value.hasValue) {
38786 if(!compatibleValueArrayDimensions(value: &value.value, targetArrayDimensionsSize: arrayDimensionsSize,
38787 targetArrayDimensions: arrayDimensions))
38788 retval = UA_STATUSCODE_BADTYPEMISMATCH;
38789 UA_DataValue_clear(p: &value);
38790 if(retval != UA_STATUSCODE_GOOD) {
38791 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38792 msg: "Array dimensions in the current value do not match");
38793 return retval;
38794 }
38795 }
38796
38797 /* Ok, apply */
38798 UA_UInt32 *oldArrayDimensions = node->arrayDimensions;
38799 size_t oldArrayDimensionsSize = node->arrayDimensionsSize;
38800 retval = UA_Array_copy(src: arrayDimensions, size: arrayDimensionsSize,
38801 dst: (void**)&node->arrayDimensions,
38802 type: &UA_TYPES[UA_TYPES_UINT32]);
38803 if(retval != UA_STATUSCODE_GOOD)
38804 return retval;
38805 UA_Array_delete(p: oldArrayDimensions, size: oldArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
38806 node->arrayDimensionsSize = arrayDimensionsSize;
38807 return UA_STATUSCODE_GOOD;
38808}
38809
38810/* Stack layout: ... | node | type */
38811static UA_StatusCode
38812writeValueRankAttribute(UA_Server *server, UA_Session *session,
38813 UA_VariableNode *node, const UA_VariableTypeNode *type,
38814 UA_Int32 valueRank) {
38815 UA_assert(node != NULL);
38816 UA_assert(type != NULL);
38817
38818 UA_Int32 constraintValueRank = type->valueRank;
38819
38820 /* If this is a variabletype, there must be no instances or subtypes of it
38821 * when we do the change */
38822 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38823 UA_Node_hasSubTypeOrInstances(head: &node->head))
38824 return UA_STATUSCODE_BADINTERNALERROR;
38825
38826 /* Check if the valuerank of the variabletype allows the change. */
38827 if(!compatibleValueRanks(valueRank, constraintValueRank))
38828 return UA_STATUSCODE_BADTYPEMISMATCH;
38829
38830 /* Check if the new valuerank is compatible with the array dimensions. Use
38831 * the read service to handle data sources. */
38832 size_t arrayDims = node->arrayDimensionsSize;
38833 if(arrayDims == 0) {
38834 /* the value could be an array with no arrayDimensions defined.
38835 dimensions zero indicate a scalar for compatibleValueRankArrayDimensions. */
38836 UA_DataValue value;
38837 UA_DataValue_init(p: &value);
38838 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38839 if(retval != UA_STATUSCODE_GOOD)
38840 return retval;
38841 if(!value.hasValue || !value.value.type) {
38842 /* no value -> apply */
38843 node->valueRank = valueRank;
38844 return UA_STATUSCODE_GOOD;
38845 }
38846 if(!UA_Variant_isScalar(v: &value.value))
38847 arrayDims = 1;
38848 UA_DataValue_clear(p: &value);
38849 }
38850 if(!compatibleValueRankArrayDimensions(server, session, valueRank, arrayDimensionsSize: arrayDims))
38851 return UA_STATUSCODE_BADTYPEMISMATCH;
38852
38853 /* All good, apply the change */
38854 node->valueRank = valueRank;
38855 return UA_STATUSCODE_GOOD;
38856}
38857
38858static UA_StatusCode
38859writeDataTypeAttribute(UA_Server *server, UA_Session *session,
38860 UA_VariableNode *node, const UA_VariableTypeNode *type,
38861 const UA_NodeId *dataType) {
38862 UA_assert(node != NULL);
38863 UA_assert(type != NULL);
38864
38865 /* If this is a variabletype, there must be no instances or subtypes of it
38866 when we do the change */
38867 if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE &&
38868 UA_Node_hasSubTypeOrInstances(head: &node->head))
38869 return UA_STATUSCODE_BADINTERNALERROR;
38870
38871 /* Does the new type match the constraints of the variabletype? */
38872 if(!compatibleDataTypes(server, dataType, constraintDataType: &type->dataType))
38873 return UA_STATUSCODE_BADTYPEMISMATCH;
38874
38875 /* Check if the current value would match the new type */
38876 UA_DataValue value;
38877 UA_DataValue_init(p: &value);
38878 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
38879 if(retval != UA_STATUSCODE_GOOD)
38880 return retval;
38881 if(value.hasValue) {
38882 const char *reason; /* temp value */
38883 if(!compatibleValue(server, session, targetDataTypeId: dataType, targetValueRank: node->valueRank,
38884 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
38885 value: &value.value, NULL, reason: &reason))
38886 retval = UA_STATUSCODE_BADTYPEMISMATCH;
38887 UA_DataValue_clear(p: &value);
38888 if(retval != UA_STATUSCODE_GOOD) {
38889 UA_LOG_DEBUG(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
38890 msg: "The current value does not match the new data type");
38891 return retval;
38892 }
38893 }
38894
38895 /* Replace the datatype nodeid */
38896 UA_NodeId dtCopy = node->dataType;
38897 retval = UA_NodeId_copy(src: dataType, dst: &node->dataType);
38898 if(retval != UA_STATUSCODE_GOOD) {
38899 node->dataType = dtCopy;
38900 return retval;
38901 }
38902 UA_NodeId_clear(p: &dtCopy);
38903 return UA_STATUSCODE_GOOD;
38904}
38905
38906static UA_StatusCode
38907writeValueAttributeWithoutRange(UA_VariableNode *node, const UA_DataValue *value) {
38908 UA_DataValue new_value;
38909 UA_StatusCode retval = UA_DataValue_copy(src: value, dst: &new_value);
38910 if(retval != UA_STATUSCODE_GOOD)
38911 return retval;
38912 UA_DataValue_clear(p: &node->value.data.value);
38913 node->value.data.value = new_value;
38914 return UA_STATUSCODE_GOOD;
38915}
38916
38917static UA_StatusCode
38918writeValueAttributeWithRange(UA_VariableNode *node, const UA_DataValue *value,
38919 const UA_NumericRange *rangeptr) {
38920 /* Value on both sides? */
38921 if(value->status != node->value.data.value.status ||
38922 !value->hasValue || !node->value.data.value.hasValue)
38923 return UA_STATUSCODE_BADINDEXRANGEINVALID;
38924
38925 /* Make scalar a one-entry array for range matching */
38926 UA_Variant editableValue;
38927 const UA_Variant *v = &value->value;
38928 if(UA_Variant_isScalar(v: &value->value)) {
38929 editableValue = value->value;
38930 editableValue.arrayLength = 1;
38931 v = &editableValue;
38932 }
38933
38934 /* Check that the type is an exact match and not only "compatible" */
38935 if(!node->value.data.value.value.type || !v->type ||
38936 !UA_NodeId_equal(n1: &node->value.data.value.value.type->typeId,
38937 n2: &v->type->typeId))
38938 return UA_STATUSCODE_BADTYPEMISMATCH;
38939
38940 /* Write the value */
38941 UA_StatusCode retval =
38942 UA_Variant_setRangeCopy(v: &node->value.data.value.value,
38943 array: v->data, arraySize: v->arrayLength, range: *rangeptr);
38944 if(retval != UA_STATUSCODE_GOOD)
38945 return retval;
38946
38947 /* Write the status and timestamps */
38948 node->value.data.value.hasStatus = value->hasStatus;
38949 node->value.data.value.status = value->status;
38950 node->value.data.value.hasSourceTimestamp = value->hasSourceTimestamp;
38951 node->value.data.value.sourceTimestamp = value->sourceTimestamp;
38952 node->value.data.value.hasSourcePicoseconds = value->hasSourcePicoseconds;
38953 node->value.data.value.sourcePicoseconds = value->sourcePicoseconds;
38954 return UA_STATUSCODE_GOOD;
38955}
38956
38957/* Stack layout: ... | node */
38958static UA_StatusCode
38959writeNodeValueAttribute(UA_Server *server, UA_Session *session,
38960 UA_VariableNode *node, const UA_DataValue *value,
38961 const UA_String *indexRange) {
38962 UA_assert(node != NULL);
38963 UA_assert(session != NULL);
38964
38965 /* Parse the range */
38966 UA_NumericRange range;
38967 range.dimensions = NULL;
38968 UA_NumericRange *rangeptr = NULL;
38969 UA_StatusCode retval = UA_STATUSCODE_GOOD;
38970 if(indexRange && indexRange->length > 0) {
38971 retval = UA_NumericRange_parse(range: &range, str: *indexRange);
38972 if(retval != UA_STATUSCODE_GOOD)
38973 return retval;
38974 rangeptr = &range;
38975 }
38976
38977 /* Created an editable version. The data is not touched. Only the variant
38978 * "container". */
38979 UA_DataValue adjustedValue = *value;
38980
38981 /* Type checking. May change the type of editableValue */
38982 if(value->hasValue && value->value.type) {
38983 adjustValueType(server, value: &adjustedValue.value, targetDataTypeId: &node->dataType);
38984
38985 /* The value may be an extension object, especially the nodeset compiler
38986 * uses extension objects to write variable values. If value is an
38987 * extension object we check if the current node value is also an
38988 * extension object. */
38989 const UA_NodeId nodeDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE);
38990 const UA_NodeId *nodeDataTypePtr = &node->dataType;
38991 if(value->value.type->typeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
38992 value->value.type->typeId.identifier.numeric == UA_NS0ID_STRUCTURE)
38993 nodeDataTypePtr = &nodeDataType;
38994
38995 const char *reason;
38996 if(!compatibleValue(server, session, targetDataTypeId: nodeDataTypePtr, targetValueRank: node->valueRank,
38997 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
38998 value: &adjustedValue.value, range: rangeptr, reason: &reason)) {
38999 UA_LOG_NODEID_WARNING(&node->head.nodeId,
39000 if(session == &server->adminSession) {
39001 /* If the value is written via the local API, log a warning */
39002 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
39003 "Writing the value of Node %.*s failed with the "
39004 "following reason: %s",
39005 (int)nodeIdStr.length, nodeIdStr.data, reason);
39006 } else {
39007 /* Don't spam the logs if writing from remote failed */
39008 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39009 "Writing the value of Node %.*s failed with the "
39010 "following reason: %s",
39011 (int)nodeIdStr.length, nodeIdStr.data, reason);
39012 });
39013 if(rangeptr && rangeptr->dimensions != NULL)
39014 UA_free(ptr: rangeptr->dimensions);
39015 return UA_STATUSCODE_BADTYPEMISMATCH;
39016 }
39017 }
39018
39019 /* Set the source timestamp if there is none */
39020 UA_DateTime now = UA_DateTime_now();
39021 if(!adjustedValue.hasSourceTimestamp) {
39022 adjustedValue.sourceTimestamp = now;
39023 adjustedValue.hasSourceTimestamp = true;
39024 }
39025
39026 /* Update the timestamp when the value was last updated in the server */
39027 adjustedValue.serverTimestamp = now;
39028 adjustedValue.hasServerTimestamp = true;
39029
39030 switch(node->valueBackend.backendType) {
39031 case UA_VALUEBACKENDTYPE_NONE:
39032 /* Ok, do it */
39033 if(node->valueSource == UA_VALUESOURCE_DATA) {
39034 if(!rangeptr)
39035 retval = writeValueAttributeWithoutRange(node, value: &adjustedValue);
39036 else
39037 retval = writeValueAttributeWithRange(node, value: &adjustedValue, rangeptr);
39038
39039#ifdef UA_ENABLE_HISTORIZING
39040 /* node is a UA_VariableNode*, but it may also point to a
39041 UA_VariableTypeNode */
39042 /* UA_VariableTypeNode doesn't have the historizing attribute */
39043 if(retval == UA_STATUSCODE_GOOD &&
39044 node->head.nodeClass == UA_NODECLASS_VARIABLE &&
39045 server->config.historyDatabase.setValue) {
39046 UA_UNLOCK(&server->serviceMutex);
39047 server->config.historyDatabase.
39048 setValue(server, server->config.historyDatabase.context,
39049 &session->sessionId, session->sessionHandle,
39050 &node->head.nodeId, node->historizing, &adjustedValue);
39051 UA_LOCK(&server->serviceMutex);
39052 }
39053#endif
39054 /* Callback after writing */
39055 if(retval == UA_STATUSCODE_GOOD && node->value.data.callback.onWrite) {
39056 UA_UNLOCK(&server->serviceMutex);
39057 node->value.data.callback.
39058 onWrite(server, &session->sessionId, session->sessionHandle,
39059 &node->head.nodeId, node->head.context,
39060 rangeptr, &adjustedValue);
39061 UA_LOCK(&server->serviceMutex);
39062
39063 }
39064 } else {
39065 if(node->value.dataSource.write) {
39066 UA_UNLOCK(&server->serviceMutex);
39067 retval = node->value.dataSource.
39068 write(server, &session->sessionId, session->sessionHandle,
39069 &node->head.nodeId, node->head.context,
39070 rangeptr, &adjustedValue);
39071 UA_LOCK(&server->serviceMutex);
39072 } else {
39073 retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
39074 }
39075 }
39076 break;
39077 case UA_VALUEBACKENDTYPE_INTERNAL:
39078 break;
39079 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
39080 break;
39081 case UA_VALUEBACKENDTYPE_EXTERNAL:
39082 if(node->valueBackend.backend.external.callback.userWrite == NULL){
39083 if(rangeptr && rangeptr->dimensions != NULL)
39084 UA_free(ptr: rangeptr->dimensions);
39085 return UA_STATUSCODE_BADWRITENOTSUPPORTED;
39086 }
39087 retval = node->valueBackend.backend.external.callback.
39088 userWrite(server, &session->sessionId, session->sessionHandle,
39089 &node->head.nodeId, node->head.context,
39090 rangeptr, &adjustedValue);
39091 break;
39092 }
39093
39094 /* Clean up */
39095 if(rangeptr && rangeptr->dimensions != NULL)
39096 UA_free(ptr: rangeptr->dimensions);
39097 return retval;
39098}
39099
39100static UA_StatusCode
39101writeIsAbstractAttribute(UA_Node *node, UA_Boolean value) {
39102 switch(node->head.nodeClass) {
39103 case UA_NODECLASS_OBJECTTYPE:
39104 node->objectTypeNode.isAbstract = value;
39105 break;
39106 case UA_NODECLASS_REFERENCETYPE:
39107 node->referenceTypeNode.isAbstract = value;
39108 break;
39109 case UA_NODECLASS_VARIABLETYPE:
39110 node->variableTypeNode.isAbstract = value;
39111 break;
39112 case UA_NODECLASS_DATATYPE:
39113 node->dataTypeNode.isAbstract = value;
39114 break;
39115 default:
39116 return UA_STATUSCODE_BADNODECLASSINVALID;
39117 }
39118 return UA_STATUSCODE_GOOD;
39119}
39120
39121/*****************/
39122/* Write Service */
39123/*****************/
39124
39125#define CHECK_DATATYPE_SCALAR(EXP_DT) \
39126 if(!wvalue->value.hasValue || \
39127 &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
39128 !UA_Variant_isScalar(&wvalue->value.value)) { \
39129 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39130 break; \
39131 }
39132
39133#define CHECK_DATATYPE_ARRAY(EXP_DT) \
39134 if(!wvalue->value.hasValue || \
39135 &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \
39136 UA_Variant_isScalar(&wvalue->value.value)) { \
39137 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39138 break; \
39139 }
39140
39141#define CHECK_NODECLASS_WRITE(CLASS) \
39142 if((node->head.nodeClass & (CLASS)) == 0) { \
39143 retval = UA_STATUSCODE_BADNODECLASSINVALID; \
39144 break; \
39145 }
39146
39147#define CHECK_USERWRITEMASK(mask) \
39148 if(!(userWriteMask & (mask))) { \
39149 retval = UA_STATUSCODE_BADUSERACCESSDENIED; \
39150 break; \
39151 }
39152
39153#define GET_NODETYPE \
39154 type = (const UA_VariableTypeNode*) \
39155 getNodeType(server, &node->head); \
39156 if(!type) { \
39157 retval = UA_STATUSCODE_BADTYPEMISMATCH; \
39158 break; \
39159 }
39160
39161/* Update a localized text. Don't touch the target if copying fails
39162 * (maybe due to BadOutOfMemory). */
39163static UA_StatusCode
39164updateLocalizedText(const UA_LocalizedText *source, UA_LocalizedText *target) {
39165 UA_LocalizedText tmp;
39166 UA_StatusCode retval = UA_LocalizedText_copy(src: source, dst: &tmp);
39167 if(retval != UA_STATUSCODE_GOOD)
39168 return retval;
39169 UA_LocalizedText_clear(p: target);
39170 *target = tmp;
39171 return UA_STATUSCODE_GOOD;
39172}
39173
39174/* Trigger sampling if a MonitoredItem surveils the attribute with no sampling
39175 * interval */
39176#ifdef UA_ENABLE_SUBSCRIPTIONS
39177static void
39178triggerImmediateDataChange(UA_Server *server, UA_Session *session,
39179 UA_Node *node, const UA_WriteValue *wvalue) {
39180 UA_MonitoredItem *mon = node->head.monitoredItems;
39181 for(; mon != NULL; mon = mon->sampling.nodeListNext) {
39182 if(mon->itemToMonitor.attributeId != wvalue->attributeId)
39183 continue;
39184 UA_DataValue value;
39185 UA_DataValue_init(p: &value);
39186 ReadWithNode(node, server, session, timestampsToReturn: mon->timestampsToReturn,
39187 id: &mon->itemToMonitor, v: &value);
39188 UA_Subscription *sub = mon->subscription;
39189 UA_StatusCode res = sampleCallbackWithValue(server, sub, mon, value: &value);
39190 if(res != UA_STATUSCODE_GOOD) {
39191 UA_DataValue_clear(p: &value);
39192 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
39193 "MonitoredItem %" PRIi32 " | "
39194 "Sampling returned the statuscode %s",
39195 mon->monitoredItemId,
39196 UA_StatusCode_name(res));
39197 }
39198 }
39199}
39200#endif
39201
39202/* This function implements the main part of the write service and operates on a
39203 copy of the node (not in single-threaded mode). */
39204static UA_StatusCode
39205copyAttributeIntoNode(UA_Server *server, UA_Session *session,
39206 UA_Node *node, const UA_WriteValue *wvalue) {
39207 UA_assert(session != NULL);
39208 const void *value = wvalue->value.value.data;
39209 UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head);
39210 UA_StatusCode retval = UA_STATUSCODE_GOOD;
39211
39212 UA_LOG_NODEID_DEBUG(&node->head.nodeId,
39213 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39214 "Write attribute %"PRIi32 " of Node %.*s",
39215 wvalue->attributeId, (int)nodeIdStr.length,
39216 nodeIdStr.data));
39217
39218 const UA_VariableTypeNode *type;
39219
39220 switch(wvalue->attributeId) {
39221 case UA_ATTRIBUTEID_NODEID:
39222 case UA_ATTRIBUTEID_NODECLASS:
39223 case UA_ATTRIBUTEID_USERWRITEMASK:
39224 case UA_ATTRIBUTEID_USERACCESSLEVEL:
39225 case UA_ATTRIBUTEID_USEREXECUTABLE:
39226 case UA_ATTRIBUTEID_BROWSENAME: /* BrowseName is tracked in a binary tree
39227 for fast lookup */
39228 retval = UA_STATUSCODE_BADWRITENOTSUPPORTED;
39229 break;
39230 case UA_ATTRIBUTEID_DISPLAYNAME:
39231 CHECK_USERWRITEMASK(UA_WRITEMASK_DISPLAYNAME);
39232 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39233 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39234 target: &node->head.displayName);
39235 break;
39236 case UA_ATTRIBUTEID_DESCRIPTION:
39237 CHECK_USERWRITEMASK(UA_WRITEMASK_DESCRIPTION);
39238 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39239 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39240 target: &node->head.description);
39241 break;
39242 case UA_ATTRIBUTEID_WRITEMASK:
39243 CHECK_USERWRITEMASK(UA_WRITEMASK_WRITEMASK);
39244 CHECK_DATATYPE_SCALAR(UINT32);
39245 node->head.writeMask = *(const UA_UInt32*)value;
39246 break;
39247 case UA_ATTRIBUTEID_ISABSTRACT:
39248 CHECK_USERWRITEMASK(UA_WRITEMASK_ISABSTRACT);
39249 CHECK_DATATYPE_SCALAR(BOOLEAN);
39250 retval = writeIsAbstractAttribute(node, value: *(const UA_Boolean*)value);
39251 break;
39252 case UA_ATTRIBUTEID_SYMMETRIC:
39253 CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
39254 CHECK_USERWRITEMASK(UA_WRITEMASK_SYMMETRIC);
39255 CHECK_DATATYPE_SCALAR(BOOLEAN);
39256 node->referenceTypeNode.symmetric = *(const UA_Boolean*)value;
39257 break;
39258 case UA_ATTRIBUTEID_INVERSENAME:
39259 CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE);
39260 CHECK_USERWRITEMASK(UA_WRITEMASK_INVERSENAME);
39261 CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT);
39262 retval = updateLocalizedText(source: (const UA_LocalizedText *)value,
39263 target: &node->referenceTypeNode.inverseName);
39264 break;
39265 case UA_ATTRIBUTEID_CONTAINSNOLOOPS:
39266 CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW);
39267 CHECK_USERWRITEMASK(UA_WRITEMASK_CONTAINSNOLOOPS);
39268 CHECK_DATATYPE_SCALAR(BOOLEAN);
39269 node->viewNode.containsNoLoops = *(const UA_Boolean*)value;
39270 break;
39271 case UA_ATTRIBUTEID_EVENTNOTIFIER:
39272 CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT);
39273 CHECK_USERWRITEMASK(UA_WRITEMASK_EVENTNOTIFIER);
39274 CHECK_DATATYPE_SCALAR(BYTE);
39275 if(node->head.nodeClass == UA_NODECLASS_VIEW) {
39276 node->viewNode.eventNotifier = *(const UA_Byte*)value;
39277 } else {
39278 node->objectNode.eventNotifier = *(const UA_Byte*)value;
39279 }
39280 break;
39281 case UA_ATTRIBUTEID_VALUE:
39282 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39283 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
39284 /* The access to a value variable is granted via the AccessLevel
39285 * and UserAccessLevel attributes */
39286 UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode);
39287 if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
39288 retval = UA_STATUSCODE_BADNOTWRITABLE;
39289 break;
39290 }
39291 accessLevel = getUserAccessLevel(server, session, node: &node->variableNode);
39292 if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) {
39293 retval = UA_STATUSCODE_BADUSERACCESSDENIED;
39294 break;
39295 }
39296 } else { /* UA_NODECLASS_VARIABLETYPE */
39297 CHECK_USERWRITEMASK(UA_WRITEMASK_VALUEFORVARIABLETYPE);
39298 }
39299 retval = writeNodeValueAttribute(server, session, node: &node->variableNode,
39300 value: &wvalue->value, indexRange: &wvalue->indexRange);
39301 break;
39302 case UA_ATTRIBUTEID_DATATYPE:
39303 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39304 CHECK_USERWRITEMASK(UA_WRITEMASK_DATATYPE);
39305 CHECK_DATATYPE_SCALAR(NODEID);
39306 GET_NODETYPE;
39307 retval = writeDataTypeAttribute(server, session, node: &node->variableNode,
39308 type, dataType: (const UA_NodeId*)value);
39309 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39310 break;
39311 case UA_ATTRIBUTEID_VALUERANK:
39312 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39313 CHECK_USERWRITEMASK(UA_WRITEMASK_VALUERANK);
39314 CHECK_DATATYPE_SCALAR(INT32);
39315 GET_NODETYPE;
39316 retval = writeValueRankAttribute(server, session, node: &node->variableNode,
39317 type, valueRank: *(const UA_Int32*)value);
39318 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39319 break;
39320 case UA_ATTRIBUTEID_ARRAYDIMENSIONS:
39321 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE);
39322 CHECK_USERWRITEMASK(UA_WRITEMASK_ARRRAYDIMENSIONS);
39323 CHECK_DATATYPE_ARRAY(UINT32);
39324 GET_NODETYPE;
39325 retval = writeArrayDimensionsAttribute(server, session, node: &node->variableNode,
39326 type, arrayDimensionsSize: wvalue->value.value.arrayLength,
39327 arrayDimensions: (UA_UInt32 *)wvalue->value.value.data);
39328 UA_NODESTORE_RELEASE(server, (const UA_Node*)type);
39329 break;
39330 case UA_ATTRIBUTEID_ACCESSLEVEL:
39331 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39332 CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVEL);
39333 CHECK_DATATYPE_SCALAR(BYTE);
39334 node->variableNode.accessLevel = *(const UA_Byte*)value;
39335 break;
39336 case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL:
39337 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39338 CHECK_USERWRITEMASK(UA_WRITEMASK_MINIMUMSAMPLINGINTERVAL);
39339 CHECK_DATATYPE_SCALAR(DOUBLE);
39340 node->variableNode.minimumSamplingInterval = *(const UA_Double*)value;
39341 break;
39342 case UA_ATTRIBUTEID_HISTORIZING:
39343 CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE);
39344 CHECK_USERWRITEMASK(UA_WRITEMASK_HISTORIZING);
39345 CHECK_DATATYPE_SCALAR(BOOLEAN);
39346 node->variableNode.historizing = *(const UA_Boolean*)value;
39347 break;
39348 case UA_ATTRIBUTEID_EXECUTABLE:
39349 CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD);
39350 CHECK_USERWRITEMASK(UA_WRITEMASK_EXECUTABLE);
39351 CHECK_DATATYPE_SCALAR(BOOLEAN);
39352 node->methodNode.executable = *(const UA_Boolean*)value;
39353 break;
39354 default:
39355 retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
39356 break;
39357 }
39358
39359 /* Check if writing succeeded */
39360 if(retval != UA_STATUSCODE_GOOD) {
39361 UA_LOG_INFO_SESSION(&server->config.logger, session,
39362 "WriteRequest returned status code %s",
39363 UA_StatusCode_name(retval));
39364 return retval;
39365 }
39366
39367 /* Trigger MonitoredItems with no SamplingInterval */
39368#ifdef UA_ENABLE_SUBSCRIPTIONS
39369 triggerImmediateDataChange(server, session, node, wvalue);
39370#endif
39371
39372 return UA_STATUSCODE_GOOD;
39373}
39374
39375static void
39376Operation_Write(UA_Server *server, UA_Session *session, void *context,
39377 const UA_WriteValue *wv, UA_StatusCode *result) {
39378 UA_assert(session != NULL);
39379 *result = UA_Server_editNode(server, session, nodeId: &wv->nodeId,
39380 callback: (UA_EditNodeCallback)copyAttributeIntoNode,
39381 data: (void*)(uintptr_t)wv);
39382}
39383
39384void
39385Service_Write(UA_Server *server, UA_Session *session,
39386 const UA_WriteRequest *request,
39387 UA_WriteResponse *response) {
39388 UA_assert(session != NULL);
39389 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39390 "Processing WriteRequest");
39391 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39392
39393 if(server->config.maxNodesPerWrite != 0 &&
39394 request->nodesToWriteSize > server->config.maxNodesPerWrite) {
39395 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
39396 return;
39397 }
39398
39399 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39400
39401 response->responseHeader.serviceResult =
39402 UA_Server_processServiceOperations(server, session,
39403 operationCallback: (UA_ServiceOperation)Operation_Write, NULL,
39404 requestOperations: &request->nodesToWriteSize,
39405 requestOperationsType: &UA_TYPES[UA_TYPES_WRITEVALUE],
39406 responseOperations: &response->resultsSize,
39407 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
39408}
39409
39410UA_StatusCode
39411UA_Server_write(UA_Server *server, const UA_WriteValue *value) {
39412 UA_StatusCode res = UA_STATUSCODE_GOOD;
39413 UA_LOCK(&server->serviceMutex);
39414 Operation_Write(server, session: &server->adminSession, NULL, wv: value, result: &res);
39415 UA_UNLOCK(&server->serviceMutex);
39416 return res;
39417}
39418
39419/* Convenience function to be wrapped into inline functions */
39420UA_StatusCode
39421__UA_Server_write(UA_Server *server, const UA_NodeId *nodeId,
39422 const UA_AttributeId attributeId,
39423 const UA_DataType *attr_type, const void *attr) {
39424 UA_LOCK(&server->serviceMutex);
39425 UA_StatusCode res = writeAttribute(server, session: &server->adminSession,
39426 nodeId, attributeId, attr, attr_type);
39427 UA_UNLOCK(&server->serviceMutex);
39428 return res;
39429}
39430
39431/* Internal convenience function */
39432UA_StatusCode
39433writeAttribute(UA_Server *server, UA_Session *session,
39434 const UA_NodeId *nodeId, const UA_AttributeId attributeId,
39435 const void *attr, const UA_DataType *attr_type) {
39436 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39437
39438 UA_WriteValue wvalue;
39439 UA_WriteValue_init(p: &wvalue);
39440 wvalue.nodeId = *nodeId;
39441 wvalue.attributeId = attributeId;
39442 wvalue.value.hasValue = true;
39443 if(attr_type == &UA_TYPES[UA_TYPES_VARIANT]) {
39444 wvalue.value.value = *(const UA_Variant*)attr;
39445 } else if(attr_type == &UA_TYPES[UA_TYPES_DATAVALUE]) {
39446 wvalue.value = *(const UA_DataValue*)attr;
39447 } else {
39448 /* hacked cast. the target WriteValue is used as const anyway */
39449 UA_Variant_setScalar(v: &wvalue.value.value,
39450 p: (void*)(uintptr_t)attr, type: attr_type);
39451 }
39452
39453 UA_StatusCode res = UA_STATUSCODE_GOOD;
39454 Operation_Write(server, session, NULL, wv: &wvalue, result: &res);
39455 return res;
39456}
39457
39458#ifdef UA_ENABLE_HISTORIZING
39459typedef void
39460 (*UA_HistoryDatabase_readFunc)(UA_Server *server, void *hdbContext,
39461 const UA_NodeId *sessionId, void *sessionContext,
39462 const UA_RequestHeader *requestHeader,
39463 const void *historyReadDetails,
39464 UA_TimestampsToReturn timestampsToReturn,
39465 UA_Boolean releaseContinuationPoints,
39466 size_t nodesToReadSize,
39467 const UA_HistoryReadValueId *nodesToRead,
39468 UA_HistoryReadResponse *response,
39469 void * const * const historyData);
39470
39471void
39472Service_HistoryRead(UA_Server *server, UA_Session *session,
39473 const UA_HistoryReadRequest *request,
39474 UA_HistoryReadResponse *response) {
39475 UA_assert(session != NULL);
39476 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39477 if(server->config.historyDatabase.context == NULL) {
39478 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
39479 return;
39480 }
39481
39482 if(request->historyReadDetails.encoding != UA_EXTENSIONOBJECT_DECODED) {
39483 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED;
39484 return;
39485 }
39486
39487 const UA_DataType *historyDataType = &UA_TYPES[UA_TYPES_HISTORYDATA];
39488 UA_HistoryDatabase_readFunc readHistory = NULL;
39489 if(request->historyReadDetails.content.decoded.type ==
39490 &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]) {
39491 UA_ReadRawModifiedDetails *details = (UA_ReadRawModifiedDetails*)
39492 request->historyReadDetails.content.decoded.data;
39493 if(!details->isReadModified) {
39494 readHistory = (UA_HistoryDatabase_readFunc)
39495 server->config.historyDatabase.readRaw;
39496 } else {
39497 historyDataType = &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA];
39498 readHistory = (UA_HistoryDatabase_readFunc)
39499 server->config.historyDatabase.readModified;
39500 }
39501 } else if(request->historyReadDetails.content.decoded.type ==
39502 &UA_TYPES[UA_TYPES_READEVENTDETAILS]) {
39503 historyDataType = &UA_TYPES[UA_TYPES_HISTORYEVENT];
39504 readHistory = (UA_HistoryDatabase_readFunc)
39505 server->config.historyDatabase.readEvent;
39506 } else if(request->historyReadDetails.content.decoded.type ==
39507 &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]) {
39508 readHistory = (UA_HistoryDatabase_readFunc)
39509 server->config.historyDatabase.readProcessed;
39510 } else if(request->historyReadDetails.content.decoded.type ==
39511 &UA_TYPES[UA_TYPES_READATTIMEDETAILS]) {
39512 readHistory = (UA_HistoryDatabase_readFunc)
39513 server->config.historyDatabase.readAtTime;
39514 } else {
39515 /* TODO handle more request->historyReadDetails.content.decoded.type types */
39516 response->responseHeader.serviceResult = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
39517 return;
39518 }
39519
39520 /* Something to do? */
39521 if(request->nodesToReadSize == 0) {
39522 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
39523 return;
39524 }
39525
39526 /* Check if there are too many operations */
39527 if(server->config.maxNodesPerRead != 0 &&
39528 request->nodesToReadSize > server->config.maxNodesPerRead) {
39529 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
39530 return;
39531 }
39532
39533 /* Allocate a temporary array to forward the result pointers to the
39534 * backend */
39535 void **historyData = (void **)
39536 UA_calloc(nmemb: request->nodesToReadSize, size: sizeof(void*));
39537 if(!historyData) {
39538 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39539 return;
39540 }
39541
39542 /* Allocate the results array */
39543 response->results = (UA_HistoryReadResult*)
39544 UA_Array_new(size: request->nodesToReadSize, type: &UA_TYPES[UA_TYPES_HISTORYREADRESULT]);
39545 if(!response->results) {
39546 UA_free(ptr: historyData);
39547 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39548 return;
39549 }
39550 response->resultsSize = request->nodesToReadSize;
39551
39552 for(size_t i = 0; i < response->resultsSize; ++i) {
39553 void * data = UA_new(type: historyDataType);
39554 UA_ExtensionObject_setValue(eo: &response->results[i].historyData,
39555 p: data, type: historyDataType);
39556 historyData[i] = data;
39557 }
39558 UA_UNLOCK(&server->serviceMutex);
39559 readHistory(server, server->config.historyDatabase.context,
39560 &session->sessionId, session->sessionHandle,
39561 &request->requestHeader,
39562 request->historyReadDetails.content.decoded.data,
39563 request->timestampsToReturn,
39564 request->releaseContinuationPoints,
39565 request->nodesToReadSize, request->nodesToRead,
39566 response, historyData);
39567 UA_LOCK(&server->serviceMutex);
39568 UA_free(ptr: historyData);
39569}
39570
39571void
39572Service_HistoryUpdate(UA_Server *server, UA_Session *session,
39573 const UA_HistoryUpdateRequest *request,
39574 UA_HistoryUpdateResponse *response) {
39575 UA_assert(session != NULL);
39576 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39577
39578 response->resultsSize = request->historyUpdateDetailsSize;
39579 response->results = (UA_HistoryUpdateResult*)
39580 UA_Array_new(size: response->resultsSize, type: &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]);
39581 if(!response->results) {
39582 response->resultsSize = 0;
39583 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39584 return;
39585 }
39586
39587 for(size_t i = 0; i < request->historyUpdateDetailsSize; ++i) {
39588 UA_HistoryUpdateResult_init(p: &response->results[i]);
39589 if(request->historyUpdateDetails[i].encoding != UA_EXTENSIONOBJECT_DECODED) {
39590 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39591 continue;
39592 }
39593
39594 const UA_DataType *updateDetailsType =
39595 request->historyUpdateDetails[i].content.decoded.type;
39596 void *updateDetailsData = request->historyUpdateDetails[i].content.decoded.data;
39597
39598 if(updateDetailsType == &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]) {
39599 if(!server->config.historyDatabase.updateData) {
39600 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39601 continue;
39602 }
39603 UA_UNLOCK(&server->serviceMutex);
39604 server->config.historyDatabase.
39605 updateData(server, server->config.historyDatabase.context,
39606 &session->sessionId, session->sessionHandle,
39607 &request->requestHeader,
39608 (UA_UpdateDataDetails*)updateDetailsData,
39609 &response->results[i]);
39610 UA_LOCK(&server->serviceMutex);
39611 continue;
39612 }
39613
39614 if(updateDetailsType == &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]) {
39615 if(!server->config.historyDatabase.deleteRawModified) {
39616 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39617 continue;
39618 }
39619 UA_UNLOCK(&server->serviceMutex);
39620 server->config.historyDatabase.
39621 deleteRawModified(server, server->config.historyDatabase.context,
39622 &session->sessionId, session->sessionHandle,
39623 &request->requestHeader,
39624 (UA_DeleteRawModifiedDetails*)updateDetailsData,
39625 &response->results[i]);
39626 UA_LOCK(&server->serviceMutex);
39627 continue;
39628 }
39629
39630 response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
39631 }
39632}
39633
39634#endif
39635
39636UA_StatusCode
39637UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
39638 const UA_QualifiedName propertyName,
39639 const UA_Variant value) {
39640 UA_LOCK(&server->serviceMutex);
39641 UA_StatusCode retVal = writeObjectProperty(server, objectId, propertyName, value);
39642 UA_UNLOCK(&server->serviceMutex);
39643 return retVal;
39644}
39645
39646UA_StatusCode
39647writeObjectProperty(UA_Server *server, const UA_NodeId objectId,
39648 const UA_QualifiedName propertyName,
39649 const UA_Variant value) {
39650 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39651 UA_RelativePathElement rpe;
39652 UA_RelativePathElement_init(p: &rpe);
39653 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
39654 rpe.isInverse = false;
39655 rpe.includeSubtypes = false;
39656 rpe.targetName = propertyName;
39657
39658 UA_BrowsePath bp;
39659 UA_BrowsePath_init(p: &bp);
39660 bp.startingNode = objectId;
39661 bp.relativePath.elementsSize = 1;
39662 bp.relativePath.elements = &rpe;
39663
39664 UA_StatusCode retval;
39665 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
39666 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
39667 retval = bpr.statusCode;
39668 UA_BrowsePathResult_clear(p: &bpr);
39669 return retval;
39670 }
39671
39672 retval = writeValueAttribute(server, session: &server->adminSession,
39673 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
39674
39675 UA_BrowsePathResult_clear(p: &bpr);
39676 return retval;
39677}
39678
39679UA_StatusCode UA_EXPORT
39680UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId,
39681 const UA_QualifiedName propertyName,
39682 const void *value, const UA_DataType *type) {
39683 UA_Variant var;
39684 UA_Variant_init(p: &var);
39685 UA_Variant_setScalar(v: &var, p: (void*)(uintptr_t)value, type);
39686 UA_LOCK(&server->serviceMutex);
39687 UA_StatusCode retval = writeObjectProperty(server, objectId, propertyName, value: var);
39688 UA_UNLOCK(&server->serviceMutex);
39689 return retval;
39690}
39691
39692/**** amalgamated original file "/src/server/ua_services_discovery.c" ****/
39693
39694/* This Source Code Form is subject to the terms of the Mozilla Public
39695 * License, v. 2.0. If a copy of the MPL was not distributed with this
39696 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
39697 *
39698 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
39699 * Copyright 2014-2016 (c) Sten Grüner
39700 * Copyright 2014, 2017 (c) Florian Palm
39701 * Copyright 2016 (c) Oleksiy Vasylyev
39702 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
39703 * Copyright 2017 (c) frax2222
39704 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
39705 */
39706
39707
39708#ifdef UA_ENABLE_DISCOVERY
39709
39710
39711static UA_StatusCode
39712setApplicationDescriptionFromRegisteredServer(const UA_FindServersRequest *request,
39713 UA_ApplicationDescription *target,
39714 const UA_RegisteredServer *registeredServer) {
39715 UA_ApplicationDescription_init(target);
39716 UA_StatusCode retval = UA_String_copy(&registeredServer->serverUri, &target->applicationUri);
39717 if(retval != UA_STATUSCODE_GOOD)
39718 return retval;
39719
39720 retval = UA_String_copy(&registeredServer->productUri, &target->productUri);
39721 if(retval != UA_STATUSCODE_GOOD)
39722 return retval;
39723
39724 // if the client requests a specific locale, select the corresponding server name
39725 if(request->localeIdsSize) {
39726 UA_Boolean appNameFound = false;
39727 for(size_t i =0; i<request->localeIdsSize && !appNameFound; i++) {
39728 for(size_t j =0; j<registeredServer->serverNamesSize; j++) {
39729 if(UA_String_equal(&request->localeIds[i], &registeredServer->serverNames[j].locale)) {
39730 retval = UA_LocalizedText_copy(&registeredServer->serverNames[j],
39731 &target->applicationName);
39732 if(retval != UA_STATUSCODE_GOOD)
39733 return retval;
39734 appNameFound = true;
39735 break;
39736 }
39737 }
39738 }
39739
39740 // server does not have the requested local, therefore we can select the
39741 // most suitable one
39742 if(!appNameFound && registeredServer->serverNamesSize) {
39743 retval = UA_LocalizedText_copy(&registeredServer->serverNames[0],
39744 &target->applicationName);
39745 if(retval != UA_STATUSCODE_GOOD)
39746 return retval;
39747 }
39748 } else if(registeredServer->serverNamesSize) {
39749 // just take the first name
39750 retval = UA_LocalizedText_copy(&registeredServer->serverNames[0], &target->applicationName);
39751 if(retval != UA_STATUSCODE_GOOD)
39752 return retval;
39753 }
39754
39755 target->applicationType = registeredServer->serverType;
39756 retval = UA_String_copy(&registeredServer->gatewayServerUri, &target->gatewayServerUri);
39757 if(retval != UA_STATUSCODE_GOOD)
39758 return retval;
39759 // TODO where do we get the discoveryProfileUri for application data?
39760
39761 target->discoveryUrlsSize = registeredServer->discoveryUrlsSize;
39762 if(registeredServer->discoveryUrlsSize) {
39763 size_t duSize = sizeof(UA_String) * registeredServer->discoveryUrlsSize;
39764 target->discoveryUrls = (UA_String *)UA_malloc(duSize);
39765 if(!target->discoveryUrls)
39766 return UA_STATUSCODE_BADOUTOFMEMORY;
39767 for(size_t i = 0; i < registeredServer->discoveryUrlsSize; i++) {
39768 retval = UA_String_copy(&registeredServer->discoveryUrls[i], &target->discoveryUrls[i]);
39769 if(retval != UA_STATUSCODE_GOOD)
39770 return retval;
39771 }
39772 }
39773
39774 return retval;
39775}
39776#endif
39777
39778static UA_StatusCode
39779setApplicationDescriptionFromServer(UA_ApplicationDescription *target, const UA_Server *server) {
39780 /* Copy ApplicationDescription from the config */
39781 UA_StatusCode result = UA_ApplicationDescription_copy(src: &server->config.applicationDescription, dst: target);
39782 if(result != UA_STATUSCODE_GOOD)
39783 return result;
39784
39785 /* Add the discoveryUrls from the networklayers only if discoveryUrl
39786 * not already present and to avoid redundancy */
39787 if(!target->discoveryUrlsSize) {
39788 size_t discSize = sizeof(UA_String) * (target->discoveryUrlsSize + server->config.networkLayersSize);
39789 UA_String* disc = (UA_String *)UA_realloc(ptr: target->discoveryUrls, size: discSize);
39790 if(!disc)
39791 return UA_STATUSCODE_BADOUTOFMEMORY;
39792 size_t existing = target->discoveryUrlsSize;
39793 target->discoveryUrls = disc;
39794 target->discoveryUrlsSize += server->config.networkLayersSize;
39795
39796 for(size_t i = 0; i < server->config.networkLayersSize; i++) {
39797 UA_ServerNetworkLayer* nl = &server->config.networkLayers[i];
39798 UA_String_copy(src: &nl->discoveryUrl, dst: &target->discoveryUrls[existing + i]);
39799 }
39800 }
39801
39802 return UA_STATUSCODE_GOOD;
39803}
39804
39805void Service_FindServers(UA_Server *server, UA_Session *session,
39806 const UA_FindServersRequest *request,
39807 UA_FindServersResponse *response) {
39808 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing FindServersRequest");
39809 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39810
39811 /* Return the server itself? */
39812 UA_Boolean foundSelf = false;
39813 if(request->serverUrisSize) {
39814 for(size_t i = 0; i < request->serverUrisSize; i++) {
39815 if(UA_String_equal(s1: &request->serverUris[i],
39816 s2: &server->config.applicationDescription.applicationUri)) {
39817 foundSelf = true;
39818 break;
39819 }
39820 }
39821 } else {
39822 foundSelf = true;
39823 }
39824
39825#ifndef UA_ENABLE_DISCOVERY
39826 if(!foundSelf)
39827 return;
39828
39829 UA_ApplicationDescription *ad = UA_ApplicationDescription_new();
39830 if(!ad) {
39831 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39832 return;
39833 }
39834
39835 UA_StatusCode retval = setApplicationDescriptionFromServer(target: ad, server);
39836 if(retval != UA_STATUSCODE_GOOD) {
39837 UA_ApplicationDescription_delete(p: ad);
39838 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39839 return;
39840 }
39841
39842 response->servers = ad;
39843 response->serversSize = 1;
39844 return;
39845
39846#else
39847
39848 /* Allocate enough memory, including memory for the "self" response */
39849 size_t maxResults = server->discoveryManager.registeredServersSize + 1;
39850 response->servers = (UA_ApplicationDescription*)UA_Array_new(maxResults, &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
39851 if(!response->servers) {
39852 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39853 return;
39854 }
39855
39856 /* Copy into the response. TODO: Evaluate return codes */
39857 size_t pos = 0;
39858 if(foundSelf)
39859 setApplicationDescriptionFromServer(&response->servers[pos++], server);
39860
39861 registeredServer_list_entry* current;
39862 LIST_FOREACH(current, &server->discoveryManager.registeredServers, pointers) {
39863 UA_Boolean usable = (request->serverUrisSize == 0);
39864 if(!usable) {
39865 /* If client only requested a specific set of servers */
39866 for(size_t i = 0; i < request->serverUrisSize; i++) {
39867 if(UA_String_equal(&current->registeredServer.serverUri, &request->serverUris[i])) {
39868 usable = true;
39869 break;
39870 }
39871 }
39872 }
39873
39874 if(usable)
39875 setApplicationDescriptionFromRegisteredServer(request, &response->servers[pos++],
39876 &current->registeredServer);
39877 }
39878
39879 /* Set the final size */
39880 if(pos > 0) {
39881 response->serversSize = pos;
39882 } else {
39883 UA_free(response->servers);
39884 response->servers = NULL;
39885 }
39886#endif
39887}
39888
39889void
39890Service_GetEndpoints(UA_Server *server, UA_Session *session,
39891 const UA_GetEndpointsRequest *request,
39892 UA_GetEndpointsResponse *response) {
39893 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39894
39895 /* If the client expects to see a specific endpointurl, mirror it back. If
39896 * not, clone the endpoints with the discovery url of all networklayers. */
39897 const UA_String *endpointUrl = &request->endpointUrl;
39898 if(endpointUrl->length > 0) {
39899 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39900 "Processing GetEndpointsRequest with endpointUrl "
39901 UA_PRINTF_STRING_FORMAT, UA_PRINTF_STRING_DATA(*endpointUrl));
39902 } else {
39903 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
39904 "Processing GetEndpointsRequest with an empty endpointUrl");
39905 }
39906
39907 /* Clone the endpoint for each networklayer? */
39908 size_t clone_times = 1;
39909 UA_Boolean nl_endpointurl = false;
39910 if(endpointUrl->length == 0) {
39911 clone_times = server->config.networkLayersSize;
39912 nl_endpointurl = true;
39913 }
39914
39915 /* Allocate enough memory */
39916 response->endpoints = (UA_EndpointDescription*)
39917 UA_Array_new(size: server->config.endpointsSize * clone_times,
39918 type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
39919 if(!response->endpoints) {
39920 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
39921 return;
39922 }
39923
39924 size_t pos = 0;
39925 UA_StatusCode retval = UA_STATUSCODE_GOOD;
39926 for(size_t j = 0; j < server->config.endpointsSize; ++j) {
39927 /* Test if the supported binary profile shall be returned */
39928 UA_Boolean usable = (request->profileUrisSize == 0);
39929 if(!usable) {
39930 for(size_t i = 0; i < request->profileUrisSize; ++i) {
39931 if(!UA_String_equal(s1: &request->profileUris[i],
39932 s2: &server->config.endpoints[j].transportProfileUri))
39933 continue;
39934 usable = true;
39935 break;
39936 }
39937 }
39938 if(!usable)
39939 continue;
39940
39941 /* Copy into the results */
39942 for(size_t i = 0; i < clone_times; ++i) {
39943 retval |= UA_EndpointDescription_copy(src: &server->config.endpoints[j],
39944 dst: &response->endpoints[pos]);
39945 UA_String_clear(p: &response->endpoints[pos].endpointUrl);
39946 UA_Array_delete(p: response->endpoints[pos].server.discoveryUrls,
39947 size: response->endpoints[pos].server.discoveryUrlsSize,
39948 type: &UA_TYPES[UA_TYPES_STRING]);
39949 response->endpoints[pos].server.discoveryUrls = NULL;
39950 response->endpoints[pos].server.discoveryUrlsSize = 0;
39951 if(nl_endpointurl)
39952 endpointUrl = &server->config.networkLayers[i].discoveryUrl;
39953 retval |= UA_String_copy(src: endpointUrl, dst: &response->endpoints[pos].endpointUrl);
39954 retval |= UA_Array_copy(src: endpointUrl, size: 1,
39955 dst: (void**)&response->endpoints[pos].server.discoveryUrls,
39956 type: &UA_TYPES[UA_TYPES_STRING]);
39957 if(retval != UA_STATUSCODE_GOOD)
39958 goto error;
39959 response->endpoints[pos].server.discoveryUrlsSize = 1;
39960 pos++;
39961 }
39962 }
39963
39964 UA_assert(pos <= server->config.endpointsSize * clone_times);
39965 response->endpointsSize = pos;
39966
39967 /* Clean up the memory of there are no usable results */
39968 if(pos > 0)
39969 return;
39970
39971error:
39972 response->responseHeader.serviceResult = retval;
39973 UA_Array_delete(p: response->endpoints, size: response->endpointsSize,
39974 type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]);
39975 response->endpoints = NULL;
39976 response->endpointsSize = 0;
39977}
39978
39979#ifdef UA_ENABLE_DISCOVERY
39980
39981static void
39982process_RegisterServer(UA_Server *server, UA_Session *session,
39983 const UA_RequestHeader* requestHeader,
39984 const UA_RegisteredServer *requestServer,
39985 const size_t requestDiscoveryConfigurationSize,
39986 const UA_ExtensionObject *requestDiscoveryConfiguration,
39987 UA_ResponseHeader* responseHeader,
39988 size_t *responseConfigurationResultsSize,
39989 UA_StatusCode **responseConfigurationResults,
39990 size_t *responseDiagnosticInfosSize,
39991 UA_DiagnosticInfo *responseDiagnosticInfos) {
39992 UA_LOCK_ASSERT(&server->serviceMutex, 1);
39993
39994 /* Find the server from the request in the registered list */
39995 registeredServer_list_entry* current;
39996 registeredServer_list_entry *registeredServer_entry = NULL;
39997 LIST_FOREACH(current, &server->discoveryManager.registeredServers, pointers) {
39998 if(UA_String_equal(&current->registeredServer.serverUri, &requestServer->serverUri)) {
39999 registeredServer_entry = current;
40000 break;
40001 }
40002 }
40003
40004 UA_MdnsDiscoveryConfiguration *mdnsConfig = NULL;
40005
40006 const UA_String* mdnsServerName = NULL;
40007 if(requestDiscoveryConfigurationSize) {
40008 *responseConfigurationResults =
40009 (UA_StatusCode *)UA_Array_new(requestDiscoveryConfigurationSize,
40010 &UA_TYPES[UA_TYPES_STATUSCODE]);
40011 if(!(*responseConfigurationResults)) {
40012 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40013 return;
40014 }
40015 *responseConfigurationResultsSize = requestDiscoveryConfigurationSize;
40016
40017 for(size_t i = 0; i < requestDiscoveryConfigurationSize; i++) {
40018 const UA_ExtensionObject *object = &requestDiscoveryConfiguration[i];
40019 if(!mdnsConfig && (object->encoding == UA_EXTENSIONOBJECT_DECODED ||
40020 object->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) &&
40021 (object->content.decoded.type == &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION])) {
40022 mdnsConfig = (UA_MdnsDiscoveryConfiguration *)object->content.decoded.data;
40023 mdnsServerName = &mdnsConfig->mdnsServerName;
40024 (*responseConfigurationResults)[i] = UA_STATUSCODE_GOOD;
40025 } else {
40026 (*responseConfigurationResults)[i] = UA_STATUSCODE_BADNOTSUPPORTED;
40027 }
40028 }
40029 }
40030
40031 if(!mdnsServerName && requestServer->serverNamesSize)
40032 mdnsServerName = &requestServer->serverNames[0].text;
40033
40034 if(!mdnsServerName) {
40035 responseHeader->serviceResult = UA_STATUSCODE_BADSERVERNAMEMISSING;
40036 return;
40037 }
40038
40039 if(requestServer->discoveryUrlsSize == 0) {
40040 responseHeader->serviceResult = UA_STATUSCODE_BADDISCOVERYURLMISSING;
40041 return;
40042 }
40043
40044 if(requestServer->semaphoreFilePath.length) {
40045#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
40046 char* filePath = (char*)
40047 UA_malloc(sizeof(char)*requestServer->semaphoreFilePath.length+1);
40048 if(!filePath) {
40049 UA_LOG_ERROR_SESSION(&server->config.logger, session,
40050 "Cannot allocate memory for semaphore path. Out of memory.");
40051 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40052 return;
40053 }
40054 memcpy(filePath, requestServer->semaphoreFilePath.data, requestServer->semaphoreFilePath.length );
40055 filePath[requestServer->semaphoreFilePath.length] = '\0';
40056 if(!UA_fileExists( filePath )) {
40057 responseHeader->serviceResult = UA_STATUSCODE_BADSEMPAHOREFILEMISSING;
40058 UA_free(filePath);
40059 return;
40060 }
40061 UA_free(filePath);
40062#else
40063 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_CLIENT,
40064 "Ignoring semaphore file path. open62541 not compiled "
40065 "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON");
40066#endif
40067 }
40068
40069#ifdef UA_ENABLE_DISCOVERY_MULTICAST
40070 if(server->config.mdnsEnabled) {
40071 for(size_t i = 0; i < requestServer->discoveryUrlsSize; i++) {
40072 /* create TXT if is online and first index, delete TXT if is offline and last index */
40073 UA_Boolean updateTxt = (requestServer->isOnline && i==0) ||
40074 (!requestServer->isOnline && i==requestServer->discoveryUrlsSize);
40075 UA_Server_updateMdnsForDiscoveryUrl(server, mdnsServerName, mdnsConfig,
40076 &requestServer->discoveryUrls[i],
40077 requestServer->isOnline, updateTxt);
40078 }
40079 }
40080#endif
40081
40082 if(!requestServer->isOnline) {
40083 // server is shutting down. Remove it from the registered servers list
40084 if(!registeredServer_entry) {
40085 // server not found, show warning
40086 UA_LOG_WARNING_SESSION(&server->config.logger, session,
40087 "Could not unregister server %.*s. Not registered.",
40088 (int)requestServer->serverUri.length, requestServer->serverUri.data);
40089 responseHeader->serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
40090 return;
40091 }
40092
40093 if(server->discoveryManager.registerServerCallback) {
40094 UA_UNLOCK(&server->serviceMutex);
40095 server->discoveryManager.
40096 registerServerCallback(requestServer,
40097 server->discoveryManager.registerServerCallbackData);
40098 UA_LOCK(&server->serviceMutex);
40099 }
40100
40101 // server found, remove from list
40102 LIST_REMOVE(registeredServer_entry, pointers);
40103 UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
40104 UA_free(registeredServer_entry);
40105 server->discoveryManager.registeredServersSize--;
40106 responseHeader->serviceResult = UA_STATUSCODE_GOOD;
40107 return;
40108 }
40109
40110 UA_StatusCode retval = UA_STATUSCODE_GOOD;
40111 if(!registeredServer_entry) {
40112 // server not yet registered, register it by adding it to the list
40113 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Registering new server: %.*s",
40114 (int)requestServer->serverUri.length, requestServer->serverUri.data);
40115
40116 registeredServer_entry =
40117 (registeredServer_list_entry *)UA_malloc(sizeof(registeredServer_list_entry));
40118 if(!registeredServer_entry) {
40119 responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40120 return;
40121 }
40122
40123 LIST_INSERT_HEAD(&server->discoveryManager.registeredServers, registeredServer_entry, pointers);
40124 UA_atomic_addSize(&server->discoveryManager.registeredServersSize, 1);
40125 } else {
40126 UA_RegisteredServer_clear(&registeredServer_entry->registeredServer);
40127 }
40128
40129 // Always call the callback, if it is set.
40130 // Previously we only called it if it was a new register call. It may be the case that this endpoint
40131 // registered before, then crashed, restarts and registeres again. In that case the entry is not deleted
40132 // and the callback would not be called.
40133 if(server->discoveryManager.registerServerCallback) {
40134 UA_UNLOCK(&server->serviceMutex);
40135 server->discoveryManager.
40136 registerServerCallback(requestServer,
40137 server->discoveryManager.registerServerCallbackData);
40138 UA_LOCK(&server->serviceMutex);
40139 }
40140
40141 // copy the data from the request into the list
40142 UA_RegisteredServer_copy(requestServer, &registeredServer_entry->registeredServer);
40143 registeredServer_entry->lastSeen = UA_DateTime_nowMonotonic();
40144 responseHeader->serviceResult = retval;
40145}
40146
40147void Service_RegisterServer(UA_Server *server, UA_Session *session,
40148 const UA_RegisterServerRequest *request,
40149 UA_RegisterServerResponse *response) {
40150 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40151 "Processing RegisterServerRequest");
40152 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40153 process_RegisterServer(server, session, &request->requestHeader, &request->server, 0,
40154 NULL, &response->responseHeader, 0, NULL, 0, NULL);
40155}
40156
40157void Service_RegisterServer2(UA_Server *server, UA_Session *session,
40158 const UA_RegisterServer2Request *request,
40159 UA_RegisterServer2Response *response) {
40160 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40161 "Processing RegisterServer2Request");
40162 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40163 process_RegisterServer(server, session, &request->requestHeader, &request->server,
40164 request->discoveryConfigurationSize, request->discoveryConfiguration,
40165 &response->responseHeader, &response->configurationResultsSize,
40166 &response->configurationResults, &response->diagnosticInfosSize,
40167 response->diagnosticInfos);
40168}
40169
40170/* Cleanup server registration: If the semaphore file path is set, then it just
40171 * checks the existence of the file. When it is deleted, the registration is
40172 * removed. If there is no semaphore file, then the registration will be removed
40173 * if it is older than 60 minutes. */
40174void UA_Discovery_cleanupTimedOut(UA_Server *server, UA_DateTime nowMonotonic) {
40175 UA_DateTime timedOut = nowMonotonic;
40176 // registration is timed out if lastSeen is older than 60 minutes (default
40177 // value, can be modified by user).
40178 if(server->config.discoveryCleanupTimeout)
40179 timedOut -= server->config.discoveryCleanupTimeout * UA_DATETIME_SEC;
40180
40181 registeredServer_list_entry* current, *temp;
40182 LIST_FOREACH_SAFE(current, &server->discoveryManager.registeredServers, pointers, temp) {
40183 UA_Boolean semaphoreDeleted = false;
40184
40185#ifdef UA_ENABLE_DISCOVERY_SEMAPHORE
40186 if(current->registeredServer.semaphoreFilePath.length) {
40187 size_t fpSize = sizeof(char)*current->registeredServer.semaphoreFilePath.length+1;
40188 // todo: malloc may fail: return a statuscode
40189 char* filePath = (char *)UA_malloc(fpSize);
40190 if(filePath) {
40191 memcpy(filePath, current->registeredServer.semaphoreFilePath.data,
40192 current->registeredServer.semaphoreFilePath.length );
40193 filePath[current->registeredServer.semaphoreFilePath.length] = '\0';
40194 semaphoreDeleted = UA_fileExists(filePath) == false;
40195 UA_free(filePath);
40196 } else {
40197 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40198 "Cannot check registration semaphore. Out of memory");
40199 }
40200 }
40201#endif
40202
40203 if(semaphoreDeleted || (server->config.discoveryCleanupTimeout &&
40204 current->lastSeen < timedOut)) {
40205 if(semaphoreDeleted) {
40206 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40207 "Registration of server with URI %.*s is removed because "
40208 "the semaphore file '%.*s' was deleted.",
40209 (int)current->registeredServer.serverUri.length,
40210 current->registeredServer.serverUri.data,
40211 (int)current->registeredServer.semaphoreFilePath.length,
40212 current->registeredServer.semaphoreFilePath.data);
40213 } else {
40214 // cppcheck-suppress unreadVariable
40215 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40216 "Registration of server with URI %.*s has timed out and is removed.",
40217 (int)current->registeredServer.serverUri.length,
40218 current->registeredServer.serverUri.data);
40219 }
40220 LIST_REMOVE(current, pointers);
40221 UA_RegisteredServer_clear(&current->registeredServer);
40222 UA_free(current);
40223 server->discoveryManager.registeredServersSize--;
40224 }
40225 }
40226}
40227
40228/* Called by the UA_Server callback. The OPC UA specification says:
40229 *
40230 * > If an error occurs during registration (e.g. the Discovery Server is not running) then the Server
40231 * > must periodically re-attempt registration. The frequency of these attempts should start at 1 second
40232 * > but gradually increase until the registration frequency is the same as what it would be if not
40233 * > errors occurred. The recommended approach would double the period each attempt until reaching the maximum.
40234 *
40235 * We will do so by using the additional data parameter which holds information
40236 * if the next interval is default or if it is a repeated call. */
40237static void
40238periodicServerRegister(UA_Server *server, void *data) {
40239 UA_assert(data != NULL);
40240 UA_LOCK(&server->serviceMutex);
40241
40242 struct PeriodicServerRegisterCallback *cb = (struct PeriodicServerRegisterCallback *)data;
40243
40244 UA_StatusCode retval = UA_Client_connectSecureChannel(cb->client, cb->discovery_server_url);
40245 if (retval == UA_STATUSCODE_GOOD) {
40246 /* Register
40247 You can also use a semaphore file. That file must exist. When the file is
40248 deleted, the server is automatically unregistered. The semaphore file has
40249 to be accessible by the discovery server
40250
40251 UA_StatusCode retval = UA_Server_register_discovery(server,
40252 "opc.tcp://localhost:4840", "/path/to/some/file");
40253 */
40254 retval = register_server_with_discovery_server(server, cb->client, false, NULL);
40255 if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
40256 /* If the periodic interval is higher than the maximum lifetime of
40257 * the session, the server will close the connection. In this case
40258 * we should try to reconnect */
40259 UA_Client_disconnect(cb->client);
40260 retval = UA_Client_connectSecureChannel(cb->client, cb->discovery_server_url);
40261 if (retval == UA_STATUSCODE_GOOD) {
40262 retval = register_server_with_discovery_server(server, cb->client, false, NULL);
40263 }
40264 }
40265 }
40266 /* Registering failed */
40267 if(retval != UA_STATUSCODE_GOOD) {
40268 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40269 "Could not register server with discovery server. "
40270 "Is the discovery server started? StatusCode %s",
40271 UA_StatusCode_name(retval));
40272
40273 /* If the server was previously registered, retry in one second,
40274 * else, double the previous interval */
40275 UA_Double nextInterval = 1000.0;
40276 if(!cb->registered)
40277 nextInterval = cb->this_interval * 2;
40278
40279 /* The interval should be smaller than the default interval */
40280 if(nextInterval > cb->default_interval)
40281 nextInterval = cb->default_interval;
40282
40283 cb->this_interval = nextInterval;
40284 changeRepeatedCallbackInterval(server, cb->id, nextInterval);
40285 UA_UNLOCK(&server->serviceMutex);
40286 return;
40287 }
40288
40289 /* Registering succeeded */
40290 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
40291 "Server successfully registered. Next periodical register will be in %d seconds",
40292 (int)(cb->default_interval/1000));
40293
40294 if(!cb->registered) {
40295 retval = changeRepeatedCallbackInterval(server, cb->id, cb->default_interval);
40296 /* If changing the interval fails, try again after the next registering */
40297 if(retval == UA_STATUSCODE_GOOD)
40298 cb->registered = true;
40299 }
40300 UA_UNLOCK(&server->serviceMutex);
40301}
40302
40303UA_StatusCode
40304UA_Server_addPeriodicServerRegisterCallback(UA_Server *server,
40305 struct UA_Client *client,
40306 const char* discoveryServerUrl,
40307 UA_Double intervalMs,
40308 UA_Double delayFirstRegisterMs,
40309 UA_UInt64 *periodicCallbackId) {
40310 UA_LOCK(&server->serviceMutex);
40311 /* No valid server URL */
40312 if(!discoveryServerUrl) {
40313 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40314 "No discovery server URL provided");
40315 UA_UNLOCK(&server->serviceMutex);
40316 return UA_STATUSCODE_BADINTERNALERROR;
40317 }
40318
40319
40320 if (client->connection.state != UA_CONNECTIONSTATE_CLOSED) {
40321 UA_UNLOCK(&server->serviceMutex);
40322 return UA_STATUSCODE_BADINVALIDSTATE;
40323 }
40324
40325 /* Check if we are already registering with the given discovery url and
40326 * remove the old periodic call */
40327 periodicServerRegisterCallback_entry *rs, *rs_tmp;
40328 LIST_FOREACH_SAFE(rs, &server->discoveryManager.
40329 periodicServerRegisterCallbacks, pointers, rs_tmp) {
40330 if(strcmp(rs->callback->discovery_server_url, discoveryServerUrl) == 0) {
40331 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
40332 "There is already a register callback for '%s' in place. "
40333 "Removing the older one.", discoveryServerUrl);
40334 removeCallback(server, rs->callback->id);
40335 LIST_REMOVE(rs, pointers);
40336 UA_free(rs->callback->discovery_server_url);
40337 UA_free(rs->callback);
40338 UA_free(rs);
40339 break;
40340 }
40341 }
40342
40343 /* Allocate and initialize */
40344 struct PeriodicServerRegisterCallback* cb = (struct PeriodicServerRegisterCallback*)
40345 UA_malloc(sizeof(struct PeriodicServerRegisterCallback));
40346 if(!cb) {
40347 UA_UNLOCK(&server->serviceMutex);
40348 return UA_STATUSCODE_BADOUTOFMEMORY;
40349 }
40350
40351 /* Start repeating a failed register after 1s, then increase the delay. Set
40352 * to 500ms, as the delay is doubled before changing the callback
40353 * interval.*/
40354 cb->this_interval = 500.0;
40355 cb->default_interval = intervalMs;
40356 cb->registered = false;
40357 cb->client = client;
40358 size_t len = strlen(discoveryServerUrl);
40359 cb->discovery_server_url = (char*)UA_malloc(len+1);
40360 if (!cb->discovery_server_url) {
40361 UA_free(cb);
40362 UA_UNLOCK(&server->serviceMutex);
40363 return UA_STATUSCODE_BADOUTOFMEMORY;
40364 }
40365 memcpy(cb->discovery_server_url, discoveryServerUrl, len+1);
40366
40367 /* Add the callback */
40368 UA_StatusCode retval =
40369 addRepeatedCallback(server, periodicServerRegister,
40370 cb, delayFirstRegisterMs, &cb->id);
40371 if(retval != UA_STATUSCODE_GOOD) {
40372 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
40373 "Could not create periodic job for server register. "
40374 "StatusCode %s", UA_StatusCode_name(retval));
40375 UA_free(cb);
40376 UA_UNLOCK(&server->serviceMutex);
40377 return retval;
40378 }
40379
40380#ifndef __clang_analyzer__
40381 // the analyzer reports on LIST_INSERT_HEAD a use after free false positive
40382 periodicServerRegisterCallback_entry *newEntry = (periodicServerRegisterCallback_entry*)
40383 UA_malloc(sizeof(periodicServerRegisterCallback_entry));
40384 if(!newEntry) {
40385 removeCallback(server, cb->id);
40386 UA_free(cb);
40387 UA_UNLOCK(&server->serviceMutex);
40388 return UA_STATUSCODE_BADOUTOFMEMORY;
40389 }
40390 newEntry->callback = cb;
40391 LIST_INSERT_HEAD(&server->discoveryManager.periodicServerRegisterCallbacks, newEntry, pointers);
40392#endif
40393
40394 if(periodicCallbackId)
40395 *periodicCallbackId = cb->id;
40396 UA_UNLOCK(&server->serviceMutex);
40397 return UA_STATUSCODE_GOOD;
40398}
40399
40400void
40401UA_Server_setRegisterServerCallback(UA_Server *server,
40402 UA_Server_registerServerCallback cb,
40403 void* data) {
40404 UA_LOCK(&server->serviceMutex);
40405 server->discoveryManager.registerServerCallback = cb;
40406 server->discoveryManager.registerServerCallbackData = data;
40407 UA_UNLOCK(&server->serviceMutex);
40408}
40409
40410#endif /* UA_ENABLE_DISCOVERY */
40411
40412/**** amalgamated original file "/src/server/ua_services_subscription.c" ****/
40413
40414/* This Source Code Form is subject to the terms of the Mozilla Public
40415 * License, v. 2.0. If a copy of the MPL was not distributed with this
40416 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
40417 *
40418 * Copyright 2014-2018, 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
40419 * Copyright 2016-2017 (c) Florian Palm
40420 * Copyright 2015 (c) Chris Iatrou
40421 * Copyright 2015-2016 (c) Sten Grüner
40422 * Copyright 2015-2016 (c) Oleksiy Vasylyev
40423 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
40424 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
40425 * Copyright 2017 (c) Mattias Bornhager
40426 * Copyright 2017 (c) Henrik Norrman
40427 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
40428 * Copyright 2018 (c) Fabian Arndt, Root-Core
40429 * Copyright 2017-2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
40430 */
40431
40432
40433#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
40434
40435static void
40436setPublishingEnabled(UA_Subscription *sub, UA_Boolean publishingEnabled) {
40437 if(sub->publishingEnabled == publishingEnabled)
40438 return;
40439
40440 sub->publishingEnabled = publishingEnabled;
40441
40442#ifdef UA_ENABLE_DIAGNOSTICS
40443 if(publishingEnabled)
40444 sub->enableCount++;
40445 else
40446 sub->disableCount++;
40447#endif
40448}
40449
40450static void
40451setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription,
40452 UA_Double requestedPublishingInterval,
40453 UA_UInt32 requestedLifetimeCount,
40454 UA_UInt32 requestedMaxKeepAliveCount,
40455 UA_UInt32 maxNotificationsPerPublish,
40456 UA_Byte priority) {
40457 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40458
40459 /* re-parameterize the subscription */
40460 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.publishingIntervalLimits,
40461 requestedPublishingInterval,
40462 subscription->publishingInterval);
40463 /* check for nan*/
40464 if(requestedPublishingInterval != requestedPublishingInterval)
40465 subscription->publishingInterval = server->config.publishingIntervalLimits.min;
40466 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.keepAliveCountLimits,
40467 requestedMaxKeepAliveCount, subscription->maxKeepAliveCount);
40468 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.lifeTimeCountLimits,
40469 requestedLifetimeCount, subscription->lifeTimeCount);
40470 if(subscription->lifeTimeCount < 3 * subscription->maxKeepAliveCount)
40471 subscription->lifeTimeCount = 3 * subscription->maxKeepAliveCount;
40472 subscription->notificationsPerPublish = maxNotificationsPerPublish;
40473 if(maxNotificationsPerPublish == 0 ||
40474 maxNotificationsPerPublish > server->config.maxNotificationsPerPublish)
40475 subscription->notificationsPerPublish = server->config.maxNotificationsPerPublish;
40476 subscription->priority = priority;
40477}
40478
40479void
40480Service_CreateSubscription(UA_Server *server, UA_Session *session,
40481 const UA_CreateSubscriptionRequest *request,
40482 UA_CreateSubscriptionResponse *response) {
40483 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40484
40485 /* Check limits for the number of subscriptions */
40486 if(((server->config.maxSubscriptions != 0) &&
40487 (server->subscriptionsSize >= server->config.maxSubscriptions)) ||
40488 ((server->config.maxSubscriptionsPerSession != 0) &&
40489 (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession))) {
40490 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
40491 return;
40492 }
40493
40494 /* Create the subscription */
40495 UA_Subscription *sub= UA_Subscription_new();
40496 if(!sub) {
40497 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40498 "Processing CreateSubscriptionRequest failed");
40499 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
40500 return;
40501 }
40502
40503 /* Set the subscription parameters */
40504 setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval,
40505 requestedLifetimeCount: request->requestedLifetimeCount,
40506 requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount,
40507 maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority);
40508 setPublishingEnabled(sub, publishingEnabled: request->publishingEnabled);
40509 sub->currentKeepAliveCount = sub->maxKeepAliveCount; /* set settings first */
40510
40511 /* Assign the SubscriptionId */
40512 sub->subscriptionId = ++server->lastSubscriptionId;
40513
40514 /* Register the cyclic callback */
40515 UA_StatusCode retval = Subscription_registerPublishCallback(server, sub);
40516 if(retval != UA_STATUSCODE_GOOD) {
40517 UA_LOG_DEBUG_SESSION(&server->config.logger, sub->session,
40518 "Subscription %" PRIu32 " | "
40519 "Could not register publish callback with error code %s",
40520 sub->subscriptionId, UA_StatusCode_name(retval));
40521 response->responseHeader.serviceResult = retval;
40522 UA_Subscription_delete(server, sub);
40523 return;
40524 }
40525
40526 /* Register the subscription in the server */
40527 LIST_INSERT_HEAD(&server->subscriptions, sub, serverListEntry);
40528 server->subscriptionsSize++;
40529
40530 /* Update the server statistics */
40531 server->serverDiagnosticsSummary.currentSubscriptionCount++;
40532 server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
40533
40534 /* Attach the Subscription to the session */
40535 UA_Session_attachSubscription(session, sub);
40536
40537 /* Prepare the response */
40538 response->subscriptionId = sub->subscriptionId;
40539 response->revisedPublishingInterval = sub->publishingInterval;
40540 response->revisedLifetimeCount = sub->lifeTimeCount;
40541 response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
40542
40543#ifdef UA_ENABLE_DIAGNOSTICS
40544 createSubscriptionObject(server, session, sub);
40545#endif
40546
40547 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
40548 "Subscription created (Publishing interval %.2fms, "
40549 "max %lu notifications per publish)",
40550 sub->publishingInterval,
40551 (long unsigned)sub->notificationsPerPublish);}
40552
40553void
40554Service_ModifySubscription(UA_Server *server, UA_Session *session,
40555 const UA_ModifySubscriptionRequest *request,
40556 UA_ModifySubscriptionResponse *response) {
40557 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40558 "Processing ModifySubscriptionRequest");
40559 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40560
40561 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
40562 if(!sub) {
40563 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40564 return;
40565 }
40566
40567 /* Store the old publishing interval */
40568 UA_Double oldPublishingInterval = sub->publishingInterval;
40569 UA_Byte oldPriority = sub->priority;
40570
40571 /* Change the Subscription settings */
40572 setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval,
40573 requestedLifetimeCount: request->requestedLifetimeCount,
40574 requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount,
40575 maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority);
40576
40577 /* Reset the subscription lifetime */
40578 sub->currentLifetimeCount = 0;
40579
40580 /* Change the repeated callback to the new interval. This cannot fail as the
40581 * CallbackId must exist. */
40582 if(sub->publishCallbackId > 0 &&
40583 sub->publishingInterval != oldPublishingInterval)
40584 changeRepeatedCallbackInterval(server, callbackId: sub->publishCallbackId,
40585 interval_ms: sub->publishingInterval);
40586
40587 /* If the priority has changed, re-enter the subscription to the
40588 * priority-ordered queue in the session. */
40589 if(oldPriority != sub->priority) {
40590 UA_Session_detachSubscription(server, session, sub, false);
40591 UA_Session_attachSubscription(session, sub);
40592 }
40593
40594 /* Set the response */
40595 response->revisedPublishingInterval = sub->publishingInterval;
40596 response->revisedLifetimeCount = sub->lifeTimeCount;
40597 response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount;
40598
40599 /* Update the diagnostics statistics */
40600#ifdef UA_ENABLE_DIAGNOSTICS
40601 sub->modifyCount++;
40602#endif
40603}
40604
40605static void
40606Operation_SetPublishingMode(UA_Server *server, UA_Session *session,
40607 const UA_Boolean *publishingEnabled,
40608 const UA_UInt32 *subscriptionId,
40609 UA_StatusCode *result) {
40610 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40611 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId);
40612 if(!sub) {
40613 *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40614 return;
40615 }
40616
40617 sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
40618 setPublishingEnabled(sub, publishingEnabled: *publishingEnabled); /* Set the publishing mode */
40619}
40620
40621void
40622Service_SetPublishingMode(UA_Server *server, UA_Session *session,
40623 const UA_SetPublishingModeRequest *request,
40624 UA_SetPublishingModeResponse *response) {
40625 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40626 "Processing SetPublishingModeRequest");
40627 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40628
40629 UA_Boolean publishingEnabled = request->publishingEnabled; /* request is const */
40630 response->responseHeader.serviceResult =
40631 UA_Server_processServiceOperations(server, session,
40632 operationCallback: (UA_ServiceOperation)Operation_SetPublishingMode,
40633 context: &publishingEnabled,
40634 requestOperations: &request->subscriptionIdsSize,
40635 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
40636 responseOperations: &response->resultsSize,
40637 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
40638}
40639
40640UA_StatusCode
40641Service_Publish(UA_Server *server, UA_Session *session,
40642 const UA_PublishRequest *request, UA_UInt32 requestId) {
40643 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing PublishRequest");
40644 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40645
40646 /* Return an error if the session has no subscription */
40647 if(TAILQ_EMPTY(&session->subscriptions)) {
40648 sendServiceFault(channel: session->header.channel, requestId,
40649 requestHandle: request->requestHeader.requestHandle,
40650 UA_STATUSCODE_BADNOSUBSCRIPTION);
40651 return UA_STATUSCODE_BADNOSUBSCRIPTION;
40652 }
40653
40654 /* Handle too many subscriptions to free resources before trying to allocate
40655 * resources for the new publish request. If the limit has been reached the
40656 * oldest publish request shall be responded */
40657 if((server->config.maxPublishReqPerSession != 0) &&
40658 (session->responseQueueSize >= server->config.maxPublishReqPerSession)) {
40659 if(!UA_Session_reachedPublishReqLimit(server, session)) {
40660 sendServiceFault(channel: session->header.channel, requestId,
40661 requestHandle: request->requestHeader.requestHandle,
40662 UA_STATUSCODE_BADINTERNALERROR);
40663 return UA_STATUSCODE_BADINTERNALERROR;
40664 }
40665 }
40666
40667 /* Allocate the response to store it in the retransmission queue */
40668 UA_PublishResponseEntry *entry = (UA_PublishResponseEntry *)
40669 UA_malloc(size: sizeof(UA_PublishResponseEntry));
40670 if(!entry) {
40671 sendServiceFault(channel: session->header.channel, requestId,
40672 requestHandle: request->requestHeader.requestHandle,
40673 UA_STATUSCODE_BADOUTOFMEMORY);
40674 return UA_STATUSCODE_BADOUTOFMEMORY;
40675 }
40676
40677 /* Prepare the response */
40678 entry->requestId = requestId;
40679 UA_PublishResponse *response = &entry->response;
40680 UA_PublishResponse_init(p: response);
40681 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
40682
40683 /* Allocate the results array to acknowledge the acknowledge */
40684 if(request->subscriptionAcknowledgementsSize > 0) {
40685 response->results = (UA_StatusCode *)
40686 UA_Array_new(size: request->subscriptionAcknowledgementsSize,
40687 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
40688 if(!response->results) {
40689 UA_free(ptr: entry);
40690 sendServiceFault(channel: session->header.channel, requestId,
40691 requestHandle: request->requestHeader.requestHandle,
40692 UA_STATUSCODE_BADOUTOFMEMORY);
40693 return UA_STATUSCODE_BADOUTOFMEMORY;
40694 }
40695 response->resultsSize = request->subscriptionAcknowledgementsSize;
40696 }
40697
40698 /* <--- A good StatusCode is returned from here on ---> */
40699
40700 /* Delete Acknowledged Subscription Messages */
40701 for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; ++i) {
40702 UA_SubscriptionAcknowledgement *ack = &request->subscriptionAcknowledgements[i];
40703 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: ack->subscriptionId);
40704 if(!sub) {
40705 response->results[i] = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40706 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40707 "Cannot process acknowledgements subscription %u" PRIu32,
40708 ack->subscriptionId);
40709 continue;
40710 }
40711 /* Remove the acked transmission from the retransmission queue */
40712 response->results[i] =
40713 UA_Subscription_removeRetransmissionMessage(sub, sequenceNumber: ack->sequenceNumber);
40714 }
40715
40716 /* Queue the publish response. It will be dequeued in a repeated publish
40717 * callback. This can also be triggered right now for a late
40718 * subscription. */
40719 UA_Session_queuePublishReq(session, entry, false);
40720 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Queued a publication message");
40721
40722 /* If we still had publish requests in the queue, none of the subscriptions
40723 * is late. So we don't have to search for one. */
40724 if(session->responseQueueSize > 1) {
40725 return UA_STATUSCODE_GOOD;
40726 }
40727
40728 /* If there are late subscriptions, the new publish request is used to
40729 * answer them immediately. Late subscriptions with higher priority are
40730 * considered earlier. However, a single subscription that generates many
40731 * notifications must not "starve" other late subscriptions. Hence we move
40732 * it to the end of the queue for the subscriptions of that priority. */
40733 UA_Subscription *late, *late_tmp;
40734 TAILQ_FOREACH_SAFE(late, &session->subscriptions, sessionListEntry, late_tmp) {
40735 if(late->state != UA_SUBSCRIPTIONSTATE_LATE)
40736 continue;
40737
40738 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, late,
40739 "Send PublishResponse on a late subscription");
40740 UA_Subscription_publishOnce(server, sub: late);
40741
40742 /* Skip re-insert if the subscription was deleted during publishOnce */
40743 if(late->session) {
40744 /* Find the first element with smaller priority and insert before
40745 * that. If there is none, insert at the end of the queue. */
40746 UA_Subscription *after = TAILQ_NEXT(late, sessionListEntry);
40747 while(after && after->priority >= late->priority)
40748 after = TAILQ_NEXT(after, sessionListEntry);
40749 TAILQ_REMOVE(&session->subscriptions, late, sessionListEntry);
40750 if(after)
40751 TAILQ_INSERT_BEFORE(after, late, sessionListEntry);
40752 else
40753 TAILQ_INSERT_TAIL(&session->subscriptions, late, sessionListEntry);
40754 }
40755
40756 /* In case of an error we might not have used the publish request that
40757 * was just enqueued. Continue to find late subscriptions in that
40758 * case. */
40759 if(session->responseQueueSize == 0)
40760 break;
40761 }
40762
40763 return UA_STATUSCODE_GOOD;
40764}
40765
40766static void
40767Operation_DeleteSubscription(UA_Server *server, UA_Session *session, void *_,
40768 const UA_UInt32 *subscriptionId, UA_StatusCode *result) {
40769 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId);
40770 if(!sub) {
40771 *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40772 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40773 "Deleting Subscription with Id %" PRIu32
40774 " failed with error code %s",
40775 *subscriptionId, UA_StatusCode_name(*result));
40776 return;
40777 }
40778
40779 UA_Subscription_delete(server, sub);
40780 *result = UA_STATUSCODE_GOOD;
40781 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40782 "Subscription %" PRIu32 " | Subscription deleted",
40783 *subscriptionId);
40784}
40785
40786void
40787Service_DeleteSubscriptions(UA_Server *server, UA_Session *session,
40788 const UA_DeleteSubscriptionsRequest *request,
40789 UA_DeleteSubscriptionsResponse *response) {
40790 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40791 "Processing DeleteSubscriptionsRequest");
40792 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40793
40794 response->responseHeader.serviceResult =
40795 UA_Server_processServiceOperations(server, session,
40796 operationCallback: (UA_ServiceOperation)Operation_DeleteSubscription, NULL,
40797 requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
40798 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
40799}
40800
40801void
40802Service_Republish(UA_Server *server, UA_Session *session,
40803 const UA_RepublishRequest *request,
40804 UA_RepublishResponse *response) {
40805 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
40806 "Processing RepublishRequest");
40807 UA_LOCK_ASSERT(&server->serviceMutex, 1);
40808
40809 /* Get the subscription */
40810 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
40811 if(!sub) {
40812 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40813 return;
40814 }
40815
40816 /* Reset the subscription lifetime */
40817 sub->currentLifetimeCount = 0;
40818
40819 /* Update the subscription statistics */
40820#ifdef UA_ENABLE_DIAGNOSTICS
40821 sub->republishRequestCount++;
40822#endif
40823
40824 /* Find the notification in the retransmission queue */
40825 UA_NotificationMessageEntry *entry;
40826 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
40827 if(entry->message.sequenceNumber == request->retransmitSequenceNumber)
40828 break;
40829 }
40830 if(!entry) {
40831 response->responseHeader.serviceResult = UA_STATUSCODE_BADMESSAGENOTAVAILABLE;
40832 return;
40833 }
40834
40835 response->responseHeader.serviceResult =
40836 UA_NotificationMessage_copy(src: &entry->message, dst: &response->notificationMessage);
40837
40838 /* Update the subscription statistics for the case where we return a message */
40839#ifdef UA_ENABLE_DIAGNOSTICS
40840 sub->republishMessageCount++;
40841#endif
40842}
40843
40844static UA_StatusCode
40845setTransferredSequenceNumbers(const UA_Subscription *sub, UA_TransferResult *result) {
40846 /* Allocate memory */
40847 result->availableSequenceNumbers = (UA_UInt32*)
40848 UA_Array_new(size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]);
40849 if(!result->availableSequenceNumbers)
40850 return UA_STATUSCODE_BADOUTOFMEMORY;
40851 result->availableSequenceNumbersSize = sub->retransmissionQueueSize;
40852
40853 /* Copy over the sequence numbers */
40854 UA_NotificationMessageEntry *entry;
40855 size_t i = 0;
40856 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
40857 result->availableSequenceNumbers[i] = entry->message.sequenceNumber;
40858 i++;
40859 }
40860
40861 UA_assert(i == result->availableSequenceNumbersSize);
40862
40863 return UA_STATUSCODE_GOOD;
40864}
40865
40866static void
40867Operation_TransferSubscription(UA_Server *server, UA_Session *session,
40868 const UA_Boolean *sendInitialValues,
40869 const UA_UInt32 *subscriptionId,
40870 UA_TransferResult *result) {
40871 /* Get the subscription. This requires a server-wide lookup instead of the
40872 * usual session-wide lookup. */
40873 UA_Subscription *sub = UA_Server_getSubscriptionById(server, subscriptionId: *subscriptionId);
40874 if(!sub) {
40875 result->statusCode = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
40876 return;
40877 }
40878
40879 /* Update the diagnostics statistics */
40880#ifdef UA_ENABLE_DIAGNOSTICS
40881 sub->transferRequestCount++;
40882#endif
40883
40884 /* Is this the same session? Return the sequence numbers and do nothing else. */
40885 UA_Session *oldSession = sub->session;
40886 if(oldSession == session) {
40887 result->statusCode = setTransferredSequenceNumbers(sub, result);
40888#ifdef UA_ENABLE_DIAGNOSTICS
40889 sub->transferredToSameClientCount++;
40890#endif
40891 return;
40892 }
40893
40894 /* Check with AccessControl if the transfer is allowed */
40895 if(!server->config.accessControl.allowTransferSubscription ||
40896 !server->config.accessControl.
40897 allowTransferSubscription(server, &server->config.accessControl,
40898 oldSession ? &oldSession->sessionId : NULL,
40899 oldSession ? oldSession->sessionHandle : NULL,
40900 &session->sessionId, session->sessionHandle)) {
40901 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
40902 return;
40903 }
40904
40905 /* Check limits for the number of subscriptions for this Session */
40906 if((server->config.maxSubscriptionsPerSession != 0) &&
40907 (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession)) {
40908 result->statusCode = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS;
40909 return;
40910 }
40911
40912 /* Allocate memory for the new subscription */
40913 UA_Subscription *newSub = (UA_Subscription*)UA_malloc(size: sizeof(UA_Subscription));
40914 if(!newSub) {
40915 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
40916 return;
40917 }
40918
40919 /* Set the available sequence numbers */
40920 result->statusCode = setTransferredSequenceNumbers(sub, result);
40921 if(result->statusCode != UA_STATUSCODE_GOOD) {
40922 UA_free(ptr: newSub);
40923 return;
40924 }
40925
40926 /* Create an identical copy of the Subscription struct. The original
40927 * subscription remains in place until a StatusChange notification has been
40928 * sent. The elements for lists and queues are moved over manually to ensure
40929 * that all backpointers are set correctly. */
40930 memcpy(dest: newSub, src: sub, n: sizeof(UA_Subscription));
40931
40932 /* Register cyclic publish callback */
40933 result->statusCode = Subscription_registerPublishCallback(server, sub: newSub);
40934 if(result->statusCode != UA_STATUSCODE_GOOD) {
40935 UA_Array_delete(p: result->availableSequenceNumbers,
40936 size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]);
40937 result->availableSequenceNumbers = NULL;
40938 result->availableSequenceNumbersSize = 0;
40939 UA_free(ptr: newSub);
40940 return;
40941 }
40942
40943 /* <-- The point of no return --> */
40944
40945 /* Move over the MonitoredItems and adjust the backpointers */
40946 LIST_INIT(&newSub->monitoredItems);
40947 UA_MonitoredItem *mon, *mon_tmp;
40948 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp) {
40949 LIST_REMOVE(mon, listEntry);
40950 mon->subscription = newSub;
40951 LIST_INSERT_HEAD(&newSub->monitoredItems, mon, listEntry);
40952 }
40953 sub->monitoredItemsSize = 0;
40954
40955 /* Move over the notification queue */
40956 TAILQ_INIT(&newSub->notificationQueue);
40957 UA_Notification *nn, *nn_tmp;
40958 TAILQ_FOREACH_SAFE(nn, &sub->notificationQueue, globalEntry, nn_tmp) {
40959 TAILQ_REMOVE(&sub->notificationQueue, nn, globalEntry);
40960 TAILQ_INSERT_TAIL(&newSub->notificationQueue, nn, globalEntry);
40961 }
40962 sub->notificationQueueSize = 0;
40963 sub->dataChangeNotifications = 0;
40964 sub->eventNotifications = 0;
40965
40966 TAILQ_INIT(&newSub->retransmissionQueue);
40967 UA_NotificationMessageEntry *nme, *nme_tmp;
40968 TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
40969 TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
40970 TAILQ_INSERT_TAIL(&newSub->retransmissionQueue, nme, listEntry);
40971 if(oldSession)
40972 oldSession->totalRetransmissionQueueSize -= 1;
40973 sub->retransmissionQueueSize -= 1;
40974 }
40975 UA_assert(sub->retransmissionQueueSize == 0);
40976 sub->retransmissionQueueSize = 0;
40977
40978 /* Add to the server */
40979 UA_assert(newSub->subscriptionId == sub->subscriptionId);
40980 LIST_INSERT_HEAD(&server->subscriptions, newSub, serverListEntry);
40981 server->subscriptionsSize++;
40982
40983 /* Attach to the session */
40984 UA_Session_attachSubscription(session, sub: newSub);
40985
40986 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, newSub, "Transferred to this Session");
40987
40988 /* Set StatusChange in the original subscription and force publish. This
40989 * also removes the Subscription, even if there was no PublishResponse
40990 * queued to send a StatusChangeNotification. */
40991 sub->statusChange = UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED;
40992 UA_Subscription_publish(server, sub);
40993
40994 /* The original subscription has been deactivated */
40995 UA_assert(sub->publishCallbackId == 0);
40996
40997 /* Re-create notifications with the current values for the new subscription */
40998 if(*sendInitialValues) {
40999 LIST_FOREACH(mon, &newSub->monitoredItems, listEntry) {
41000
41001 /* Create only DataChange notifications */
41002 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
41003 continue;
41004
41005 /* Only if the mode is monitoring */
41006 if(mon->monitoringMode != UA_MONITORINGMODE_REPORTING)
41007 continue;
41008
41009 /* If a value is queued for a data MonitoredItem, the next value in
41010 * the queue is sent in the Publish response. */
41011 if(mon->queueSize > 0)
41012 continue;
41013
41014 /* Create a notification with the last sampled value */
41015 UA_MonitoredItem_createDataChangeNotification(server, sub: newSub, mon,
41016 value: &mon->lastValue);
41017 }
41018 }
41019
41020 /* Do not update the statistics for the number of Subscriptions here. The
41021 * fact that we duplicate the subscription and move over the content is just
41022 * an implementtion detail.
41023 * server->serverDiagnosticsSummary.currentSubscriptionCount++;
41024 * server->serverDiagnosticsSummary.cumulatedSubscriptionCount++;
41025 *
41026 * Update the diagnostics statistics: */
41027#ifdef UA_ENABLE_DIAGNOSTICS
41028 if(oldSession &&
41029 UA_order(&oldSession->clientDescription,
41030 &session->clientDescription,
41031 &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]) == UA_ORDER_EQ)
41032 sub->transferredToSameClientCount++;
41033 else
41034 sub->transferredToAltClientCount++;
41035#endif
41036
41037 /* Immediately try to publish on the new Subscription. This might put it
41038 * into the "late subscription" mode. */
41039 UA_Subscription_publish(server, sub: newSub);
41040}
41041
41042void Service_TransferSubscriptions(UA_Server *server, UA_Session *session,
41043 const UA_TransferSubscriptionsRequest *request,
41044 UA_TransferSubscriptionsResponse *response) {
41045 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41046 "Processing TransferSubscriptionsRequest");
41047 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41048
41049 response->responseHeader.serviceResult =
41050 UA_Server_processServiceOperations(server, session,
41051 operationCallback: (UA_ServiceOperation)Operation_TransferSubscription,
41052 context: &request->sendInitialValues,
41053 requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41054 responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_TRANSFERRESULT]);
41055}
41056
41057#endif /* UA_ENABLE_SUBSCRIPTIONS */
41058
41059/**** amalgamated original file "/src/server/ua_services_monitoreditem.c" ****/
41060
41061/* This Source Code Form is subject to the terms of the Mozilla Public
41062 * License, v. 2.0. If a copy of the MPL was not distributed with this
41063 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
41064 *
41065 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
41066 * Copyright 2016-2017 (c) Florian Palm
41067 * Copyright 2015 (c) Chris Iatrou
41068 * Copyright 2015-2016 (c) Sten Grüner
41069 * Copyright 2015-2016 (c) Oleksiy Vasylyev
41070 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
41071 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
41072 * Copyright 2017 (c) Mattias Bornhager
41073 * Copyright 2017 (c) Henrik Norrman
41074 * Copyright 2017-2023 (c) Thomas Stalder, Blue Time Concept SA
41075 * Copyright 2018 (c) Fabian Arndt, Root-Core
41076 * Copyright 2020 (c) Kalycito Infotech Private Limited
41077 * Copyright 2021 (c) Uranik, Berisha
41078 * Copyright 2021 (c) Ammar, Morshed
41079 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
41080 */
41081
41082
41083#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
41084
41085#ifdef UA_ENABLE_DA
41086
41087/* Translate a percentage deadband into an absolute deadband based on the
41088 * UARange property of the variable */
41089static UA_StatusCode
41090setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session,
41091 const UA_MonitoredItem *mon, UA_DataChangeFilter *filter) {
41092 /* A valid deadband? */
41093 if(filter->deadbandValue < 0.0 || filter->deadbandValue > 100.0)
41094 return UA_STATUSCODE_BADDEADBANDFILTERINVALID;
41095
41096 /* Browse for the percent range */
41097 UA_QualifiedName qn = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EURange");
41098 UA_BrowsePathResult bpr =
41099 browseSimplifiedBrowsePath(server, origin: mon->itemToMonitor.nodeId, browsePathSize: 1, browsePath: &qn);
41100 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
41101 UA_BrowsePathResult_clear(p: &bpr);
41102 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41103 }
41104
41105 /* Read the range */
41106 UA_ReadValueId rvi;
41107 UA_ReadValueId_init(p: &rvi);
41108 rvi.nodeId = bpr.targets->targetId.nodeId;
41109 rvi.attributeId = UA_ATTRIBUTEID_VALUE;
41110 UA_DataValue rangeVal = UA_Server_readWithSession(server, session, item: &rvi,
41111 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
41112 UA_BrowsePathResult_clear(p: &bpr);
41113 if(!UA_Variant_isScalar(v: &rangeVal.value) ||
41114 rangeVal.value.type != &UA_TYPES[UA_TYPES_RANGE]) {
41115 UA_DataValue_clear(p: &rangeVal);
41116 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41117 }
41118
41119 /* Compute the abs deadband */
41120 UA_Range *euRange = (UA_Range*)rangeVal.value.data;
41121 UA_Double absDeadband = (filter->deadbandValue/100.0) * (euRange->high - euRange->low);
41122
41123 UA_DataValue_clear(p: &rangeVal);
41124
41125 /* EURange invalid or NaN? */
41126 if(absDeadband < 0.0 || absDeadband != absDeadband) {
41127 UA_DataValue_clear(p: &rangeVal);
41128 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41129 }
41130
41131 /* Adjust the original filter */
41132 filter->deadbandType = UA_DEADBANDTYPE_ABSOLUTE;
41133 filter->deadbandValue = absDeadband;
41134 return UA_STATUSCODE_GOOD;
41135}
41136
41137#endif /* UA_ENABLE_DA */
41138
41139void
41140Service_SetTriggering(UA_Server *server, UA_Session *session,
41141 const UA_SetTriggeringRequest *request,
41142 UA_SetTriggeringResponse *response) {
41143 /* Nothing to do? */
41144 if(request->linksToRemoveSize == 0 &&
41145 request->linksToAddSize == 0) {
41146 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO;
41147 return;
41148 }
41149
41150 /* Get the Subscription */
41151 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41152 if(!sub) {
41153 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41154 return;
41155 }
41156
41157 /* Get the MonitoredItem */
41158 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->triggeringItemId);
41159 if(!mon) {
41160 response->responseHeader.serviceResult = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41161 return;
41162 }
41163
41164 /* Allocate the results arrays */
41165 if(request->linksToRemoveSize > 0) {
41166 response->removeResults = (UA_StatusCode*)
41167 UA_Array_new(size: request->linksToRemoveSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41168 if(!response->removeResults) {
41169 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
41170 return;
41171 }
41172 response->removeResultsSize = request->linksToRemoveSize;
41173 }
41174
41175 if(request->linksToAddSize> 0) {
41176 response->addResults = (UA_StatusCode*)
41177 UA_Array_new(size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41178 if(!response->addResults) {
41179 UA_Array_delete(p: response->removeResults,
41180 size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41181 response->removeResults = NULL;
41182 response->removeResultsSize = 0;
41183 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
41184 return;
41185 }
41186 response->addResultsSize = request->linksToAddSize;
41187 }
41188
41189 /* Apply the changes */
41190 for(size_t i = 0; i < request->linksToRemoveSize; i++)
41191 response->removeResults[i] =
41192 UA_MonitoredItem_removeLink(sub, mon, linkId: request->linksToRemove[i]);
41193
41194 for(size_t i = 0; i < request->linksToAddSize; i++)
41195 response->addResults[i] =
41196 UA_MonitoredItem_addLink(sub, mon, linkId: request->linksToAdd[i]);
41197}
41198
41199/* Verify and adjust the parameters of a MonitoredItem */
41200static UA_StatusCode
41201checkAdjustMonitoredItemParams(UA_Server *server, UA_Session *session,
41202 const UA_MonitoredItem *mon,
41203 const UA_DataType* valueType,
41204 UA_MonitoringParameters *params) {
41205 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41206
41207 /* Check the filter */
41208 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41209 /* Event MonitoredItems need a filter */
41210#ifndef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41211 return UA_STATUSCODE_BADNOTSUPPORTED;
41212#else
41213 if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED &&
41214 params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE)
41215 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41216 if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
41217 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41218#endif
41219 } else {
41220 /* DataChange MonitoredItem. Can be "no filter" which defaults to
41221 * triggering on Status and Value. */
41222 if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED &&
41223 params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE &&
41224 params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY)
41225 return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
41226
41227 /* If the filter ExtensionObject has a body, then it must be a
41228 * DataChangeFilter */
41229 if(params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
41230 params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGEFILTER])
41231 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41232
41233 /* Check the deadband and adjust if necessary. */
41234 if(params->filter.content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
41235 UA_DataChangeFilter *filter = (UA_DataChangeFilter *)
41236 params->filter.content.decoded.data;
41237 switch(filter->deadbandType) {
41238 case UA_DEADBANDTYPE_NONE:
41239 break;
41240 case UA_DEADBANDTYPE_ABSOLUTE:
41241 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
41242 !valueType || !UA_DataType_isNumeric(type: valueType))
41243 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41244 break;
41245#ifdef UA_ENABLE_DA
41246 case UA_DEADBANDTYPE_PERCENT: {
41247 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE ||
41248 !valueType || !UA_DataType_isNumeric(type: valueType))
41249 return UA_STATUSCODE_BADFILTERNOTALLOWED;
41250 /* If percentage deadband is supported, look up the range values
41251 * and precompute as if it was an absolute deadband. */
41252 UA_StatusCode res =
41253 setAbsoluteFromPercentageDeadband(server, session, mon, filter);
41254 if(res != UA_STATUSCODE_GOOD)
41255 return res;
41256 break;
41257 }
41258#endif
41259 default:
41260 return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED;
41261 }
41262 }
41263 }
41264
41265 /* Read the minimum sampling interval for the variable. The sampling
41266 * interval of the MonitoredItem must not be less than that. */
41267 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_VALUE) {
41268 const UA_Node *node = UA_NODESTORE_GET(server, &mon->itemToMonitor.nodeId);
41269 if(node) {
41270 const UA_VariableNode *vn = &node->variableNode;
41271 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
41272 /* Take into account if the publishing interval is used for sampling */
41273 UA_Double samplingInterval = params->samplingInterval;
41274 if(samplingInterval < 0 && mon->subscription)
41275 samplingInterval = mon->subscription->publishingInterval;
41276 /* Adjust if smaller than the allowed minimum for the variable */
41277 if(samplingInterval < vn->minimumSamplingInterval)
41278 params->samplingInterval = vn->minimumSamplingInterval;
41279 }
41280 UA_NODESTORE_RELEASE(server, node);
41281 }
41282 }
41283
41284 /* Adjust sampling interval */
41285 if(params->samplingInterval < 0.0) {
41286 /* A negative number indicates that the sampling interval is the
41287 * publishing interval of the Subscription. */
41288 if(!mon->subscription) {
41289 /* Not possible for local MonitoredItems */
41290 params->samplingInterval = server->config.samplingIntervalLimits.min;
41291 } else {
41292 /* Test if the publishing interval is a valid sampling interval. If
41293 * not, adjust to lie within the limits. */
41294 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
41295 mon->subscription->publishingInterval,
41296 params->samplingInterval);
41297 if(params->samplingInterval == mon->subscription->publishingInterval) {
41298 /* The publishing interval is valid also for sampling. Set sampling
41299 * interval to -1 to sample the monitored item in the publish
41300 * callback. The revised sampling interval of the response will be
41301 * set to the publishing interval.*/
41302 params->samplingInterval = -1.0;
41303 }
41304 }
41305 } else {
41306 /* Adjust positive sampling interval to lie within the limits */
41307 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits,
41308 params->samplingInterval, params->samplingInterval);
41309 /* Check for NaN */
41310 if(mon->parameters.samplingInterval != mon->parameters.samplingInterval)
41311 params->samplingInterval = server->config.samplingIntervalLimits.min;
41312 }
41313
41314 /* Adjust the maximum queue size */
41315#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41316 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41317 /* 0 => Set to the configured maximum. Otherwise adjust with configured limits */
41318 if(params->queueSize == 0) {
41319 params->queueSize = server->config.queueSizeLimits.max;
41320 } else {
41321 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
41322 params->queueSize, params->queueSize);
41323 }
41324 } else
41325#endif
41326 {
41327 /* 0 or 1 => queue-size 1. Otherwise adjust with configured limits */
41328 if(params->queueSize == 0)
41329 params->queueSize = 1;
41330 if(params->queueSize != 1)
41331 UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits,
41332 params->queueSize, params->queueSize);
41333 }
41334
41335 return UA_STATUSCODE_GOOD;
41336}
41337
41338#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41339static UA_StatusCode
41340checkEventFilterParam(UA_Server *server, UA_Session *session,
41341 const UA_MonitoredItem *mon,
41342 UA_MonitoringParameters *params,
41343 UA_MonitoredItemCreateResult *result) {
41344 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
41345 return UA_STATUSCODE_GOOD;
41346
41347 UA_EventFilter *eventFilter =
41348 (UA_EventFilter *) params->filter.content.decoded.data;
41349
41350 if(eventFilter == NULL)
41351 return UA_STATUSCODE_BADEVENTFILTERINVALID;
41352
41353 //TODO make the maximum select clause size param an server-config parameter
41354 if(eventFilter->selectClausesSize > 128)
41355 return UA_STATUSCODE_BADCONFIGURATIONERROR;
41356
41357 UA_ContentFilterResult contentFilterResult;
41358 UA_Event_staticWhereClauseValidation(server, filter: &eventFilter->whereClause,
41359 &contentFilterResult);
41360
41361 UA_StatusCode selectClauseValidationResult[128];
41362 UA_Event_staticSelectClauseValidation(server,eventFilter,
41363 result: selectClauseValidationResult);
41364
41365 //check the where clause for logical consistency
41366 UA_StatusCode res = UA_STATUSCODE_GOOD;
41367 for(size_t i = 0; i < contentFilterResult.elementResultsSize; ++i) {
41368 if(contentFilterResult.elementResults[i].statusCode != UA_STATUSCODE_GOOD){
41369 //ToDo currently we return the first non good status code, check if
41370 //we can use the detailed contentFilterResult later
41371 res = contentFilterResult.elementResults[i].statusCode;
41372 break;
41373 }
41374 }
41375
41376 //check the select clause for logical consistency
41377 for(size_t i = 0; i < eventFilter->selectClausesSize; ++i){
41378 //ToDo currently we return the first non good status code, check if
41379 //we can use the detailed status code list later
41380 if(selectClauseValidationResult[i] != UA_STATUSCODE_GOOD){
41381 res = selectClauseValidationResult[i];
41382 break;
41383 }
41384 }
41385
41386 if(res == UA_STATUSCODE_GOOD) {
41387 UA_ContentFilterResult_clear(p: &contentFilterResult);
41388 return res;
41389 }
41390
41391 /* Create the EventFilterResult output */
41392 UA_EventFilterResult *efr = UA_EventFilterResult_new();
41393 if(!efr) {
41394 UA_ContentFilterResult_clear(p: &contentFilterResult);
41395 return UA_STATUSCODE_BADOUTOFMEMORY;
41396 }
41397
41398 efr->whereClauseResult = contentFilterResult;
41399 /* UA_ContentFilterResult_init(&contentFilterResult); */
41400
41401 efr->selectClauseResults = (UA_StatusCode*)
41402 UA_Array_new(size: eventFilter->selectClausesSize,
41403 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
41404 if(!efr->selectClauseResults) {
41405 UA_EventFilterResult_delete(p: efr);
41406 return UA_STATUSCODE_BADOUTOFMEMORY;
41407 }
41408
41409 efr->selectClauseResultsSize = eventFilter->selectClausesSize;
41410 memcpy(dest: efr->selectClauseResults, src: selectClauseValidationResult,
41411 n: sizeof(UA_StatusCode) * efr->selectClauseResultsSize);
41412
41413 UA_ExtensionObject_setValue(eo: &result->filterResult, p: efr,
41414 type: &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]);
41415
41416 return res;
41417}
41418#endif
41419
41420static const UA_String
41421binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *)"Default Binary"};
41422
41423/* Structure to pass additional arguments into the operation */
41424struct createMonContext {
41425 UA_Subscription *sub;
41426 UA_TimestampsToReturn timestampsToReturn;
41427
41428 /* If sub is NULL, use local callbacks */
41429 UA_Server_DataChangeNotificationCallback dataChangeCallback;
41430 void *context;
41431};
41432
41433static void
41434Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session,
41435 struct createMonContext *cmc,
41436 const UA_MonitoredItemCreateRequest *request,
41437 UA_MonitoredItemCreateResult *result) {
41438 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41439
41440 /* Check available capacity */
41441 if(cmc->sub &&
41442 (((server->config.maxMonitoredItems != 0) &&
41443 (server->monitoredItemsSize >= server->config.maxMonitoredItems)) ||
41444 ((server->config.maxMonitoredItemsPerSubscription != 0) &&
41445 (cmc->sub->monitoredItemsSize >= server->config.maxMonitoredItemsPerSubscription)))) {
41446 result->statusCode = UA_STATUSCODE_BADTOOMANYMONITOREDITEMS;
41447 return;
41448 }
41449
41450 /* Check if the encoding is supported */
41451 if(request->itemToMonitor.dataEncoding.name.length > 0 &&
41452 (!UA_String_equal(s1: &binaryEncoding, s2: &request->itemToMonitor.dataEncoding.name) ||
41453 request->itemToMonitor.dataEncoding.namespaceIndex != 0)) {
41454 result->statusCode = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED;
41455 return;
41456 }
41457
41458 /* Check if the encoding is set for a value */
41459 if(request->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE &&
41460 request->itemToMonitor.dataEncoding.name.length > 0) {
41461 result->statusCode = UA_STATUSCODE_BADDATAENCODINGINVALID;
41462 return;
41463 }
41464
41465 /* Make an example read to check the itemToMonitor. The DataSource itself
41466 * could return a (temporary) error. This should still result in a valid
41467 * MonitoredItem. Only a few StatusCodes are considered unrecoverable and
41468 * lead to an abort:
41469 * - The Node does not exist
41470 * - The AttributeId does not match the NodeClass
41471 * - The Session does not have sufficient access rights
41472 * - The indicated encoding is not supported or not valid */
41473 UA_DataValue v = UA_Server_readWithSession(server, session, item: &request->itemToMonitor,
41474 timestampsToReturn: cmc->timestampsToReturn);
41475 if(v.hasStatus &&
41476 (v.status == UA_STATUSCODE_BADNODEIDUNKNOWN ||
41477 v.status == UA_STATUSCODE_BADATTRIBUTEIDINVALID ||
41478 v.status == UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED ||
41479 v.status == UA_STATUSCODE_BADDATAENCODINGINVALID ||
41480 v.status == UA_STATUSCODE_BADINDEXRANGEINVALID
41481 /* Part 4, 5.12.2 CreateMonitoredItems: When a user adds a monitored
41482 * item that the user is denied read access to, the add operation for
41483 * the item shall succeed and the bad status Bad_NotReadable or
41484 * Bad_UserAccessDenied shall be returned in the Publish response.
41485 * v.status == UA_STATUSCODE_BADNOTREADABLE
41486 * v.status == UA_STATUSCODE_BADUSERACCESSDENIED
41487 *
41488 * The IndexRange error can change depending on the value.
41489 * v.status == UA_STATUSCODE_BADINDEXRANGENODATA */
41490 )) {
41491 result->statusCode = v.status;
41492 UA_DataValue_clear(p: &v);
41493 return;
41494 }
41495
41496 /* Adding an Event MonitoredItem */
41497#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41498 if(request->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) {
41499 /* TODO: Only remote clients can add Event-MonitoredItems at the moment */
41500 if(!cmc->sub) {
41501 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
41502 msg: "Only remote clients can add Event-MonitoredItems");
41503 result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
41504 UA_DataValue_clear(p: &v);
41505 return;
41506 }
41507
41508 /* If the 'SubscribeToEvents' bit of EventNotifier attribute is
41509 * zero, then the object cannot be subscribed to monitor events */
41510 if(!v.hasValue || !v.value.data) {
41511 result->statusCode = UA_STATUSCODE_BADINTERNALERROR;
41512 UA_DataValue_clear(p: &v);
41513 return;
41514 }
41515 UA_Byte eventNotifierValue = *((UA_Byte *)v.value.data);
41516 if((eventNotifierValue & 0x01) != 1) {
41517 result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED;
41518 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41519 "Could not create a MonitoredItem as the "
41520 "'SubscribeToEvents' bit of the EventNotifier "
41521 "attribute is not set");
41522 UA_DataValue_clear(p: &v);
41523 return;
41524 }
41525 }
41526#endif
41527
41528 const UA_DataType *valueType = v.value.type;
41529 UA_DataValue_clear(p: &v);
41530
41531 /* Allocate the MonitoredItem */
41532 UA_MonitoredItem *newMon = NULL;
41533 if(cmc->sub) {
41534 newMon = (UA_MonitoredItem*)UA_malloc(size: sizeof(UA_MonitoredItem));
41535 } else {
41536 UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*)
41537 UA_malloc(size: sizeof(UA_LocalMonitoredItem));
41538 if(localMon) {
41539 /* Set special values only for the LocalMonitoredItem */
41540 localMon->context = cmc->context;
41541 localMon->callback.dataChangeCallback = cmc->dataChangeCallback;
41542 }
41543 newMon = &localMon->monitoredItem;
41544 }
41545 if(!newMon) {
41546 result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY;
41547 return;
41548 }
41549
41550 /* Initialize the MonitoredItem */
41551 UA_MonitoredItem_init(mon: newMon);
41552 newMon->subscription = cmc->sub; /* Can be NULL for local MonitoredItems */
41553 newMon->timestampsToReturn = cmc->timestampsToReturn;
41554 result->statusCode |= UA_ReadValueId_copy(src: &request->itemToMonitor,
41555 dst: &newMon->itemToMonitor);
41556 result->statusCode |= UA_MonitoringParameters_copy(src: &request->requestedParameters,
41557 dst: &newMon->parameters);
41558 result->statusCode |= checkAdjustMonitoredItemParams(server, session, mon: newMon,
41559 valueType, params: &newMon->parameters);
41560#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
41561 result->statusCode |= checkEventFilterParam(server, session, mon: newMon,
41562 params: &newMon->parameters, result);
41563#endif
41564 if(result->statusCode != UA_STATUSCODE_GOOD) {
41565 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41566 "Could not create a MonitoredItem "
41567 "with StatusCode %s",
41568 UA_StatusCode_name(result->statusCode));
41569 UA_MonitoredItem_delete(server, monitoredItem: newMon);
41570 return;
41571 }
41572
41573 /* Initialize the value status so the first sample always passes the filter */
41574 newMon->lastValue.hasStatus = true;
41575 newMon->lastValue.status = ~(UA_StatusCode)0;
41576
41577 /* Register the Monitoreditem in the server and subscription */
41578 UA_Server_registerMonitoredItem(server, mon: newMon);
41579
41580 /* Activate the MonitoredItem */
41581 result->statusCode |=
41582 UA_MonitoredItem_setMonitoringMode(server, mon: newMon, monitoringMode: request->monitoringMode);
41583 if(result->statusCode != UA_STATUSCODE_GOOD) {
41584 UA_MonitoredItem_delete(server, monitoredItem: newMon);
41585 return;
41586 }
41587
41588 /* Prepare the response */
41589 result->revisedSamplingInterval = newMon->parameters.samplingInterval;
41590 result->revisedQueueSize = newMon->parameters.queueSize;
41591 result->monitoredItemId = newMon->monitoredItemId;
41592
41593 /* If the sampling interval is negative (the sampling callback is called
41594 * from within the publishing callback), return the publishing interval of
41595 * the Subscription. Note that we only use the cyclic callback of the
41596 * Subscription. So if the Subscription publishing interval is modified,
41597 * this also impacts this MonitoredItem. */
41598 if(result->revisedSamplingInterval < 0.0 && cmc->sub)
41599 result->revisedSamplingInterval = cmc->sub->publishingInterval;
41600
41601 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, cmc->sub,
41602 "MonitoredItem %" PRIi32 " | "
41603 "Created the MonitoredItem "
41604 "(Sampling Interval: %.2fms, Queue Size: %lu)",
41605 newMon->monitoredItemId,
41606 newMon->parameters.samplingInterval,
41607 (unsigned long)newMon->parameters.queueSize);
41608}
41609
41610void
41611Service_CreateMonitoredItems(UA_Server *server, UA_Session *session,
41612 const UA_CreateMonitoredItemsRequest *request,
41613 UA_CreateMonitoredItemsResponse *response) {
41614 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41615 "Processing CreateMonitoredItemsRequest");
41616 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41617
41618 if(server->config.maxMonitoredItemsPerCall != 0 &&
41619 request->itemsToCreateSize > server->config.maxMonitoredItemsPerCall) {
41620 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41621 return;
41622 }
41623
41624 /* Check if the timestampstoreturn is valid */
41625 struct createMonContext cmc;
41626 cmc.timestampsToReturn = request->timestampsToReturn;
41627 if(cmc.timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
41628 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
41629 return;
41630 }
41631
41632 /* Find the subscription */
41633 cmc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41634 if(!cmc.sub) {
41635 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41636 return;
41637 }
41638
41639 /* Reset the subscription lifetime */
41640 cmc.sub->currentLifetimeCount = 0;
41641
41642 response->responseHeader.serviceResult =
41643 UA_Server_processServiceOperations(server, session,
41644 operationCallback: (UA_ServiceOperation)Operation_CreateMonitoredItem,
41645 context: &cmc, requestOperations: &request->itemsToCreateSize,
41646 requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST],
41647 responseOperations: &response->resultsSize,
41648 responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]);
41649}
41650
41651UA_MonitoredItemCreateResult
41652UA_Server_createDataChangeMonitoredItem(UA_Server *server,
41653 UA_TimestampsToReturn timestampsToReturn,
41654 const UA_MonitoredItemCreateRequest item,
41655 void *monitoredItemContext,
41656 UA_Server_DataChangeNotificationCallback callback) {
41657 struct createMonContext cmc;
41658 cmc.sub = NULL;
41659 cmc.context = monitoredItemContext;
41660 cmc.dataChangeCallback = callback;
41661 cmc.timestampsToReturn = timestampsToReturn;
41662
41663 UA_MonitoredItemCreateResult result;
41664 UA_MonitoredItemCreateResult_init(p: &result);
41665 UA_LOCK(&server->serviceMutex);
41666 Operation_CreateMonitoredItem(server, session: &server->adminSession, cmc: &cmc, request: &item, result: &result);
41667 UA_UNLOCK(&server->serviceMutex);
41668 return result;
41669}
41670
41671static void
41672Operation_ModifyMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
41673 const UA_MonitoredItemModifyRequest *request,
41674 UA_MonitoredItemModifyResult *result) {
41675 /* Get the MonitoredItem */
41676 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->monitoredItemId);
41677 if(!mon) {
41678 result->statusCode = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41679 return;
41680 }
41681
41682 /* Make local copy of the settings */
41683 UA_MonitoringParameters params;
41684 result->statusCode =
41685 UA_MonitoringParameters_copy(src: &request->requestedParameters, dst: &params);
41686 if(result->statusCode != UA_STATUSCODE_GOOD)
41687 return;
41688
41689 /* Read the current value to test if filters are possible.
41690 * Can return an empty value (v.value.type == NULL). */
41691 UA_DataValue v =
41692 UA_Server_readWithSession(server, session, item: &mon->itemToMonitor,
41693 timestampsToReturn: mon->timestampsToReturn);
41694
41695 /* Verify and adjust the new parameters. This still leaves the original
41696 * MonitoredItem untouched. */
41697 result->statusCode =
41698 checkAdjustMonitoredItemParams(server, session, mon,
41699 valueType: v.value.type, params: &params);
41700 UA_DataValue_clear(p: &v);
41701 if(result->statusCode != UA_STATUSCODE_GOOD) {
41702 UA_MonitoringParameters_clear(p: &params);
41703 return;
41704 }
41705
41706 /* Store the old sampling interval */
41707 UA_Double oldSamplingInterval = mon->parameters.samplingInterval;
41708
41709 /* Move over the new settings */
41710 UA_MonitoringParameters_clear(p: &mon->parameters);
41711 mon->parameters = params;
41712
41713 /* Re-register the callback if necessary */
41714 if(oldSamplingInterval != mon->parameters.samplingInterval) {
41715 UA_MonitoredItem_unregisterSampling(server, mon);
41716 result->statusCode =
41717 UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: mon->monitoringMode);
41718 }
41719
41720 result->revisedSamplingInterval = mon->parameters.samplingInterval;
41721 result->revisedQueueSize = mon->parameters.queueSize;
41722
41723 /* Remove some notifications if the queue is now too small */
41724 UA_MonitoredItem_ensureQueueSpace(server, mon);
41725
41726 /* Remove the overflow bits if the queue has now a size of 1 */
41727 UA_MonitoredItem_removeOverflowInfoBits(mon);
41728
41729 /* If the sampling interval is negative (the sampling callback is called
41730 * from within the publishing callback), return the publishing interval of
41731 * the Subscription. Note that we only use the cyclic callback of the
41732 * Subscription. So if the Subscription publishing interval is modified,
41733 * this also impacts this MonitoredItem. */
41734 if(result->revisedSamplingInterval < 0.0 && mon->subscription)
41735 result->revisedSamplingInterval = mon->subscription->publishingInterval;
41736
41737 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
41738 "MonitoredItem %" PRIi32 " | "
41739 "Modified the MonitoredItem "
41740 "(Sampling Interval: %fms, Queue Size: %lu)",
41741 mon->monitoredItemId,
41742 mon->parameters.samplingInterval,
41743 (unsigned long)mon->queueSize);
41744}
41745
41746void
41747Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session,
41748 const UA_ModifyMonitoredItemsRequest *request,
41749 UA_ModifyMonitoredItemsResponse *response) {
41750 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41751 "Processing ModifyMonitoredItemsRequest");
41752 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41753
41754 if(server->config.maxMonitoredItemsPerCall != 0 &&
41755 request->itemsToModifySize > server->config.maxMonitoredItemsPerCall) {
41756 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41757 return;
41758 }
41759
41760 /* Check if the timestampstoreturn is valid */
41761 if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) {
41762 response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID;
41763 return;
41764 }
41765
41766 /* Get the subscription */
41767 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41768 if(!sub) {
41769 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41770 return;
41771 }
41772
41773 sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
41774
41775 response->responseHeader.serviceResult =
41776 UA_Server_processServiceOperations(server, session,
41777 operationCallback: (UA_ServiceOperation)Operation_ModifyMonitoredItem,
41778 context: sub, requestOperations: &request->itemsToModifySize,
41779 requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST],
41780 responseOperations: &response->resultsSize,
41781 responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]);
41782}
41783
41784struct setMonitoringContext {
41785 UA_Subscription *sub;
41786 UA_MonitoringMode monitoringMode;
41787};
41788
41789static void
41790Operation_SetMonitoringMode(UA_Server *server, UA_Session *session,
41791 struct setMonitoringContext *smc,
41792 const UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
41793 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub: smc->sub, monitoredItemId: *monitoredItemId);
41794 if(!mon) {
41795 *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41796 return;
41797 }
41798 *result = UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: smc->monitoringMode);
41799}
41800
41801void
41802Service_SetMonitoringMode(UA_Server *server, UA_Session *session,
41803 const UA_SetMonitoringModeRequest *request,
41804 UA_SetMonitoringModeResponse *response) {
41805 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing SetMonitoringMode");
41806 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41807
41808 if(server->config.maxMonitoredItemsPerCall != 0 &&
41809 request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
41810 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41811 return;
41812 }
41813
41814 /* Get the subscription */
41815 struct setMonitoringContext smc;
41816 smc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41817 if(!smc.sub) {
41818 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41819 return;
41820 }
41821
41822 smc.sub->currentLifetimeCount = 0; /* Reset the subscription lifetime */
41823
41824 smc.monitoringMode = request->monitoringMode;
41825 response->responseHeader.serviceResult =
41826 UA_Server_processServiceOperations(server, session,
41827 operationCallback: (UA_ServiceOperation)Operation_SetMonitoringMode,
41828 context: &smc, requestOperations: &request->monitoredItemIdsSize,
41829 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41830 responseOperations: &response->resultsSize,
41831 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
41832}
41833
41834static void
41835Operation_DeleteMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub,
41836 const UA_UInt32 *monitoredItemId, UA_StatusCode *result) {
41837 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41838 UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: *monitoredItemId);
41839 if(!mon) {
41840 *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41841 return;
41842 }
41843 UA_MonitoredItem_delete(server, monitoredItem: mon);
41844}
41845
41846void
41847Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session,
41848 const UA_DeleteMonitoredItemsRequest *request,
41849 UA_DeleteMonitoredItemsResponse *response) {
41850 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
41851 "Processing DeleteMonitoredItemsRequest");
41852 UA_LOCK_ASSERT(&server->serviceMutex, 1);
41853
41854 if(server->config.maxMonitoredItemsPerCall != 0 &&
41855 request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) {
41856 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
41857 return;
41858 }
41859
41860 /* Get the subscription */
41861 UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId);
41862 if(!sub) {
41863 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
41864 return;
41865 }
41866
41867 /* Reset the subscription lifetime */
41868 sub->currentLifetimeCount = 0;
41869
41870 response->responseHeader.serviceResult =
41871 UA_Server_processServiceOperations(server, session,
41872 operationCallback: (UA_ServiceOperation)Operation_DeleteMonitoredItem,
41873 context: sub, requestOperations: &request->monitoredItemIdsSize,
41874 requestOperationsType: &UA_TYPES[UA_TYPES_UINT32],
41875 responseOperations: &response->resultsSize,
41876 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
41877}
41878
41879UA_StatusCode
41880UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId) {
41881 UA_LOCK(&server->serviceMutex);
41882 UA_MonitoredItem *mon, *mon_tmp;
41883 LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) {
41884 if(mon->monitoredItemId != monitoredItemId)
41885 continue;
41886 UA_MonitoredItem_delete(server, monitoredItem: mon);
41887 UA_UNLOCK(&server->serviceMutex);
41888 return UA_STATUSCODE_GOOD;
41889 }
41890 UA_UNLOCK(&server->serviceMutex);
41891 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
41892}
41893
41894#endif /* UA_ENABLE_SUBSCRIPTIONS */
41895
41896/**** amalgamated original file "/src/server/ua_services_securechannel.c" ****/
41897
41898/* This Source Code Form is subject to the terms of the Mozilla Public
41899 * License, v. 2.0. If a copy of the MPL was not distributed with this
41900 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
41901 *
41902 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
41903 * Copyright 2014, 2017 (c) Florian Palm
41904 * Copyright 2015 (c) Oleksiy Vasylyev
41905 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
41906 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
41907 * Copyright 2023 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Phuong Nguyen)
41908 */
41909
41910
41911#ifndef container_of
41912#define container_of(ptr, type, member) \
41913 (type *)((uintptr_t)ptr - offsetof(type,member))
41914#endif
41915
41916static void
41917removeSecureChannelCallback(void *_, channel_entry *entry) {
41918 UA_SecureChannel_close(channel: &entry->channel);
41919}
41920
41921/* Half-closes the channel. Will be completely closed / deleted in a deferred
41922 * callback. Deferring is necessary so we don't remove lists that are still
41923 * processed upwards the call stack. */
41924static void
41925removeSecureChannel(UA_Server *server, channel_entry *entry,
41926 UA_DiagnosticEvent event) {
41927 if(entry->channel.state == UA_SECURECHANNELSTATE_CLOSING)
41928 return;
41929 entry->channel.state = UA_SECURECHANNELSTATE_CLOSING;
41930
41931 /* Detach from the connection and close the connection */
41932 if(entry->channel.connection) {
41933 if(entry->channel.connection->state != UA_CONNECTIONSTATE_CLOSED)
41934 entry->channel.connection->close(entry->channel.connection);
41935 UA_Connection_detachSecureChannel(connection: entry->channel.connection);
41936 }
41937
41938 /* Detach the channel */
41939 TAILQ_REMOVE(&server->channels, entry, pointers);
41940
41941 /* Update the statistics */
41942 UA_SecureChannelStatistics *scs = &server->secureChannelStatistics;
41943 UA_atomic_subSize(addr: &scs->currentChannelCount, decrease: 1);
41944 switch(event) {
41945 case UA_DIAGNOSTICEVENT_CLOSE:
41946 break;
41947 case UA_DIAGNOSTICEVENT_TIMEOUT:
41948 UA_atomic_addSize(addr: &scs->channelTimeoutCount, increase: 1);
41949 break;
41950 case UA_DIAGNOSTICEVENT_PURGE:
41951 UA_atomic_addSize(addr: &scs->channelPurgeCount, increase: 1);
41952 break;
41953 case UA_DIAGNOSTICEVENT_REJECT:
41954 case UA_DIAGNOSTICEVENT_SECURITYREJECT:
41955 UA_atomic_addSize(addr: &scs->rejectedChannelCount, increase: 1);
41956 break;
41957 case UA_DIAGNOSTICEVENT_ABORT:
41958 UA_atomic_addSize(addr: &scs->channelAbortCount, increase: 1);
41959 break;
41960 default:
41961 UA_assert(false);
41962 break;
41963 }
41964
41965 /* Add a delayed callback to remove the channel when the currently
41966 * scheduled jobs have completed */
41967 entry->cleanupCallback.callback = (UA_ApplicationCallback)removeSecureChannelCallback;
41968 entry->cleanupCallback.application = NULL;
41969 entry->cleanupCallback.data = entry;
41970 entry->cleanupCallback.nextTime = UA_DateTime_nowMonotonic() + 1;
41971 entry->cleanupCallback.interval = 0; /* Remove the structure */
41972 UA_Timer_addTimerEntry(t: &server->timer, te: &entry->cleanupCallback, NULL);
41973}
41974
41975void
41976UA_Server_deleteSecureChannels(UA_Server *server) {
41977 channel_entry *entry, *temp;
41978 TAILQ_FOREACH_SAFE(entry, &server->channels, pointers, temp)
41979 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_CLOSE);
41980}
41981
41982/* remove channels that were not renewed or who have no connection attached */
41983void
41984UA_Server_cleanupTimedOutSecureChannels(UA_Server *server,
41985 UA_DateTime nowMonotonic) {
41986 channel_entry *entry, *temp;
41987 TAILQ_FOREACH_SAFE(entry, &server->channels, pointers, temp) {
41988 /* The channel was closed internally */
41989 if(entry->channel.state == UA_SECURECHANNELSTATE_CLOSED ||
41990 !entry->channel.connection) {
41991 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_CLOSE);
41992 continue;
41993 }
41994
41995 /* Is the SecurityToken already created? */
41996 if(entry->channel.securityToken.createdAt == 0) {
41997 /* No -> channel is still in progress of being opened, do not remove */
41998 continue;
41999 }
42000
42001 /* Has the SecurityToken timed out? */
42002 UA_DateTime timeout =
42003 entry->channel.securityToken.createdAt +
42004 (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
42005
42006 /* There is a new token. But it has not been used by the client so far.
42007 * Do the rollover now instead of shutting the channel down.
42008 *
42009 * Part 4, 5.5.2 says: Servers shall use the existing SecurityToken to
42010 * secure outgoing Messages until the SecurityToken expires or the
42011 * Server receives a Message secured with a new SecurityToken.*/
42012 if(timeout < nowMonotonic &&
42013 entry->channel.renewState == UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER) {
42014 /* Compare with the rollover in checkSymHeader */
42015 entry->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
42016 entry->channel.securityToken = entry->channel.altSecurityToken;
42017 UA_ChannelSecurityToken_init(p: &entry->channel.altSecurityToken);
42018 UA_SecureChannel_generateLocalKeys(channel: &entry->channel);
42019 generateRemoteKeys(channel: &entry->channel);
42020
42021 /* Use the timeout of the new SecurityToken */
42022 timeout = entry->channel.securityToken.createdAt +
42023 (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC);
42024 }
42025
42026 if(timeout < nowMonotonic) {
42027 UA_LOG_INFO_CHANNEL(&server->config.logger, &entry->channel,
42028 "SecureChannel has timed out");
42029 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_TIMEOUT);
42030 }
42031 }
42032}
42033
42034/* remove the first channel that has no session attached */
42035static UA_Boolean
42036purgeFirstChannelWithoutSession(UA_Server *server) {
42037 channel_entry *entry;
42038 TAILQ_FOREACH(entry, &server->channels, pointers) {
42039 if(SLIST_FIRST(&entry->channel.sessions))
42040 continue;
42041 UA_LOG_INFO_CHANNEL(&server->config.logger, &entry->channel,
42042 "Channel was purged since maxSecureChannels was "
42043 "reached and channel had no session attached");
42044 removeSecureChannel(server, entry, event: UA_DIAGNOSTICEVENT_PURGE);
42045 return true;
42046 }
42047 return false;
42048}
42049
42050UA_StatusCode
42051UA_Server_createSecureChannel(UA_Server *server, UA_Connection *connection) {
42052 /* connection already has a channel attached. */
42053 if(connection->channel != NULL)
42054 return UA_STATUSCODE_BADINTERNALERROR;
42055
42056 /* Check if there exists a free SC, otherwise try to purge one SC without a
42057 * session the purge has been introduced to pass CTT, it is not clear what
42058 * strategy is expected here */
42059 if((server->secureChannelStatistics.currentChannelCount >=
42060 server->config.maxSecureChannels) &&
42061 !purgeFirstChannelWithoutSession(server))
42062 return UA_STATUSCODE_BADOUTOFMEMORY;
42063
42064 channel_entry *entry = (channel_entry *)UA_malloc(size: sizeof(channel_entry));
42065 if(!entry)
42066 return UA_STATUSCODE_BADOUTOFMEMORY;
42067
42068 /* Channel state is closed (0) */
42069 /* TODO: Use the connection config from the correct network layer */
42070 UA_SecureChannel_init(channel: &entry->channel,
42071 config: &server->config.networkLayers[0].localConnectionConfig);
42072 entry->channel.certificateVerification = &server->config.certificateVerification;
42073 entry->channel.processOPNHeader = UA_Server_configSecureChannel;
42074
42075 TAILQ_INSERT_TAIL(&server->channels, entry, pointers);
42076 UA_Connection_attachSecureChannel(connection, channel: &entry->channel);
42077 server->secureChannelStatistics.currentChannelCount++;
42078 server->secureChannelStatistics.cumulatedChannelCount++;
42079 return UA_STATUSCODE_GOOD;
42080}
42081
42082/* Get pointer to leaf certificate of a specified valid chain of DER encoded
42083 * certificates */
42084static void
42085getLeafCertificate(const UA_ByteString *chain, UA_ByteString *leaf) {
42086 /* Detect DER encoded X.509 v3 certificate. If the DER detection fails,
42087 * return the entire chain.
42088 *
42089 * The OPC UA standard requires this to be DER. But we also allow other
42090 * formats like PEM. Afterwards it depends on the crypto backend to parse
42091 * it. mbedTLS and OpenSSL detect the format automatically. */
42092 if(chain->length < 4 || chain->data[0] != 0x30 || chain->data[1] != 0x82) {
42093 *leaf = *chain;
42094 return;
42095 }
42096
42097 /* The certificate length is encoded in the next 2 bytes. */
42098 size_t leafLen = 4; /* Magic numbers + length bytes */
42099 leafLen += (size_t)(((uint16_t)chain->data[2]) << 8);
42100 leafLen += chain->data[3];
42101
42102 /* Length consistency check */
42103 if(leafLen > chain->length)
42104 return;
42105
42106 leaf->data = chain->data;
42107 leaf->length = leafLen;
42108}
42109
42110UA_StatusCode
42111UA_Server_configSecureChannel(void *application, UA_SecureChannel *channel,
42112 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
42113 /* Iterate over available endpoints and choose the correct one */
42114 UA_SecurityPolicy *securityPolicy = NULL;
42115 UA_Server *const server = (UA_Server *const) application;
42116 for(size_t i = 0; i < server->config.securityPoliciesSize; ++i) {
42117 UA_SecurityPolicy *policy = &server->config.securityPolicies[i];
42118 if(!UA_ByteString_equal(string1: &asymHeader->securityPolicyUri, string2: &policy->policyUri))
42119 continue;
42120
42121 UA_StatusCode retval = policy->asymmetricModule.
42122 compareCertificateThumbprint(policy, &asymHeader->receiverCertificateThumbprint);
42123 if(retval != UA_STATUSCODE_GOOD)
42124 continue;
42125
42126 /* We found the correct policy (except for security mode). The endpoint
42127 * needs to be selected by the client / server to match the security
42128 * mode in the endpoint for the session. */
42129 securityPolicy = policy;
42130 break;
42131 }
42132
42133 if(!securityPolicy)
42134 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
42135
42136 /* If the sender provides a chain of certificates then we shall extract the
42137 * ApplicationInstanceCertificate. and ignore the extra bytes. See also: OPC
42138 * UA Part 6, V1.04, 6.7.2.3 Security Header, Table 42 - Asymmetric
42139 * algorithm Security header */
42140 UA_ByteString appInstanceCertificate = UA_BYTESTRING_NULL;
42141 getLeafCertificate(chain: &asymHeader->senderCertificate, leaf: &appInstanceCertificate);
42142
42143 /* Create the channel context and parse the sender (remote) certificate used for the
42144 * secureChannel. */
42145 UA_StatusCode retval =
42146 UA_SecureChannel_setSecurityPolicy(channel, securityPolicy,
42147 remoteCertificate: &appInstanceCertificate);
42148 if(retval != UA_STATUSCODE_GOOD)
42149 return retval;
42150
42151 channel->securityToken.tokenId = server->lastTokenId++;
42152 return UA_STATUSCODE_GOOD;
42153}
42154
42155static UA_StatusCode
42156UA_SecureChannelManager_open(UA_Server *server, UA_SecureChannel *channel,
42157 const UA_OpenSecureChannelRequest *request,
42158 UA_OpenSecureChannelResponse *response) {
42159 if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT) {
42160 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42161 "Called open on already open or closed channel");
42162 return UA_STATUSCODE_BADINTERNALERROR;
42163 }
42164
42165 if(request->securityMode != UA_MESSAGESECURITYMODE_NONE &&
42166 UA_ByteString_equal(string1: &channel->securityPolicy->policyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
42167 return UA_STATUSCODE_BADSECURITYMODEREJECTED;
42168 }
42169
42170 channel->securityMode = request->securityMode;
42171 channel->securityToken.channelId = server->lastChannelId++;
42172 channel->securityToken.createdAt = UA_DateTime_nowMonotonic();
42173
42174 /* Set the lifetime. Lifetime 0 -> set the maximum possible */
42175 channel->securityToken.revisedLifetime =
42176 (request->requestedLifetime > server->config.maxSecurityTokenLifetime) ?
42177 server->config.maxSecurityTokenLifetime : request->requestedLifetime;
42178 if(channel->securityToken.revisedLifetime == 0)
42179 channel->securityToken.revisedLifetime = server->config.maxSecurityTokenLifetime;
42180
42181 UA_StatusCode retval = UA_ByteString_copy(src: &request->clientNonce, dst: &channel->remoteNonce);
42182 if(retval != UA_STATUSCODE_GOOD)
42183 return retval;
42184
42185 /* Generate the nonce. The syymmetric encryption keys are generated when the
42186 * first symmetric message is received */
42187 retval = UA_SecureChannel_generateLocalNonce(channel);
42188 if(retval != UA_STATUSCODE_GOOD)
42189 return retval;
42190
42191 /* Set the response. The token will be revolved to the new token when the
42192 * first symmetric messages is received. */
42193 response->securityToken = channel->securityToken;
42194 response->securityToken.createdAt = UA_DateTime_now(); /* Only for sending */
42195 response->responseHeader.timestamp = response->securityToken.createdAt;
42196 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
42197 retval = UA_ByteString_copy(src: &channel->localNonce, dst: &response->serverNonce);
42198 if(retval != UA_STATUSCODE_GOOD)
42199 return retval;
42200
42201 /* The channel is open */
42202 channel->state = UA_SECURECHANNELSTATE_OPEN;
42203
42204 /* For the first revolve */
42205 channel->renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER;
42206 channel->altSecurityToken = channel->securityToken;
42207 channel->securityToken.tokenId = 0;
42208 return UA_STATUSCODE_GOOD;
42209}
42210
42211static UA_StatusCode
42212UA_SecureChannelManager_renew(UA_Server *server, UA_SecureChannel *channel,
42213 const UA_OpenSecureChannelRequest *request,
42214 UA_OpenSecureChannelResponse *response) {
42215 if(channel->state != UA_SECURECHANNELSTATE_OPEN) {
42216 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42217 "Called renew on channel which is not open");
42218 return UA_STATUSCODE_BADINTERNALERROR;
42219 }
42220
42221 /* Check whether the nonce was reused */
42222 if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE &&
42223 UA_ByteString_equal(string1: &channel->remoteNonce, string2: &request->clientNonce)) {
42224 UA_LOG_ERROR_CHANNEL(&server->config.logger, channel,
42225 "The client reused the last nonce");
42226 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
42227 }
42228
42229 /* Create a new SecurityToken. Will be switched over when the first message
42230 * is received. */
42231 channel->altSecurityToken = channel->securityToken;
42232 channel->altSecurityToken.tokenId = server->lastTokenId++;
42233 channel->altSecurityToken.createdAt = UA_DateTime_nowMonotonic();
42234 channel->altSecurityToken.revisedLifetime =
42235 (request->requestedLifetime > server->config.maxSecurityTokenLifetime) ?
42236 server->config.maxSecurityTokenLifetime : request->requestedLifetime;
42237 if(channel->altSecurityToken.revisedLifetime == 0) /* lifetime 0 -> return the max lifetime */
42238 channel->altSecurityToken.revisedLifetime = server->config.maxSecurityTokenLifetime;
42239
42240 /* Replace the nonces */
42241 UA_ByteString_clear(p: &channel->remoteNonce);
42242 UA_StatusCode retval = UA_ByteString_copy(src: &request->clientNonce, dst: &channel->remoteNonce);
42243 if(retval != UA_STATUSCODE_GOOD)
42244 return retval;
42245
42246 retval = UA_SecureChannel_generateLocalNonce(channel);
42247 if(retval != UA_STATUSCODE_GOOD)
42248 return retval;
42249
42250 /* Set the response */
42251 response->securityToken = channel->altSecurityToken;
42252 response->securityToken.createdAt = UA_DateTime_now(); /* Only for sending */
42253 response->responseHeader.requestHandle = request->requestHeader.requestHandle;
42254 retval = UA_ByteString_copy(src: &channel->localNonce, dst: &response->serverNonce);
42255 if(retval != UA_STATUSCODE_GOOD)
42256 return retval;
42257
42258 channel->renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER;
42259 return UA_STATUSCODE_GOOD;
42260}
42261
42262void
42263UA_Server_closeSecureChannel(UA_Server *server, UA_SecureChannel *channel,
42264 UA_DiagnosticEvent event) {
42265 removeSecureChannel(server, container_of(channel, channel_entry, channel), event);
42266}
42267
42268void
42269Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel,
42270 const UA_OpenSecureChannelRequest *request,
42271 UA_OpenSecureChannelResponse *response) {
42272 if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_RENEW) {
42273 /* Renew the channel */
42274 response->responseHeader.serviceResult =
42275 UA_SecureChannelManager_renew(server, channel, request, response);
42276
42277 /* Logging */
42278 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
42279 UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
42280 UA_LOG_INFO_CHANNEL(&server->config.logger, channel, "SecureChannel renewed "
42281 "with a revised lifetime of %.2fs", lifetime);
42282 } else {
42283 UA_LOG_DEBUG_CHANNEL(&server->config.logger, channel,
42284 "Renewing SecureChannel failed");
42285 }
42286 return;
42287 }
42288
42289 /* Must be ISSUE or RENEW */
42290 if(request->requestType != UA_SECURITYTOKENREQUESTTYPE_ISSUE) {
42291 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
42292 return;
42293 }
42294
42295 /* Open the channel */
42296 response->responseHeader.serviceResult =
42297 UA_SecureChannelManager_open(server, channel, request, response);
42298
42299 /* Logging */
42300 if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) {
42301 UA_Float lifetime = (UA_Float)response->securityToken.revisedLifetime / 1000;
42302 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
42303 "SecureChannel opened with SecurityPolicy %.*s "
42304 "and a revised lifetime of %.2fs",
42305 (int)channel->securityPolicy->policyUri.length,
42306 channel->securityPolicy->policyUri.data, lifetime);
42307 } else {
42308 UA_LOG_INFO_CHANNEL(&server->config.logger, channel,
42309 "Opening a SecureChannel failed");
42310 }
42311}
42312
42313/* The server does not send a CloseSecureChannel response */
42314void
42315Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) {
42316 UA_LOG_INFO_CHANNEL(&server->config.logger, channel, "CloseSecureChannel");
42317 removeSecureChannel(server, container_of(channel, channel_entry, channel),
42318 event: UA_DIAGNOSTICEVENT_CLOSE);
42319}
42320
42321/**** amalgamated original file "/src/server/ua_services_nodemanagement.c" ****/
42322
42323/* This Source Code Form is subject to the terms of the Mozilla Public
42324 * License, v. 2.0. If a copy of the MPL was not distributed with this
42325 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
42326 *
42327 * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
42328 * Copyright 2014-2017 (c) Florian Palm
42329 * Copyright 2015-2016 (c) Sten Grüner
42330 * Copyright 2015-2016 (c) Chris Iatrou
42331 * Copyright 2015-2016 (c) Oleksiy Vasylyev
42332 * Copyright 2017 (c) Julian Grothoff
42333 * Copyright 2016 (c) LEvertz
42334 * Copyright 2016 (c) Lorenz Haas
42335 * Copyright 2017 (c) frax2222
42336 * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
42337 * Copyright 2017 (c) Christian von Arnim
42338 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
42339 * Copyright 2017 (c) Henrik Norrman
42340 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
42341 */
42342
42343
42344static UA_StatusCode
42345setMethodNode_callback(UA_Server *server,
42346 const UA_NodeId methodNodeId,
42347 UA_MethodCallback methodCallback);
42348
42349/*********************/
42350/* Edit Node Context */
42351/*********************/
42352
42353UA_StatusCode
42354UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId,
42355 void **nodeContext) {
42356 UA_LOCK(&server->serviceMutex);
42357 UA_StatusCode retval = getNodeContext(server, nodeId, nodeContext);
42358 UA_UNLOCK(&server->serviceMutex);
42359 return retval;
42360}
42361
42362UA_StatusCode
42363getNodeContext(UA_Server *server, UA_NodeId nodeId,
42364 void **nodeContext) {
42365 const UA_Node *node = UA_NODESTORE_GET(server, &nodeId);
42366 if(!node)
42367 return UA_STATUSCODE_BADNODEIDUNKNOWN;
42368 *nodeContext = node->head.context;
42369 UA_NODESTORE_RELEASE(server, node);
42370 return UA_STATUSCODE_GOOD;
42371}
42372
42373static UA_StatusCode
42374setDeconstructedNode(UA_Server *server, UA_Session *session,
42375 UA_NodeHead *head, void *context) {
42376 head->constructed = false;
42377 return UA_STATUSCODE_GOOD;
42378}
42379
42380static UA_StatusCode
42381setConstructedNodeContext(UA_Server *server, UA_Session *session,
42382 UA_NodeHead *head, void *context) {
42383 head->context = context;
42384 head->constructed = true;
42385 return UA_STATUSCODE_GOOD;
42386}
42387
42388static UA_StatusCode
42389editNodeContext(UA_Server *server, UA_Session* session,
42390 UA_NodeHead *head, void *context) {
42391 head->context = context;
42392 return UA_STATUSCODE_GOOD;
42393}
42394
42395UA_StatusCode
42396setNodeContext(UA_Server *server, UA_NodeId nodeId,
42397 void *nodeContext) {
42398 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
42399 callback: (UA_EditNodeCallback)editNodeContext, data: nodeContext);
42400}
42401
42402UA_StatusCode
42403UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId,
42404 void *nodeContext) {
42405 UA_LOCK(&server->serviceMutex);
42406 UA_StatusCode retval = setNodeContext(server, nodeId, nodeContext);
42407 UA_UNLOCK(&server->serviceMutex);
42408 return retval;
42409}
42410
42411static UA_StatusCode
42412checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
42413 const UA_NodeId *nodeId);
42414
42415/**********************/
42416/* Consistency Checks */
42417/**********************/
42418
42419#define UA_PARENT_REFERENCES_COUNT 2
42420
42421const UA_NodeId parentReferences[UA_PARENT_REFERENCES_COUNT] = {
42422 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}},
42423 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}
42424};
42425
42426static void
42427logAddNode(const UA_Logger *logger, UA_Session *session,
42428 const UA_NodeId *nodeId, const char *msg) {
42429 UA_LOG_NODEID_INFO(nodeId,
42430 UA_LOG_INFO_SESSION(logger, session, "AddNode (%.*s): %s",
42431 (int)nodeIdStr.length, nodeIdStr.data, msg));
42432}
42433
42434/* Check if the requested parent node exists, has the right node class and is
42435 * referenced with an allowed (hierarchical) reference type. For "type" nodes,
42436 * only hasSubType references are allowed. */
42437static UA_StatusCode
42438checkParentReference(UA_Server *server, UA_Session *session, const UA_NodeHead *head,
42439 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) {
42440 /* Objects do not need a parent (e.g. mandatory/optional modellingrules).
42441 * Also, there are some variables which do not have parents, e.g.
42442 * EnumStrings, EnumValues */
42443 if((head->nodeClass == UA_NODECLASS_OBJECT ||
42444 head->nodeClass == UA_NODECLASS_VARIABLE) &&
42445 UA_NodeId_isNull(p: parentNodeId) && UA_NodeId_isNull(p: referenceTypeId))
42446 return UA_STATUSCODE_GOOD;
42447
42448 /* See if the parent exists */
42449 const UA_Node *parent = UA_NODESTORE_GET(server, parentNodeId);
42450 if(!parent) {
42451 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42452 msg: "Parent node not found");
42453 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
42454 }
42455
42456 UA_NodeClass parentNodeClass = parent->head.nodeClass;
42457 UA_NODESTORE_RELEASE(server, parent);
42458
42459 /* Check the referencetype exists */
42460 const UA_Node *referenceType = UA_NODESTORE_GET(server, referenceTypeId);
42461 if(!referenceType) {
42462 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42463 msg: "Reference type to the parent not found");
42464 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42465 }
42466
42467 /* Check if the referencetype is a reference type node */
42468 if(referenceType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
42469 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42470 msg: "Reference type to the parent is not a ReferenceTypeNode");
42471 UA_NODESTORE_RELEASE(server, referenceType);
42472 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42473 }
42474
42475 /* Check that the reference type is not abstract */
42476 UA_Boolean referenceTypeIsAbstract = referenceType->referenceTypeNode.isAbstract;
42477 UA_NODESTORE_RELEASE(server, referenceType);
42478 if(referenceTypeIsAbstract == true) {
42479 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42480 msg: "Abstract reference type to the parent not allowed");
42481 return UA_STATUSCODE_BADREFERENCENOTALLOWED;
42482 }
42483
42484 /* Check hassubtype relation for type nodes */
42485 if(head->nodeClass == UA_NODECLASS_DATATYPE ||
42486 head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
42487 head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
42488 head->nodeClass == UA_NODECLASS_REFERENCETYPE) {
42489 /* Type needs hassubtype reference to the supertype */
42490 if(referenceType->referenceTypeNode.referenceTypeIndex !=
42491 UA_REFERENCETYPEINDEX_HASSUBTYPE) {
42492 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42493 msg: "Type nodes need to have a HasSubType reference to the parent");
42494 return UA_STATUSCODE_BADREFERENCENOTALLOWED;
42495 }
42496 /* Supertype needs to be of the same node type */
42497 if(parentNodeClass != head->nodeClass) {
42498 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42499 msg: "Type nodes needs to be of the same node "
42500 "type as their parent");
42501 return UA_STATUSCODE_BADPARENTNODEIDINVALID;
42502 }
42503 return UA_STATUSCODE_GOOD;
42504 }
42505
42506 /* Test if the referencetype is hierarchical */
42507 const UA_NodeId hierarchRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
42508 if(!isNodeInTree_singleRef(server, leafNode: referenceTypeId, nodeToFind: &hierarchRefs,
42509 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
42510 logAddNode(logger: &server->config.logger, session, nodeId: &head->nodeId,
42511 msg: "Reference type to the parent is not hierarchical");
42512 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
42513 }
42514
42515 return UA_STATUSCODE_GOOD;
42516}
42517
42518static UA_StatusCode
42519setDefaultValue(UA_Server *server, const UA_VariableNode *node) {
42520 /* Get the DataType */
42521 UA_StatusCode res = UA_STATUSCODE_GOOD;
42522 const UA_DataType *type = UA_Server_findDataType(server, typeId: &node->dataType);
42523 if(!type) {
42524 /* No description for the DataType found. It is possible that an
42525 * abstract DataType is used, e.g. UInteger. Browse to see if there is a
42526 * non-abstract subtype that can be used for the default value.
42527 *
42528 * Look up and downwards in the hierarchy. Some data types (e.g.
42529 * UtcTime) are derived from a non-abstract data type. This is then used
42530 * for the actual value, Use the first match. */
42531 UA_ReferenceTypeSet refs = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
42532 UA_ExpandedNodeId *typeCandidates = NULL;
42533 size_t typeCandidatesSize = 0;
42534 res = browseRecursive(server, startNodesSize: 1, startNodes: &node->dataType,
42535 browseDirection: UA_BROWSEDIRECTION_BOTH, refTypes: &refs,
42536 nodeClassMask: UA_NODECLASS_DATATYPE, false,
42537 resultsSize: &typeCandidatesSize, results: &typeCandidates);
42538 if(res != UA_STATUSCODE_GOOD)
42539 return res;
42540
42541 for(size_t i = 0; i < typeCandidatesSize; i++) {
42542 /* Skip BaseDataType (Variant). This is the root of the DataType
42543 * hierarchy. Variables of BaseDataType can be empty. */
42544 if(UA_NodeId_equal(n1: &UA_TYPES[UA_TYPES_VARIANT].typeId,
42545 n2: &typeCandidates[i].nodeId))
42546 continue;
42547 type = UA_Server_findDataType(server, typeId: &typeCandidates[i].nodeId);
42548 if(type)
42549 break;
42550 }
42551
42552 UA_Array_delete(p: typeCandidates, size: typeCandidatesSize,
42553 type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
42554 if(!type)
42555 return UA_STATUSCODE_BADTYPEMISMATCH;
42556 }
42557
42558 /* Set up the value with the default content */
42559 UA_Variant val;
42560 UA_Variant_init(p: &val);
42561 if(node->valueRank < 0) {
42562 /* Set a scalar */
42563 void *data = UA_new(type);
42564 if(!data)
42565 return UA_STATUSCODE_BADOUTOFMEMORY;
42566 UA_Variant_setScalar(v: &val, p: data, type);
42567 } else if(node->valueRank == 0) {
42568 /* Use an empty array of one dimension */
42569 UA_Variant_setArray(v: &val, NULL, arraySize: 0, type);
42570 } else {
42571 /* Write an array that matches the ArrayDimensions */
42572 res = UA_Array_copy(src: node->arrayDimensions, size: node->arrayDimensionsSize,
42573 dst: (void**)&val.arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
42574 if(res != UA_STATUSCODE_GOOD)
42575 return res;
42576 val.arrayDimensionsSize = node->arrayDimensionsSize;
42577
42578 /* No length restriction in the ArrayDimension -> use length 1 */
42579 size_t size = 1;
42580 for(size_t i = 0; i < val.arrayDimensionsSize; i++) {
42581 if(val.arrayDimensions[i] == 0)
42582 val.arrayDimensions[i] = 1;
42583 size *= val.arrayDimensions[i];
42584 }
42585
42586 /* Create the content array */
42587 void *data = UA_Array_new(size, type);
42588 if(!data) {
42589 UA_Variant_clear(p: &val);
42590 return UA_STATUSCODE_BADOUTOFMEMORY;
42591 }
42592
42593 val.data = data;
42594 val.arrayLength = size;
42595 val.type = type;
42596 }
42597
42598 /* Write the value */
42599 res = writeAttribute(server, session: &server->adminSession, nodeId: &node->head.nodeId,
42600 attributeId: UA_ATTRIBUTEID_VALUE, attr: &val, attr_type: &UA_TYPES[UA_TYPES_VARIANT]);
42601
42602 /* Clean up */
42603 UA_Variant_clear(p: &val);
42604 return res;
42605}
42606
42607static UA_StatusCode
42608typeCheckVariableNode(UA_Server *server, UA_Session *session,
42609 const UA_VariableNode *node,
42610 const UA_VariableTypeNode *vt) {
42611 /* Check the datatype against the vt */
42612 if(!compatibleDataTypes(server, dataType: &node->dataType, constraintDataType: &vt->dataType)) {
42613 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42614 msg: "The value of is incompatible with "
42615 "the datatype of the VariableType");
42616 return UA_STATUSCODE_BADTYPEMISMATCH;
42617 }
42618
42619 /* Check valueRank against array dimensions */
42620 if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank,
42621 arrayDimensionsSize: node->arrayDimensionsSize)) {
42622 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42623 msg: "The value rank of is incompatible with its array dimensions");
42624 return UA_STATUSCODE_BADTYPEMISMATCH;
42625 }
42626
42627 /* Check valueRank against the vt */
42628 if(!compatibleValueRanks(valueRank: node->valueRank, constraintValueRank: vt->valueRank)) {
42629 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42630 msg: "The value rank is incompatible "
42631 "with the value rank of the VariableType");
42632 return UA_STATUSCODE_BADTYPEMISMATCH;
42633 }
42634
42635 /* Check array dimensions against the vt */
42636 if(!compatibleArrayDimensions(constraintArrayDimensionsSize: vt->arrayDimensionsSize, constraintArrayDimensions: vt->arrayDimensions,
42637 testArrayDimensionsSize: node->arrayDimensionsSize, testArrayDimensions: node->arrayDimensions)) {
42638 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42639 msg: "The array dimensions are incompatible with the "
42640 "array dimensions of the VariableType");
42641 return UA_STATUSCODE_BADTYPEMISMATCH;
42642 }
42643
42644 /* Typecheck the value */
42645
42646 /* The value might come from a datasource, so we perform a
42647 * regular read. */
42648 UA_DataValue value;
42649 UA_DataValue_init(p: &value);
42650 UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value);
42651 if(retval != UA_STATUSCODE_GOOD)
42652 return retval;
42653
42654 /* Only BaseDataType (Variant) can have empty values. Create default content
42655 * otherwise that matches the constraints. */
42656 if(!value.hasValue || !value.value.type) {
42657 if(!UA_NodeId_equal(n1: &node->dataType, n2: &UA_TYPES[UA_TYPES_VARIANT].typeId)) {
42658 /* Warn if that is configured */
42659 if(!server->bootstrapNS0 &&
42660 server->config.allowEmptyVariables != UA_RULEHANDLING_ACCEPT)
42661 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42662 msg: "The value is empty. But this is only allowed for BaseDataType. "
42663 "Create a matching default value.");
42664
42665 /* Abort if that is configured */
42666 if(server->config.allowEmptyVariables == UA_RULEHANDLING_ABORT)
42667 retval = UA_STATUSCODE_BADTYPEMISMATCH;
42668
42669 /* Try to generate a default value if that is configured */
42670 if(server->config.allowEmptyVariables == UA_RULEHANDLING_DEFAULT) {
42671 retval = setDefaultValue(server, node);
42672 if(retval != UA_STATUSCODE_GOOD) {
42673 UA_LOG_NODEID_INFO(&node->head.nodeId,
42674 UA_LOG_INFO_SESSION(&server->config.logger, session,
42675 "AddNode (%.*s): Could not create a default value "
42676 "with StatusCode %s", (int)nodeIdStr.length,
42677 nodeIdStr.data, UA_StatusCode_name(retval)));
42678 }
42679
42680 /* Reread the current value for compat tests below */
42681 UA_DataValue_clear(p: &value);
42682 retval = readValueAttribute(server, session, vn: node, v: &value);
42683 }
42684 }
42685
42686 if(retval != UA_STATUSCODE_GOOD) {
42687 UA_DataValue_clear(p: &value);
42688 return retval;
42689 }
42690 }
42691
42692 /* Perform the value typecheck. If this fails, write the current value
42693 * again. The write-service tries to convert to the correct type... */
42694 const char *reason;
42695 if(!compatibleValue(server, session, targetDataTypeId: &node->dataType, targetValueRank: node->valueRank,
42696 targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions,
42697 value: &value.value, NULL, reason: &reason)) {
42698 retval = writeValueAttribute(server, session, nodeId: &node->head.nodeId, value: &value.value);
42699 if(retval != UA_STATUSCODE_GOOD) {
42700 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42701 msg: "The value is incompatible with the variable definition");
42702 }
42703 }
42704
42705 UA_DataValue_clear(p: &value);
42706 return retval;
42707}
42708
42709/********************/
42710/* Instantiate Node */
42711/********************/
42712
42713static const UA_NodeId baseDataVariableType =
42714 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEDATAVARIABLETYPE}};
42715static const UA_NodeId baseObjectType =
42716 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEOBJECTTYPE}};
42717static const UA_NodeId hasTypeDefinition =
42718 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}};
42719
42720/* Use attributes from the variable type wherever required. Reload the node if
42721 * changes were made. */
42722static UA_StatusCode
42723useVariableTypeAttributes(UA_Server *server, UA_Session *session,
42724 const UA_VariableNode *node,
42725 const UA_VariableTypeNode *vt) {
42726 /* If no value is set, see if the vt provides one and copy it. This needs to
42727 * be done before copying the datatype from the vt, as setting the datatype
42728 * triggers a typecheck. */
42729 UA_Variant orig;
42730 UA_StatusCode retval =
42731 readWithReadValue(server, nodeId: &node->head.nodeId, attributeId: UA_ATTRIBUTEID_VALUE, v: &orig);
42732 if(retval != UA_STATUSCODE_GOOD)
42733 return retval;
42734
42735 if(orig.type) {
42736 /* A value is present */
42737 UA_Variant_clear(p: &orig);
42738 } else {
42739 UA_DataValue v;
42740 UA_DataValue_init(p: &v);
42741 retval = readValueAttribute(server, session, vn: (const UA_VariableNode*)vt, v: &v);
42742 if(retval == UA_STATUSCODE_GOOD && v.hasValue) {
42743 retval = writeValueAttribute(server, session, nodeId: &node->head.nodeId, value: &v.value);
42744 }
42745 UA_DataValue_clear(p: &v);
42746
42747 if(retval != UA_STATUSCODE_GOOD) {
42748 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42749 msg: "The default content of the VariableType could "
42750 "not be used. This may happen if the VariableNode "
42751 "makes additional restrictions.");
42752 retval = UA_STATUSCODE_GOOD;
42753 }
42754 }
42755
42756 /* If no datatype is given, use the datatype of the vt */
42757 if(UA_NodeId_isNull(p: &node->dataType)) {
42758 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
42759 msg: "No datatype given; Copy the datatype attribute "
42760 "from the TypeDefinition");
42761 retval = writeAttribute(server, session, nodeId: &node->head.nodeId,
42762 attributeId: UA_ATTRIBUTEID_DATATYPE, attr: &vt->dataType,
42763 attr_type: &UA_TYPES[UA_TYPES_NODEID]);
42764 if(retval != UA_STATUSCODE_GOOD)
42765 return retval;
42766 }
42767
42768 /* Use the ArrayDimensions of the vt */
42769 if(node->arrayDimensionsSize == 0 && vt->arrayDimensionsSize > 0) {
42770 UA_Variant v;
42771 UA_Variant_init(p: &v);
42772 UA_Variant_setArray(v: &v, array: vt->arrayDimensions, arraySize: vt->arrayDimensionsSize,
42773 type: &UA_TYPES[UA_TYPES_UINT32]);
42774 retval = writeAttribute(server, session, nodeId: &node->head.nodeId,
42775 attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS, attr: &v,
42776 attr_type: &UA_TYPES[UA_TYPES_VARIANT]);
42777 }
42778
42779 return retval;
42780}
42781
42782/* Search for an instance of "browseName" in node searchInstance. Used during
42783 * copyChildNodes to find overwritable/mergable nodes. Does not touch
42784 * outInstanceNodeId if no child is found. */
42785static UA_StatusCode
42786findChildByBrowsename(UA_Server *server, UA_Session *session,
42787 const UA_NodeId *searchInstance,
42788 const UA_QualifiedName *browseName,
42789 UA_NodeId *outInstanceNodeId) {
42790 UA_BrowseDescription bd;
42791 UA_BrowseDescription_init(p: &bd);
42792 bd.nodeId = *searchInstance;
42793 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
42794 bd.includeSubtypes = true;
42795 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
42796 bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
42797 bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
42798
42799 UA_BrowseResult br;
42800 UA_BrowseResult_init(p: &br);
42801 UA_UInt32 maxrefs = 0;
42802 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
42803 if(br.statusCode != UA_STATUSCODE_GOOD)
42804 return br.statusCode;
42805
42806 UA_StatusCode retval = UA_STATUSCODE_GOOD;
42807 for(size_t i = 0; i < br.referencesSize; ++i) {
42808 UA_ReferenceDescription *rd = &br.references[i];
42809 if(rd->browseName.namespaceIndex == browseName->namespaceIndex &&
42810 UA_String_equal(s1: &rd->browseName.name, s2: &browseName->name)) {
42811 retval = UA_NodeId_copy(src: &rd->nodeId.nodeId, dst: outInstanceNodeId);
42812 break;
42813 }
42814 }
42815
42816 UA_BrowseResult_clear(p: &br);
42817 return retval;
42818}
42819
42820static const UA_NodeId mandatoryId =
42821 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_MODELLINGRULE_MANDATORY}};
42822
42823static UA_Boolean
42824isMandatoryChild(UA_Server *server, UA_Session *session,
42825 const UA_NodeId *childNodeId) {
42826 /* Get the child */
42827 const UA_Node *child = UA_NODESTORE_GET(server, childNodeId);
42828 if(!child)
42829 return false;
42830
42831 /* Look for the reference making the child mandatory */
42832 UA_NodePointer mandatoryP = UA_NodePointer_fromNodeId(id: &mandatoryId);
42833 for(size_t i = 0; i < child->head.referencesSize; ++i) {
42834 UA_NodeReferenceKind *rk = &child->head.references[i];
42835 if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASMODELLINGRULE)
42836 continue;
42837 if(rk->isInverse)
42838 continue;
42839
42840 const UA_ReferenceTarget *t = NULL;
42841 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
42842 if(UA_NodePointer_equal(p1: mandatoryP, p2: t->targetId)) {
42843 UA_NODESTORE_RELEASE(server, child);
42844 return true;
42845 }
42846 }
42847 }
42848
42849 UA_NODESTORE_RELEASE(server, child);
42850 return false;
42851}
42852
42853static UA_StatusCode
42854copyAllChildren(UA_Server *server, UA_Session *session,
42855 const UA_NodeId *source, const UA_NodeId *destination);
42856
42857static void
42858Operation_addReference(UA_Server *server, UA_Session *session, void *context,
42859 const UA_AddReferencesItem *item, UA_StatusCode *retval);
42860
42861UA_StatusCode
42862addRef(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId,
42863 const UA_NodeId *referenceTypeId, const UA_NodeId *targetId,
42864 UA_Boolean forward) {
42865 UA_AddReferencesItem ref_item;
42866 UA_AddReferencesItem_init(p: &ref_item);
42867 ref_item.sourceNodeId = *sourceId;
42868 ref_item.referenceTypeId = *referenceTypeId;
42869 ref_item.isForward = forward;
42870 ref_item.targetNodeId.nodeId = *targetId;
42871
42872 UA_StatusCode retval = UA_STATUSCODE_GOOD;
42873 Operation_addReference(server, session, NULL, item: &ref_item, retval: &retval);
42874 return retval;
42875}
42876
42877static UA_StatusCode
42878addInterfaceChildren(UA_Server *server, UA_Session *session,
42879 const UA_NodeId *nodeId, const UA_NodeId *typeId) {
42880 /* Get the hierarchy of the type and all its supertypes */
42881 UA_NodeId *hierarchy = NULL;
42882 size_t hierarchySize = 0;
42883 UA_StatusCode retval = getAllInterfaceChildNodeIds(server, objectNode: nodeId, objectTypeNode: typeId,
42884 interfaceChildNodes: &hierarchy, interfaceChildNodesSize: &hierarchySize);
42885 if(retval != UA_STATUSCODE_GOOD)
42886 return retval;
42887
42888 /* Copy members of the type and supertypes (and instantiate them) */
42889 for(size_t i = 0; i < hierarchySize; ++i) {
42890 retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId);
42891 if(retval != UA_STATUSCODE_GOOD) {
42892 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
42893 return retval;
42894 }
42895 }
42896
42897 for(size_t i = 0; i < hierarchySize; ++i) {
42898 UA_NodeId refId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASINTERFACE);
42899 retval = addRef(server, session: &server->adminSession, sourceId: nodeId, referenceTypeId: &refId, targetId: &hierarchy[i], true);
42900
42901 /* Don't add the original HasInterface reference to ObjectType sub nodes */
42902 if(retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
42903 retval = UA_STATUSCODE_GOOD;
42904 } else if(retval != UA_STATUSCODE_GOOD) {
42905 break;
42906 }
42907 }
42908
42909 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
42910 return retval;
42911}
42912
42913static UA_StatusCode
42914copyChild(UA_Server *server, UA_Session *session,
42915 const UA_NodeId *destinationNodeId,
42916 const UA_ReferenceDescription *rd) {
42917 UA_assert(session);
42918
42919 /* Is there an existing child with the browsename? */
42920 UA_NodeId existingChild = UA_NODEID_NULL;
42921 UA_StatusCode retval = findChildByBrowsename(server, session, searchInstance: destinationNodeId,
42922 browseName: &rd->browseName, outInstanceNodeId: &existingChild);
42923 if(retval != UA_STATUSCODE_GOOD)
42924 return retval;
42925
42926 /* Have a child with that browseName. Deep-copy missing members. */
42927 if(!UA_NodeId_isNull(p: &existingChild)) {
42928 if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
42929 rd->nodeClass == UA_NODECLASS_OBJECT)
42930 retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &existingChild);
42931 UA_NodeId_clear(p: &existingChild);
42932 return retval;
42933 }
42934
42935 /* Is the child mandatory? If not, ask callback whether child should be instantiated.
42936 * If not, skip. */
42937 if(!isMandatoryChild(server, session, childNodeId: &rd->nodeId.nodeId)) {
42938 if(!server->config.nodeLifecycle.createOptionalChild)
42939 return UA_STATUSCODE_GOOD;
42940 UA_UNLOCK(&server->serviceMutex);
42941 UA_Boolean createChild = server->config.nodeLifecycle.
42942 createOptionalChild(server, &session->sessionId, session->sessionHandle,
42943 &rd->nodeId.nodeId, destinationNodeId, &rd->referenceTypeId);
42944 UA_LOCK(&server->serviceMutex);
42945 if(!createChild)
42946 return UA_STATUSCODE_GOOD;
42947 }
42948
42949 /* Child is a method -> create a reference */
42950 if(rd->nodeClass == UA_NODECLASS_METHOD) {
42951 UA_AddReferencesItem newItem;
42952 UA_AddReferencesItem_init(p: &newItem);
42953 newItem.sourceNodeId = *destinationNodeId;
42954 newItem.referenceTypeId = rd->referenceTypeId;
42955 newItem.isForward = true;
42956 newItem.targetNodeId = rd->nodeId;
42957 newItem.targetNodeClass = UA_NODECLASS_METHOD;
42958 Operation_addReference(server, session, NULL, item: &newItem, retval: &retval);
42959 return retval;
42960 }
42961
42962 /* Child is a variable or object */
42963 if(rd->nodeClass == UA_NODECLASS_VARIABLE ||
42964 rd->nodeClass == UA_NODECLASS_OBJECT) {
42965 /* Make a copy of the node */
42966 UA_Node *node;
42967 retval = UA_NODESTORE_GETCOPY(server, &rd->nodeId.nodeId, &node);
42968 if(retval != UA_STATUSCODE_GOOD)
42969 return retval;
42970
42971 /* Remove the context of the copied node */
42972 node->head.context = NULL;
42973 node->head.constructed = false;
42974#ifdef UA_ENABLE_SUBSCRIPTIONS
42975 node->head.monitoredItems = NULL;
42976#endif
42977
42978 /* Reset the NodeId (random numeric id will be assigned in the nodestore) */
42979 UA_NodeId_clear(p: &node->head.nodeId);
42980 node->head.nodeId.namespaceIndex = destinationNodeId->namespaceIndex;
42981
42982 if(server->config.nodeLifecycle.generateChildNodeId) {
42983 UA_UNLOCK(&server->serviceMutex);
42984 retval = server->config.nodeLifecycle.
42985 generateChildNodeId(server, &session->sessionId, session->sessionHandle,
42986 &rd->nodeId.nodeId, destinationNodeId,
42987 &rd->referenceTypeId, &node->head.nodeId);
42988 UA_LOCK(&server->serviceMutex);
42989 if(retval != UA_STATUSCODE_GOOD) {
42990 UA_NODESTORE_DELETE(server, node);
42991 return retval;
42992 }
42993 }
42994
42995 /* Remove references, they are re-created from scratch in addnode_finish */
42996 /* TODO: Be more clever in removing references that are re-added during
42997 * addnode_finish. That way, we can call addnode_finish also on children that were
42998 * manually added by the user during addnode_begin and addnode_finish. */
42999 /* For now we keep all the modelling rule references and delete all others */
43000 const UA_NodeId nodeId_typesFolder= UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER);
43001 const UA_ReferenceTypeSet reftypes_aggregates =
43002 UA_REFTYPESET(UA_REFERENCETYPEINDEX_AGGREGATES);
43003 UA_ReferenceTypeSet reftypes_skipped;
43004 /* Check if the hasModellingRule-reference is required (configured or node in an
43005 instance declaration) */
43006 if(server->config.modellingRulesOnInstances ||
43007 isNodeInTree(server, leafNode: destinationNodeId,
43008 nodeToFind: &nodeId_typesFolder, relevantRefs: &reftypes_aggregates)) {
43009 reftypes_skipped = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASMODELLINGRULE);
43010 } else {
43011 UA_ReferenceTypeSet_init(set: &reftypes_skipped);
43012 }
43013 reftypes_skipped = UA_ReferenceTypeSet_union(setA: reftypes_skipped, setB: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE));
43014 UA_Node_deleteReferencesSubset(node, keepSet: &reftypes_skipped);
43015
43016 /* Add the node to the nodestore */
43017 UA_NodeId newNodeId;
43018 retval = UA_NODESTORE_INSERT(server, node, &newNodeId);
43019 /* node = NULL; The pointer is no longer valid */
43020 if(retval != UA_STATUSCODE_GOOD)
43021 return retval;
43022
43023 /* Add the node references */
43024 retval = AddNode_addRefs(server, session, nodeId: &newNodeId, parentNodeId: destinationNodeId,
43025 referenceTypeId: &rd->referenceTypeId, typeDefinitionId: &rd->typeDefinition.nodeId);
43026 if(retval != UA_STATUSCODE_GOOD) {
43027 UA_NODESTORE_REMOVE(server, &newNodeId);
43028 UA_NodeId_clear(p: &newNodeId);
43029 return retval;
43030 }
43031
43032 if (rd->nodeClass == UA_NODECLASS_VARIABLE) {
43033 retval = checkSetIsDynamicVariable(server, session, nodeId: &newNodeId);
43034
43035 if(retval != UA_STATUSCODE_GOOD) {
43036 UA_NODESTORE_REMOVE(server, &newNodeId);
43037 return retval;
43038 }
43039 }
43040
43041 /* For the new child, recursively copy the members of the original. No
43042 * typechecking is performed here. Assuming that the original is
43043 * consistent. */
43044 retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &newNodeId);
43045 if(retval != UA_STATUSCODE_GOOD) {
43046 deleteNode(server, nodeId: newNodeId, true);
43047 return retval;
43048 }
43049
43050 /* Check if its a dynamic variable, add all type and/or interface
43051 * children and call the constructor */
43052 retval = AddNode_finish(server, session, nodeId: &newNodeId);
43053 if(retval != UA_STATUSCODE_GOOD) {
43054 deleteNode(server, nodeId: newNodeId, true);
43055 return retval;
43056 }
43057
43058 /* Clean up. Because it can happen that a string is assigned as ID at
43059 * generateChildNodeId. */
43060 UA_NodeId_clear(p: &newNodeId);
43061 }
43062
43063 return retval;
43064}
43065
43066/* Copy any children of Node sourceNodeId to another node destinationNodeId. */
43067static UA_StatusCode
43068copyAllChildren(UA_Server *server, UA_Session *session,
43069 const UA_NodeId *source, const UA_NodeId *destination) {
43070 /* Browse to get all children of the source */
43071 UA_BrowseDescription bd;
43072 UA_BrowseDescription_init(p: &bd);
43073 bd.nodeId = *source;
43074 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
43075 bd.includeSubtypes = true;
43076 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
43077 bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD;
43078 bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS |
43079 UA_BROWSERESULTMASK_BROWSENAME | UA_BROWSERESULTMASK_TYPEDEFINITION;
43080
43081 UA_BrowseResult br;
43082 UA_BrowseResult_init(p: &br);
43083 UA_UInt32 maxrefs = 0;
43084 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
43085 if(br.statusCode != UA_STATUSCODE_GOOD)
43086 return br.statusCode;
43087
43088 UA_StatusCode retval = UA_STATUSCODE_GOOD;
43089 for(size_t i = 0; i < br.referencesSize; ++i) {
43090 UA_ReferenceDescription *rd = &br.references[i];
43091 retval = copyChild(server, session, destinationNodeId: destination, rd);
43092 if(retval != UA_STATUSCODE_GOOD)
43093 break;
43094 }
43095
43096 UA_BrowseResult_clear(p: &br);
43097 return retval;
43098}
43099
43100static UA_StatusCode
43101addTypeChildren(UA_Server *server, UA_Session *session,
43102 const UA_NodeId *nodeId, const UA_NodeId *typeId) {
43103 /* Get the hierarchy of the type and all its supertypes */
43104 UA_NodeId *hierarchy = NULL;
43105 size_t hierarchySize = 0;
43106 UA_StatusCode retval = getParentTypeAndInterfaceHierarchy(server, typeNode: typeId,
43107 typeHierarchy: &hierarchy, typeHierarchySize: &hierarchySize);
43108 if(retval != UA_STATUSCODE_GOOD)
43109 return retval;
43110 UA_assert(hierarchySize < 1000);
43111
43112 /* Copy members of the type and supertypes (and instantiate them) */
43113 for(size_t i = 0; i < hierarchySize; ++i) {
43114 retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId);
43115 if(retval != UA_STATUSCODE_GOOD)
43116 break;
43117 }
43118
43119 UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]);
43120 return retval;
43121}
43122
43123/************/
43124/* Add Node */
43125/************/
43126
43127static const UA_NodeId hasSubtype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}};
43128
43129UA_StatusCode
43130AddNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
43131 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
43132 const UA_NodeId *typeDefinitionId) {
43133 /* Get the node */
43134 const UA_Node *type = NULL;
43135 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43136 if(!node)
43137 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43138
43139 /* Use the typeDefinition as parent for type-nodes */
43140 const UA_NodeHead *head = &node->head;
43141 if(head->nodeClass == UA_NODECLASS_VARIABLETYPE ||
43142 head->nodeClass == UA_NODECLASS_OBJECTTYPE ||
43143 head->nodeClass == UA_NODECLASS_REFERENCETYPE ||
43144 head->nodeClass == UA_NODECLASS_DATATYPE) {
43145 if(UA_NodeId_equal(n1: referenceTypeId, n2: &UA_NODEID_NULL))
43146 referenceTypeId = &hasSubtype;
43147 const UA_Node *parentNode = UA_NODESTORE_GET(server, parentNodeId);
43148 if(parentNode) {
43149 if(parentNode->head.nodeClass == head->nodeClass)
43150 typeDefinitionId = parentNodeId;
43151 UA_NODESTORE_RELEASE(server, parentNode);
43152 }
43153 }
43154
43155 UA_StatusCode retval;
43156 /* Make sure newly created node does not have itself as parent */
43157 if(UA_NodeId_equal(n1: nodeId, n2: parentNodeId)) {
43158 logAddNode(logger: &server->config.logger, session, nodeId,
43159 msg: "A node cannot have itself as parent");
43160 retval = UA_STATUSCODE_BADINVALIDARGUMENT;
43161 goto cleanup;
43162 }
43163
43164
43165 /* Check parent reference. Objects may have no parent. */
43166 retval = checkParentReference(server, session, head, parentNodeId, referenceTypeId);
43167 if(retval != UA_STATUSCODE_GOOD) {
43168 logAddNode(logger: &server->config.logger, session, nodeId,
43169 msg: "The parent reference for is invalid");
43170 goto cleanup;
43171 }
43172
43173 /* Replace empty typeDefinition with the most permissive default */
43174 if((head->nodeClass == UA_NODECLASS_VARIABLE ||
43175 head->nodeClass == UA_NODECLASS_OBJECT) &&
43176 UA_NodeId_isNull(p: typeDefinitionId)) {
43177 logAddNode(logger: &server->config.logger, session, nodeId,
43178 msg: "No TypeDefinition. Use the default "
43179 "TypeDefinition for the Variable/Object");
43180 if(head->nodeClass == UA_NODECLASS_VARIABLE)
43181 typeDefinitionId = &baseDataVariableType;
43182 else
43183 typeDefinitionId = &baseObjectType;
43184 }
43185
43186 /* Get the node type. There must be a typedefinition for variables, objects
43187 * and type-nodes. See the above checks. */
43188 if(!UA_NodeId_isNull(p: typeDefinitionId)) {
43189 /* Get the type node */
43190 type = UA_NODESTORE_GET(server, typeDefinitionId);
43191 if(!type) {
43192 logAddNode(logger: &server->config.logger, session, nodeId, msg: "Node type not found");
43193 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43194 goto cleanup;
43195 }
43196
43197 UA_Boolean typeOk = false;
43198 const UA_NodeHead *typeHead = &type->head;
43199 switch(head->nodeClass) {
43200 case UA_NODECLASS_DATATYPE:
43201 typeOk = typeHead->nodeClass == UA_NODECLASS_DATATYPE;
43202 break;
43203 case UA_NODECLASS_METHOD:
43204 typeOk = typeHead->nodeClass == UA_NODECLASS_METHOD;
43205 break;
43206 case UA_NODECLASS_OBJECT:
43207 case UA_NODECLASS_OBJECTTYPE:
43208 typeOk = typeHead->nodeClass == UA_NODECLASS_OBJECTTYPE;
43209 break;
43210 case UA_NODECLASS_REFERENCETYPE:
43211 typeOk = typeHead->nodeClass == UA_NODECLASS_REFERENCETYPE;
43212 break;
43213 case UA_NODECLASS_VARIABLE:
43214 case UA_NODECLASS_VARIABLETYPE:
43215 typeOk = typeHead->nodeClass == UA_NODECLASS_VARIABLETYPE;
43216 break;
43217 case UA_NODECLASS_VIEW:
43218 typeOk = typeHead->nodeClass == UA_NODECLASS_VIEW;
43219 break;
43220 default:
43221 typeOk = false;
43222 }
43223 if(!typeOk) {
43224 logAddNode(logger: &server->config.logger, session, nodeId,
43225 msg: "Type does not match the NodeClass");
43226 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43227 goto cleanup;
43228 }
43229
43230 /* See if the type has the correct node class. For type-nodes, we know
43231 * that type has the same nodeClass from checkParentReference. */
43232 if(head->nodeClass == UA_NODECLASS_VARIABLE &&
43233 type->variableTypeNode.isAbstract) {
43234 /* Get subtypes of the parent reference types */
43235 UA_ReferenceTypeSet refTypes1, refTypes2;
43236 retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true);
43237 retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true);
43238 UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2);
43239 if(retval != UA_STATUSCODE_GOOD)
43240 goto cleanup;
43241
43242 /* Abstract variable is allowed if parent is a children of a
43243 * base data variable. An abstract variable may be part of an
43244 * object type which again is below BaseObjectType */
43245 const UA_NodeId variableTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE);
43246 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE);
43247 if(!isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &variableTypes, relevantRefs: &refTypes) &&
43248 !isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes)) {
43249 logAddNode(logger: &server->config.logger, session, nodeId,
43250 msg: "Type of variable node must be a "
43251 "VariableType and not cannot be abstract");
43252 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43253 goto cleanup;
43254 }
43255 }
43256
43257 if(head->nodeClass == UA_NODECLASS_OBJECT &&
43258 type->objectTypeNode.isAbstract) {
43259 /* Get subtypes of the parent reference types */
43260 UA_ReferenceTypeSet refTypes1, refTypes2;
43261 retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true);
43262 retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true);
43263 UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2);
43264 if(retval != UA_STATUSCODE_GOOD)
43265 goto cleanup;
43266
43267
43268 /* Object node created of an abstract ObjectType. Only allowed if
43269 * within BaseObjectType folder or if it's an event (subType of
43270 * BaseEventType) */
43271 const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE);
43272 UA_Boolean isInBaseObjectType =
43273 isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes);
43274
43275 const UA_NodeId eventTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
43276 UA_Boolean isInBaseEventType =
43277 isNodeInTree_singleRef(server, leafNode: &type->head.nodeId, nodeToFind: &eventTypes,
43278 UA_REFERENCETYPEINDEX_HASSUBTYPE);
43279
43280 if(!isInBaseObjectType &&
43281 !(isInBaseEventType && UA_NodeId_isNull(p: parentNodeId))) {
43282 logAddNode(logger: &server->config.logger, session, nodeId,
43283 msg: "Type of ObjectNode must be ObjectType and not be abstract");
43284 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43285 goto cleanup;
43286 }
43287 }
43288 }
43289
43290 /* Add reference to the parent */
43291 if(!UA_NodeId_isNull(p: parentNodeId)) {
43292 if(UA_NodeId_isNull(p: referenceTypeId)) {
43293 logAddNode(logger: &server->config.logger, session, nodeId,
43294 msg: "Reference to parent cannot be null");
43295 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43296 goto cleanup;
43297 }
43298
43299 retval = addRef(server, session, sourceId: &head->nodeId, referenceTypeId,
43300 targetId: parentNodeId, false);
43301 if(retval != UA_STATUSCODE_GOOD) {
43302 logAddNode(logger: &server->config.logger, session, nodeId,
43303 msg: "Adding reference to parent failed");
43304 goto cleanup;
43305 }
43306 }
43307
43308 /* Add a hasTypeDefinition reference */
43309 if(head->nodeClass == UA_NODECLASS_VARIABLE ||
43310 head->nodeClass == UA_NODECLASS_OBJECT) {
43311 UA_assert(type != NULL); /* see above */
43312 retval = addRef(server, session, sourceId: &head->nodeId, referenceTypeId: &hasTypeDefinition,
43313 targetId: &type->head.nodeId, true);
43314 if(retval != UA_STATUSCODE_GOOD) {
43315 logAddNode(logger: &server->config.logger, session, nodeId,
43316 msg: "Adding a reference to the type definition failed");
43317 }
43318 }
43319
43320 cleanup:
43321 UA_NODESTORE_RELEASE(server, node);
43322 if(type)
43323 UA_NODESTORE_RELEASE(server, type);
43324 return retval;
43325}
43326
43327/* Create the node and add it to the nodestore. But don't typecheck and add
43328 * references so far */
43329UA_StatusCode
43330AddNode_raw(UA_Server *server, UA_Session *session, void *nodeContext,
43331 const UA_AddNodesItem *item, UA_NodeId *outNewNodeId) {
43332 /* Do not check access for server */
43333 if(session != &server->adminSession && server->config.accessControl.allowAddNode) {
43334 UA_UNLOCK(&server->serviceMutex);
43335 if(!server->config.accessControl.
43336 allowAddNode(server, &server->config.accessControl,
43337 &session->sessionId, session->sessionHandle, item)) {
43338 UA_LOCK(&server->serviceMutex);
43339 return UA_STATUSCODE_BADUSERACCESSDENIED;
43340 }
43341 UA_LOCK(&server->serviceMutex);
43342 }
43343
43344 /* Check the namespaceindex */
43345 if(item->requestedNewNodeId.nodeId.namespaceIndex >= server->namespacesSize) {
43346 UA_LOG_INFO_SESSION(&server->config.logger, session,
43347 "AddNode: Namespace invalid");
43348 return UA_STATUSCODE_BADNODEIDINVALID;
43349 }
43350
43351 if(item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED &&
43352 item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) {
43353 UA_LOG_INFO_SESSION(&server->config.logger, session,
43354 "AddNode: Node attributes invalid");
43355 return UA_STATUSCODE_BADINTERNALERROR;
43356 }
43357
43358 /* Create a node */
43359 UA_Node *node = UA_NODESTORE_NEW(server, item->nodeClass);
43360 if(!node) {
43361 UA_LOG_INFO_SESSION(&server->config.logger, session,
43362 "AddNode: Node could not create a node "
43363 "in the nodestore");
43364 return UA_STATUSCODE_BADOUTOFMEMORY;
43365 }
43366
43367 UA_NodeId tmpOutId = UA_NODEID_NULL;
43368 /* Fill the node attributes */
43369 node->head.context = nodeContext;
43370 UA_StatusCode retval =
43371 UA_NodeId_copy(src: &item->requestedNewNodeId.nodeId, dst: &node->head.nodeId);
43372 if(retval != UA_STATUSCODE_GOOD)
43373 goto create_error;
43374
43375 retval = UA_QualifiedName_copy(src: &item->browseName, dst: &node->head.browseName);
43376 if(retval != UA_STATUSCODE_GOOD)
43377 goto create_error;
43378
43379 retval = UA_Node_setAttributes(node, attributes: item->nodeAttributes.content.decoded.data,
43380 attributeType: item->nodeAttributes.content.decoded.type);
43381 if(retval != UA_STATUSCODE_GOOD)
43382 goto create_error;
43383
43384 /* Add the node to the nodestore */
43385 if(!outNewNodeId)
43386 outNewNodeId = &tmpOutId;
43387 retval = UA_NODESTORE_INSERT(server, node, outNewNodeId);
43388 if(retval != UA_STATUSCODE_GOOD) {
43389 UA_LOG_INFO_SESSION(&server->config.logger, session,
43390 "AddNode: Node could not add the new node "
43391 "to the nodestore with error code %s",
43392 UA_StatusCode_name(retval));
43393 return retval;
43394 }
43395
43396 if(outNewNodeId == &tmpOutId)
43397 UA_NodeId_clear(p: &tmpOutId);
43398
43399 return UA_STATUSCODE_GOOD;
43400
43401create_error:
43402 UA_LOG_INFO_SESSION(&server->config.logger, session,
43403 "AddNode: Node could not create a node "
43404 "with error code %s", UA_StatusCode_name(retval));
43405 UA_NODESTORE_DELETE(server, node);
43406 return retval;
43407}
43408
43409static UA_StatusCode
43410findDefaultInstanceBrowseNameNode(UA_Server *server, UA_NodeId startingNode,
43411 UA_NodeId *foundId) {
43412 UA_NodeId_init(p: foundId);
43413 UA_RelativePathElement rpe;
43414 UA_RelativePathElement_init(p: &rpe);
43415 rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
43416 rpe.targetName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "DefaultInstanceBrowseName");
43417 UA_BrowsePath bp;
43418 UA_BrowsePath_init(p: &bp);
43419 bp.startingNode = startingNode;
43420 bp.relativePath.elementsSize = 1;
43421 bp.relativePath.elements = &rpe;
43422 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp);
43423 UA_StatusCode retval = bpr.statusCode;
43424 if(retval == UA_STATUSCODE_GOOD && bpr.targetsSize > 0)
43425 retval = UA_NodeId_copy(src: &bpr.targets[0].targetId.nodeId, dst: foundId);
43426 UA_BrowsePathResult_clear(p: &bpr);
43427 return retval;
43428}
43429
43430/* Check if we got a valid browse name for the new node. For object nodes the
43431 * BrowseName may only be null if the parent type has a
43432 * 'DefaultInstanceBrowseName' property. */
43433static UA_StatusCode
43434checkSetBrowseName(UA_Server *server, UA_Session *session, UA_AddNodesItem *item) {
43435 /* If the object node already has a browse name we are done here. */
43436 if(!UA_QualifiedName_isNull(q: &item->browseName))
43437 return UA_STATUSCODE_GOOD;
43438
43439 /* Nodes other than Objects must have a BrowseName */
43440 if(item->nodeClass != UA_NODECLASS_OBJECT)
43441 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43442
43443 /* At this point we have an object with an empty browse name. Check the type
43444 * node if it has a DefaultInstanceBrowseName property. */
43445 UA_NodeId defaultBrowseNameNode;
43446 UA_StatusCode retval =
43447 findDefaultInstanceBrowseNameNode(server, startingNode: item->typeDefinition.nodeId,
43448 foundId: &defaultBrowseNameNode);
43449 if(retval != UA_STATUSCODE_GOOD)
43450 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43451
43452 UA_Variant defaultBrowseName;
43453 retval = readWithReadValue(server, nodeId: &defaultBrowseNameNode,
43454 attributeId: UA_ATTRIBUTEID_VALUE, v: &defaultBrowseName);
43455 UA_NodeId_clear(p: &defaultBrowseNameNode);
43456 if(retval != UA_STATUSCODE_GOOD)
43457 return UA_STATUSCODE_BADBROWSENAMEINVALID;
43458
43459 if(UA_Variant_hasScalarType(v: &defaultBrowseName, type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME])) {
43460 item->browseName = *(UA_QualifiedName*)defaultBrowseName.data;
43461 UA_QualifiedName_init(p: (UA_QualifiedName*)defaultBrowseName.data);
43462 } else {
43463 retval = UA_STATUSCODE_BADBROWSENAMEINVALID;
43464 }
43465
43466 UA_Variant_clear(p: &defaultBrowseName);
43467 return retval;
43468}
43469
43470/* Prepare the node, then add it to the nodestore */
43471static UA_StatusCode
43472Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContext,
43473 const UA_AddNodesItem *item, const UA_NodeId *parentNodeId,
43474 const UA_NodeId *referenceTypeId, UA_NodeId *outNewNodeId) {
43475 /* Create a temporary NodeId if none is returned */
43476 UA_NodeId newId;
43477 if(!outNewNodeId) {
43478 UA_NodeId_init(p: &newId);
43479 outNewNodeId = &newId;
43480 }
43481
43482 /* Set the BrowsenName before adding to the Nodestore. The BrowseName is
43483 * immutable afterwards. */
43484 UA_Boolean noBrowseName = UA_QualifiedName_isNull(q: &item->browseName);
43485 UA_StatusCode retval =
43486 checkSetBrowseName(server, session, item: (UA_AddNodesItem*)(uintptr_t)item);
43487 if(retval != UA_STATUSCODE_GOOD)
43488 return retval;
43489
43490 /* Create the node and add it to the nodestore */
43491 retval = AddNode_raw(server, session, nodeContext, item, outNewNodeId);
43492 if(retval != UA_STATUSCODE_GOOD)
43493 goto cleanup;
43494
43495 /* Typecheck and add references to parent and type definition */
43496 retval = AddNode_addRefs(server, session, nodeId: outNewNodeId, parentNodeId,
43497 referenceTypeId, typeDefinitionId: &item->typeDefinition.nodeId);
43498 if(retval != UA_STATUSCODE_GOOD)
43499 deleteNode(server, nodeId: *outNewNodeId, true);
43500
43501 if(outNewNodeId == &newId)
43502 UA_NodeId_clear(p: &newId);
43503
43504 cleanup:
43505 if(noBrowseName)
43506 UA_QualifiedName_clear(p: (UA_QualifiedName*)(uintptr_t)&item->browseName);
43507 return retval;
43508}
43509
43510/* Construct children first */
43511static UA_StatusCode
43512recursiveCallConstructors(UA_Server *server, UA_Session *session,
43513 const UA_NodeId *nodeId, const UA_Node *type) {
43514 /* Browse the children */
43515 UA_BrowseDescription bd;
43516 UA_BrowseDescription_init(p: &bd);
43517 bd.nodeId = *nodeId;
43518 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
43519 bd.includeSubtypes = true;
43520 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
43521
43522 UA_BrowseResult br;
43523 UA_BrowseResult_init(p: &br);
43524 UA_UInt32 maxrefs = 0;
43525 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
43526 if(br.statusCode != UA_STATUSCODE_GOOD)
43527 return br.statusCode;
43528
43529 /* Call the constructor for every unconstructed child node */
43530 UA_StatusCode retval = UA_STATUSCODE_GOOD;
43531 for(size_t i = 0; i < br.referencesSize; ++i) {
43532 UA_ReferenceDescription *rd = &br.references[i];
43533 if(!UA_ExpandedNodeId_isLocal(n: &rd->nodeId))
43534 continue;
43535 const UA_Node *target = UA_NODESTORE_GET(server, &rd->nodeId.nodeId);
43536 if(!target)
43537 continue;
43538 if(target->head.constructed) {
43539 UA_NODESTORE_RELEASE(server, target);
43540 continue;
43541 }
43542
43543 const UA_Node *targetType = NULL;
43544 if(target->head.nodeClass == UA_NODECLASS_VARIABLE ||
43545 target->head.nodeClass == UA_NODECLASS_OBJECT) {
43546 targetType = getNodeType(server, head: &target->head);
43547 if(!targetType) {
43548 UA_NODESTORE_RELEASE(server, target);
43549 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43550 break;
43551 }
43552 }
43553
43554 UA_NODESTORE_RELEASE(server, target);
43555 retval = recursiveCallConstructors(server, session, nodeId: &rd->nodeId.nodeId, type: targetType);
43556
43557 if(targetType)
43558 UA_NODESTORE_RELEASE(server, targetType);
43559 if(retval != UA_STATUSCODE_GOOD)
43560 break;
43561 }
43562
43563 UA_BrowseResult_clear(p: &br);
43564
43565 /* If a child could not be constructed or the node is already constructed */
43566 if(retval != UA_STATUSCODE_GOOD)
43567 return retval;
43568
43569 /* Get the node context */
43570 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43571 if(!node)
43572 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43573 void *context = node->head.context;
43574 UA_NODESTORE_RELEASE(server, node);
43575
43576 /* Call the global constructor */
43577 if(server->config.nodeLifecycle.constructor) {
43578 UA_UNLOCK(&server->serviceMutex);
43579 retval = server->config.nodeLifecycle.
43580 constructor(server, &session->sessionId,
43581 session->sessionHandle, nodeId, &context);
43582 UA_LOCK(&server->serviceMutex);
43583 if(retval != UA_STATUSCODE_GOOD)
43584 return retval;
43585 }
43586
43587 /* Call the local (per-type) constructor */
43588 const UA_NodeTypeLifecycle *lifecycle = NULL;
43589 if(type && node->head.nodeClass == UA_NODECLASS_OBJECT)
43590 lifecycle = &type->objectTypeNode.lifecycle;
43591 else if(type && node->head.nodeClass == UA_NODECLASS_VARIABLE)
43592 lifecycle = &type->variableTypeNode.lifecycle;
43593 if(lifecycle && lifecycle->constructor) {
43594 UA_UNLOCK(&server->serviceMutex);
43595 retval = lifecycle->constructor(server, &session->sessionId,
43596 session->sessionHandle, &type->head.nodeId,
43597 type->head.context, nodeId, &context);
43598 UA_LOCK(&server->serviceMutex);
43599 if(retval != UA_STATUSCODE_GOOD)
43600 goto global_destructor;
43601 }
43602
43603 /* Set the context *and* mark the node as constructed */
43604 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId,
43605 callback: (UA_EditNodeCallback)setConstructedNodeContext, data: context);
43606 if(retval != UA_STATUSCODE_GOOD)
43607 goto local_destructor;
43608
43609 /* All good, return */
43610 return retval;
43611
43612 /* Fail. Call the destructors. */
43613 local_destructor:
43614 if(lifecycle && lifecycle->destructor) {
43615 UA_UNLOCK(&server->serviceMutex);
43616 lifecycle->destructor(server, &session->sessionId, session->sessionHandle,
43617 &type->head.nodeId, type->head.context, nodeId, &context);
43618 UA_LOCK(&server->serviceMutex);
43619 }
43620
43621 global_destructor:
43622 if(server->config.nodeLifecycle.destructor) {
43623 UA_UNLOCK(&server->serviceMutex);
43624 server->config.nodeLifecycle.destructor(server, &session->sessionId,
43625 session->sessionHandle,
43626 nodeId, context);
43627 UA_LOCK(&server->serviceMutex);
43628 }
43629 return retval;
43630}
43631
43632/* Add new ReferenceType to the subtypes bitfield */
43633static UA_StatusCode
43634addReferenceTypeSubtype(UA_Server *server, UA_Session *session,
43635 UA_Node *node, void *context) {
43636 node->referenceTypeNode.subTypes =
43637 UA_ReferenceTypeSet_union(setA: node->referenceTypeNode.subTypes,
43638 setB: *(UA_ReferenceTypeSet*)context);
43639 return UA_STATUSCODE_GOOD;
43640}
43641
43642static UA_StatusCode
43643setReferenceTypeSubtypes(UA_Server *server, const UA_ReferenceTypeNode *node) {
43644 /* Get the ReferenceTypes upwards in the hierarchy */
43645 size_t parentsSize = 0;
43646 UA_ExpandedNodeId *parents = NULL;
43647 UA_ReferenceTypeSet reftypes_subtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
43648 UA_StatusCode res =
43649 browseRecursive(server, startNodesSize: 1, startNodes: &node->head.nodeId, browseDirection: UA_BROWSEDIRECTION_INVERSE,
43650 refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED,
43651 false, resultsSize: &parentsSize, results: &parents);
43652 if(res != UA_STATUSCODE_GOOD)
43653 return res;
43654
43655 /* Add the ReferenceTypeIndex of this node */
43656 const UA_ReferenceTypeSet *newRefSet = &node->subTypes;
43657 for(size_t i = 0; i < parentsSize; i++) {
43658 UA_Server_editNode(server, session: &server->adminSession, nodeId: &parents[i].nodeId,
43659 callback: addReferenceTypeSubtype, data: (void*)(uintptr_t)newRefSet);
43660 }
43661
43662 UA_Array_delete(p: parents, size: parentsSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
43663 return UA_STATUSCODE_GOOD;
43664}
43665
43666static UA_StatusCode
43667setVariableNodeDynamic(UA_Server *server, UA_Session *session,
43668 UA_Node *node, const void *_) {
43669 (void)_; /* unused */
43670 if(node->head.nodeClass == UA_NODECLASS_VARIABLE)
43671 ((UA_VariableNode*)node)->isDynamic = true;
43672 return UA_STATUSCODE_GOOD;
43673}
43674
43675static UA_StatusCode
43676checkSetIsDynamicVariable(UA_Server *server, UA_Session *session,
43677 const UA_NodeId *nodeId) {
43678 /* Get all hierarchical reference types */
43679 UA_ReferenceTypeSet reftypes_hierarchical;
43680 UA_ReferenceTypeSet_init(set: &reftypes_hierarchical);
43681 UA_NodeId hierarchicalRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
43682 UA_StatusCode res =
43683 referenceTypeIndices(server, refType: &hierarchicalRefs, indices: &reftypes_hierarchical, true);
43684 if(res != UA_STATUSCODE_GOOD)
43685 return res;
43686
43687 /* Is the variable under the server object? */
43688 UA_NodeId serverNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER);
43689 if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &serverNodeId, relevantRefs: &reftypes_hierarchical))
43690 return UA_STATUSCODE_GOOD;
43691
43692 /* Is the variable in the type hierarchy? */
43693 UA_NodeId typesNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER);
43694 if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &typesNodeId, relevantRefs: &reftypes_hierarchical))
43695 return UA_STATUSCODE_GOOD;
43696
43697 /* Is the variable a property of a method node (InputArguments /
43698 * OutputArguments)? */
43699 UA_BrowseDescription bd;
43700 UA_BrowseDescription_init(p: &bd);
43701 bd.nodeId = *nodeId;
43702 bd.browseDirection = UA_BROWSEDIRECTION_INVERSE;
43703 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
43704 bd.includeSubtypes = false;
43705 bd.nodeClassMask = UA_NODECLASS_METHOD;
43706 UA_BrowseResult br;
43707 UA_BrowseResult_init(p: &br);
43708 UA_UInt32 maxrefs = 0;
43709 Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br);
43710 UA_Boolean hasParentMethod = (br.referencesSize > 0);
43711 UA_BrowseResult_clear(p: &br);
43712 if(hasParentMethod)
43713 return UA_STATUSCODE_GOOD;
43714
43715 /* Set the variable to "dynamic" */
43716 UA_Server_editNode(server, session, nodeId,
43717 callback: (UA_EditNodeCallback)setVariableNodeDynamic, NULL);
43718
43719 return UA_STATUSCODE_GOOD;
43720}
43721
43722/* Children, references, type-checking, constructors. */
43723UA_StatusCode
43724AddNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId) {
43725 /* Get the node */
43726 const UA_Node *type = NULL;
43727 const UA_Node *node = UA_NODESTORE_GET(server, nodeId);
43728 if(!node)
43729 return UA_STATUSCODE_BADNODEIDUNKNOWN;
43730
43731 /* Set the ReferenceTypesSet of subtypes in the ReferenceTypeNode */
43732 UA_StatusCode retval = UA_STATUSCODE_GOOD;
43733 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
43734 retval = setReferenceTypeSubtypes(server, node: &node->referenceTypeNode);
43735 if(retval != UA_STATUSCODE_GOOD)
43736 goto cleanup;
43737 }
43738
43739 /* Check NodeClass for 'hasSubtype'. UA_NODECLASS_VARIABLE not allowed
43740 * to have subtype */
43741 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
43742 for(size_t i = 0; i < node->head.referencesSize; i++) {
43743 if(node->head.references[i].referenceTypeIndex ==
43744 UA_REFERENCETYPEINDEX_HASSUBTYPE) {
43745 UA_LOG_NODEID_INFO(&node->head.nodeId,
43746 UA_LOG_INFO_SESSION(&server->config.logger, session,
43747 "AddNode (%.*s): Variable not allowed "
43748 "to have HasSubType reference",
43749 (int)nodeIdStr.length, nodeIdStr.data));
43750 retval = UA_STATUSCODE_BADREFERENCENOTALLOWED;
43751 goto cleanup;
43752 }
43753 }
43754 }
43755
43756 /* Get the type node */
43757 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43758 node->head.nodeClass == UA_NODECLASS_VARIABLETYPE ||
43759 node->head.nodeClass == UA_NODECLASS_OBJECT) {
43760 type = getNodeType(server, head: &node->head);
43761 if(!type) {
43762 if(server->bootstrapNS0)
43763 goto constructor;
43764 logAddNode(logger: &server->config.logger, session, nodeId: &node->head.nodeId,
43765 msg: "Node type not found");
43766 retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
43767 goto cleanup;
43768 }
43769 }
43770
43771 /* Initialize and typecheck the variable */
43772 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43773 node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
43774 /* Use attributes from the type. The value and value constraints are the
43775 * same for the variable and variabletype attribute structs. */
43776 retval = useVariableTypeAttributes(server, session,
43777 node: &node->variableNode,
43778 vt: &type->variableTypeNode);
43779 if(retval != UA_STATUSCODE_GOOD) {
43780 UA_LOG_NODEID_INFO(&node->head.nodeId,
43781 UA_LOG_INFO_SESSION(&server->config.logger, session,
43782 "AddNode (%.*s): Using attributes for from "
43783 "the variable type failed with error code %s",
43784 (int)nodeIdStr.length, nodeIdStr.data,
43785 UA_StatusCode_name(retval)));
43786 goto cleanup;
43787 }
43788
43789 /* Get a new pointer to the node. It might have been switched out */
43790#ifdef UA_ENABLE_IMMUTABLE_NODES
43791 UA_NODESTORE_RELEASE(server, node);
43792 node = UA_NODESTORE_GET(server, nodeId);
43793 if(!node || (node->head.nodeClass != UA_NODECLASS_VARIABLE &&
43794 node->head.nodeClass != UA_NODECLASS_VARIABLETYPE)) {
43795 retval = UA_STATUSCODE_BADINTERNALERROR;
43796 goto cleanup;
43797 }
43798#endif
43799
43800 /* Check if all attributes hold the constraints of the type now. The initial
43801 * attributes must type-check. The constructor might change the attributes
43802 * again. Then, the changes are type-checked by the normal write service. */
43803 retval = typeCheckVariableNode(server, session, node: &node->variableNode,
43804 vt: &type->variableTypeNode);
43805 if(retval != UA_STATUSCODE_GOOD) {
43806 UA_LOG_NODEID_INFO(&node->head.nodeId,
43807 UA_LOG_INFO_SESSION(&server->config.logger, session,
43808 "AddNode (%.*s): Type-checking "
43809 "failed with error code %s", (int)nodeIdStr.length,
43810 nodeIdStr.data, UA_StatusCode_name(retval)));
43811 goto cleanup;
43812 }
43813 }
43814
43815 /* Add (mandatory) child nodes from the type definition */
43816 if(node->head.nodeClass == UA_NODECLASS_VARIABLE ||
43817 node->head.nodeClass == UA_NODECLASS_OBJECT) {
43818 retval = addTypeChildren(server, session, nodeId, typeId: &type->head.nodeId);
43819 if(retval != UA_STATUSCODE_GOOD) {
43820 UA_LOG_NODEID_INFO(&node->head.nodeId,
43821 UA_LOG_INFO_SESSION(&server->config.logger, session,
43822 "AddNode (%.*s): Adding child nodes "
43823 "failed with error code %s", (int)nodeIdStr.length,
43824 nodeIdStr.data, UA_StatusCode_name(retval)));
43825 goto cleanup;
43826 }
43827 }
43828
43829 /* Add (mandatory) child nodes from the HasInterface references */
43830 if(node->head.nodeClass == UA_NODECLASS_OBJECT) {
43831 retval = addInterfaceChildren(server, session, nodeId, typeId: &type->head.nodeId);
43832 if(retval != UA_STATUSCODE_GOOD) {
43833 UA_LOG_NODEID_INFO(&node->head.nodeId,
43834 UA_LOG_INFO_SESSION(&server->config.logger, session,
43835 "AddNode (%.*s): Adding child nodes "
43836 "interface failed with error code %s",
43837 (int)nodeIdStr.length, nodeIdStr.data,
43838 UA_StatusCode_name(retval)));
43839 goto cleanup;
43840 }
43841 }
43842
43843 /* Set variables to dynamic (source and server timestamps are meaningful) if
43844 * they fulfill some conditions */
43845 if(node->head.nodeClass == UA_NODECLASS_VARIABLE) {
43846 retval = checkSetIsDynamicVariable(server, session, nodeId);
43847 if(retval != UA_STATUSCODE_GOOD)
43848 goto cleanup;
43849 }
43850
43851 /* Call the constructor(s) */
43852 constructor:
43853 if(!node->head.constructed)
43854 retval = recursiveCallConstructors(server, session, nodeId, type);
43855 if(retval != UA_STATUSCODE_GOOD) {
43856 UA_LOG_NODEID_INFO(&node->head.nodeId,
43857 UA_LOG_INFO_SESSION(&server->config.logger, session,
43858 "AddNode (%.*s): Calling the node constructor(s) "
43859 "failed with status code %s", (int)nodeIdStr.length,
43860 nodeIdStr.data, UA_StatusCode_name(retval)));
43861 }
43862
43863 cleanup:
43864 if(type)
43865 UA_NODESTORE_RELEASE(server, type);
43866 if(node)
43867 UA_NODESTORE_RELEASE(server, node);
43868 if(retval != UA_STATUSCODE_GOOD)
43869 deleteNode(server, nodeId: *nodeId, true);
43870 return retval;
43871}
43872
43873static void
43874Operation_addNode(UA_Server *server, UA_Session *session, void *nodeContext,
43875 const UA_AddNodesItem *item, UA_AddNodesResult *result) {
43876 result->statusCode =
43877 Operation_addNode_begin(server, session, nodeContext,
43878 item, parentNodeId: &item->parentNodeId.nodeId,
43879 referenceTypeId: &item->referenceTypeId, outNewNodeId: &result->addedNodeId);
43880 if(result->statusCode != UA_STATUSCODE_GOOD)
43881 return;
43882
43883 /* AddNodes_finish */
43884 result->statusCode = AddNode_finish(server, session, nodeId: &result->addedNodeId);
43885
43886 /* If finishing failed, the node was deleted */
43887 if(result->statusCode != UA_STATUSCODE_GOOD)
43888 UA_NodeId_clear(p: &result->addedNodeId);
43889}
43890
43891void
43892Service_AddNodes(UA_Server *server, UA_Session *session,
43893 const UA_AddNodesRequest *request,
43894 UA_AddNodesResponse *response) {
43895 UA_LOG_DEBUG_SESSION(&server->config.logger, session, "Processing AddNodesRequest");
43896 UA_LOCK_ASSERT(&server->serviceMutex, 1);
43897
43898 if(server->config.maxNodesPerNodeManagement != 0 &&
43899 request->nodesToAddSize > server->config.maxNodesPerNodeManagement) {
43900 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
43901 return;
43902 }
43903
43904 response->responseHeader.serviceResult =
43905 UA_Server_processServiceOperations(server, session,
43906 operationCallback: (UA_ServiceOperation)Operation_addNode, NULL,
43907 requestOperations: &request->nodesToAddSize,
43908 requestOperationsType: &UA_TYPES[UA_TYPES_ADDNODESITEM],
43909 responseOperations: &response->resultsSize,
43910 responseOperationsType: &UA_TYPES[UA_TYPES_ADDNODESRESULT]);
43911}
43912
43913UA_StatusCode
43914addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId *requestedNewNodeId,
43915 const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId,
43916 const UA_QualifiedName browseName, const UA_NodeId *typeDefinition,
43917 const UA_NodeAttributes *attr, const UA_DataType *attributeType,
43918 void *nodeContext, UA_NodeId *outNewNodeId) {
43919 UA_LOCK_ASSERT(&server->serviceMutex, 1);
43920
43921 /* Create the AddNodesItem */
43922 UA_AddNodesItem item;
43923 UA_AddNodesItem_init(p: &item);
43924 item.nodeClass = nodeClass;
43925 item.requestedNewNodeId.nodeId = *requestedNewNodeId;
43926 item.browseName = browseName;
43927 item.parentNodeId.nodeId = *parentNodeId;
43928 item.referenceTypeId = *referenceTypeId;
43929 item.typeDefinition.nodeId = *typeDefinition;
43930 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
43931 p: (void*)(uintptr_t)attr, type: attributeType);
43932
43933 /* Call the normal addnodes service */
43934 UA_AddNodesResult result;
43935 UA_AddNodesResult_init(p: &result);
43936 Operation_addNode(server, session: &server->adminSession, nodeContext, item: &item, result: &result);
43937 if(outNewNodeId)
43938 *outNewNodeId = result.addedNodeId;
43939 else
43940 UA_NodeId_clear(p: &result.addedNodeId);
43941 return result.statusCode;
43942}
43943
43944UA_StatusCode
43945__UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass,
43946 const UA_NodeId *requestedNewNodeId,
43947 const UA_NodeId *parentNodeId,
43948 const UA_NodeId *referenceTypeId,
43949 const UA_QualifiedName browseName,
43950 const UA_NodeId *typeDefinition,
43951 const UA_NodeAttributes *attr,
43952 const UA_DataType *attributeType,
43953 void *nodeContext, UA_NodeId *outNewNodeId) {
43954 UA_LOCK(&server->serviceMutex);
43955 UA_StatusCode reval =
43956 addNode(server, nodeClass, requestedNewNodeId, parentNodeId,
43957 referenceTypeId, browseName, typeDefinition, attr,
43958 attributeType, nodeContext, outNewNodeId);
43959 UA_UNLOCK(&server->serviceMutex);
43960 return reval;
43961}
43962
43963UA_StatusCode
43964UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass,
43965 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
43966 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
43967 const UA_NodeId typeDefinition, const void *attr,
43968 const UA_DataType *attributeType, void *nodeContext,
43969 UA_NodeId *outNewNodeId) {
43970 UA_AddNodesItem item;
43971 UA_AddNodesItem_init(p: &item);
43972 item.nodeClass = nodeClass;
43973 item.requestedNewNodeId.nodeId = requestedNewNodeId;
43974 item.browseName = browseName;
43975 item.typeDefinition.nodeId = typeDefinition;
43976 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes,
43977 p: (void*)(uintptr_t)attr, type: attributeType);
43978
43979 UA_LOCK(&server->serviceMutex);
43980 UA_StatusCode retval =
43981 Operation_addNode_begin(server, session: &server->adminSession, nodeContext, item: &item,
43982 parentNodeId: &parentNodeId, referenceTypeId: &referenceTypeId, outNewNodeId);
43983 UA_UNLOCK(&server->serviceMutex);
43984 return retval;
43985}
43986
43987UA_StatusCode
43988UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId) {
43989 UA_LOCK(&server->serviceMutex);
43990 UA_StatusCode retval = AddNode_finish(server, session: &server->adminSession, nodeId: &nodeId);
43991 UA_UNLOCK(&server->serviceMutex);
43992 return retval;
43993}
43994
43995/****************/
43996/* Delete Nodes */
43997/****************/
43998
43999static void
44000Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
44001 const UA_DeleteReferencesItem *item, UA_StatusCode *retval);
44002
44003/* Remove references to this node (in the other nodes) */
44004static void
44005removeIncomingReferences(UA_Server *server, UA_Session *session, const UA_NodeHead *head) {
44006 UA_DeleteReferencesItem item;
44007 UA_DeleteReferencesItem_init(p: &item);
44008 item.targetNodeId.nodeId = head->nodeId;
44009 item.deleteBidirectional = false;
44010
44011 UA_StatusCode dummy;
44012 for(size_t i = 0; i < head->referencesSize; ++i) {
44013 const UA_NodeReferenceKind *rk = &head->references[i];
44014 item.isForward = rk->isInverse;
44015 item.referenceTypeId =
44016 *UA_NODESTORE_GETREFERENCETYPEID(server, rk->referenceTypeIndex);
44017 const UA_ReferenceTarget *t = NULL;
44018 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
44019 if(!UA_NodePointer_isLocal(np: t->targetId))
44020 continue;
44021 item.sourceNodeId = UA_NodePointer_toNodeId(np: t->targetId);
44022 Operation_deleteReference(server, session, NULL, item: &item, retval: &dummy);
44023 }
44024 }
44025}
44026
44027/* A node is auto-deleted if all its hierarchical parents are being deleted */
44028static UA_Boolean
44029hasParentRef(const UA_NodeHead *head, const UA_ReferenceTypeSet *refSet,
44030 RefTree *refTree) {
44031 for(size_t i = 0; i < head->referencesSize; i++) {
44032 const UA_NodeReferenceKind *rk = &head->references[i];
44033 if(!rk->isInverse)
44034 continue;
44035 if(!UA_ReferenceTypeSet_contains(set: refSet, index: rk->referenceTypeIndex))
44036 continue;
44037 const UA_ReferenceTarget *t = NULL;
44038 while((t = UA_NodeReferenceKind_iterate(rk, prev: t))) {
44039 if(!UA_NodePointer_isLocal(np: t->targetId))
44040 continue;
44041 UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId);
44042 if(!RefTree_containsNodeId(rt: refTree, target: &tmpId))
44043 return true;
44044 }
44045 }
44046 return false;
44047}
44048
44049static void
44050deconstructNodeSet(UA_Server *server, UA_Session *session,
44051 UA_ReferenceTypeSet *hierarchRefsSet, RefTree *refTree) {
44052 /* Deconstruct the nodes based on the RefTree entries, parent nodes first */
44053 for(size_t i = 0; i < refTree->size; i++) {
44054 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i].nodeId);
44055 if(!member)
44056 continue;
44057
44058 /* Call the type-level destructor */
44059 void *context = member->head.context; /* No longer needed after this function */
44060 if(member->head.nodeClass == UA_NODECLASS_OBJECT ||
44061 member->head.nodeClass == UA_NODECLASS_VARIABLE) {
44062 const UA_Node *type = getNodeType(server, head: &member->head);
44063 if(type) {
44064 /* Get the lifecycle */
44065 const UA_NodeTypeLifecycle *lifecycle;
44066 if(member->head.nodeClass == UA_NODECLASS_OBJECT)
44067 lifecycle = &type->objectTypeNode.lifecycle;
44068 else
44069 lifecycle = &type->variableTypeNode.lifecycle;
44070
44071 /* Call the destructor */
44072 if(lifecycle->destructor) {
44073 UA_UNLOCK(&server->serviceMutex);
44074 lifecycle->destructor(server,
44075 &session->sessionId, session->sessionHandle,
44076 &type->head.nodeId, type->head.context,
44077 &member->head.nodeId, &context);
44078 UA_LOCK(&server->serviceMutex);
44079 }
44080
44081 /* Release the type node */
44082 UA_NODESTORE_RELEASE(server, type);
44083 }
44084 }
44085
44086 /* Call the global destructor */
44087 if(server->config.nodeLifecycle.destructor) {
44088 UA_UNLOCK(&server->serviceMutex);
44089 server->config.nodeLifecycle.destructor(server, &session->sessionId,
44090 session->sessionHandle,
44091 &member->head.nodeId, context);
44092 UA_LOCK(&server->serviceMutex);
44093 }
44094
44095 /* Release the node. Don't access the node context from here on. */
44096 UA_NODESTORE_RELEASE(server, member);
44097
44098 /* Set the constructed flag to false */
44099 UA_Server_editNode(server, session: &server->adminSession, nodeId: &refTree->targets[i].nodeId,
44100 callback: (UA_EditNodeCallback)setDeconstructedNode, NULL);
44101 }
44102}
44103
44104/* The processNodeLayer function searches all children's of the head node and
44105 * adds the children node to the RefTree if all incoming references sources are
44106 * contained in the RefTree (No external references to this node --> node can be
44107 * deleted) */
44108static UA_StatusCode
44109autoDeleteChildren(UA_Server *server, UA_Session *session, RefTree *refTree,
44110 const UA_ReferenceTypeSet *hierarchRefsSet, const UA_NodeHead *head){
44111 UA_StatusCode res = UA_STATUSCODE_GOOD;
44112 for(size_t i = 0; i < head->referencesSize; ++i) {
44113 /* Check if the ReferenceType is hierarchical */
44114 UA_NodeReferenceKind *refs = &head->references[i];
44115 if(!UA_ReferenceTypeSet_contains(set: hierarchRefsSet, index: refs->referenceTypeIndex))
44116 continue;
44117
44118 /* Check if the references are forward (to a child) */
44119 if(refs->isInverse)
44120 continue;
44121
44122 /* Loop over the references */
44123 const UA_ReferenceTarget *t = NULL;
44124 while((t = UA_NodeReferenceKind_iterate(rk: refs, prev: t))) {
44125 /* Get the child */
44126 const UA_Node *child = UA_NODESTORE_GETFROMREF(server, target: t->targetId);
44127 if(!child)
44128 continue;
44129
44130 /* Only delete child nodes that have no other parent */
44131 if(!hasParentRef(head: &child->head, refSet: hierarchRefsSet, refTree))
44132 res = RefTree_addNodeId(rt: refTree, target: &child->head.nodeId, NULL);
44133 UA_NODESTORE_RELEASE(server, child);
44134 if(res != UA_STATUSCODE_GOOD)
44135 return res;
44136 }
44137 }
44138 return UA_STATUSCODE_GOOD;
44139}
44140
44141/* Build up an ordered set (tree) of all nodes that can be deleted. Step through
44142 * the ordered set in order to avoid recursion. */
44143static UA_StatusCode
44144buildDeleteNodeSet(UA_Server *server, UA_Session *session,
44145 const UA_ReferenceTypeSet *hierarchRefsSet,
44146 const UA_NodeId *initial, UA_Boolean removeTargetRefs,
44147 RefTree *refTree) {
44148 /* Add the initial node to delete */
44149 UA_StatusCode res = RefTree_addNodeId(rt: refTree, target: initial, NULL);
44150 if(res != UA_STATUSCODE_GOOD)
44151 return res;
44152
44153 /* Find out which hierarchical children should also be deleted. We know
44154 * there are no "external" ExpandedNodeId in the RefTree. */
44155 size_t pos = 0;
44156 while(pos < refTree->size) {
44157 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[pos].nodeId);
44158 pos++;
44159 if(!member)
44160 continue;
44161 res |= autoDeleteChildren(server, session, refTree, hierarchRefsSet, head: &member->head);
44162 UA_NODESTORE_RELEASE(server, member);
44163 }
44164 return res;
44165}
44166
44167static void
44168deleteNodeSet(UA_Server *server, UA_Session *session,
44169 const UA_ReferenceTypeSet *hierarchRefsSet,
44170 UA_Boolean removeTargetRefs, RefTree *refTree) {
44171 /* Delete the nodes based on the RefTree entries */
44172 for(size_t i = refTree->size; i > 0; --i) {
44173 const UA_Node *member = UA_NODESTORE_GET(server, &refTree->targets[i-1].nodeId);
44174 if(!member)
44175 continue;
44176 UA_NODESTORE_RELEASE(server, member);
44177 if(removeTargetRefs)
44178 removeIncomingReferences(server, session, head: &member->head);
44179 UA_NODESTORE_REMOVE(server, &member->head.nodeId);
44180 }
44181}
44182
44183static void
44184deleteNodeOperation(UA_Server *server, UA_Session *session, void *context,
44185 const UA_DeleteNodesItem *item, UA_StatusCode *result) {
44186 /* Do not check access for server */
44187 if(session != &server->adminSession && server->config.accessControl.allowDeleteNode) {
44188 UA_UNLOCK(&server->serviceMutex);
44189 if(!server->config.accessControl.
44190 allowDeleteNode(server, &server->config.accessControl,
44191 &session->sessionId, session->sessionHandle, item)) {
44192 UA_LOCK(&server->serviceMutex);
44193 *result = UA_STATUSCODE_BADUSERACCESSDENIED;
44194 return;
44195 }
44196 UA_LOCK(&server->serviceMutex);
44197 }
44198
44199 const UA_Node *node = UA_NODESTORE_GET(server, &item->nodeId);
44200 if(!node) {
44201 *result = UA_STATUSCODE_BADNODEIDUNKNOWN;
44202 return;
44203 }
44204
44205 if(UA_Node_hasSubTypeOrInstances(head: &node->head)) {
44206 UA_LOG_NODEID_INFO(&node->head.nodeId,
44207 UA_LOG_INFO_SESSION(&server->config.logger, session, "DeleteNode (%.*s): "
44208 "Cannot delete a type node with active instances or "
44209 "subtypes", (int)nodeIdStr.length, nodeIdStr.data));
44210 UA_NODESTORE_RELEASE(server, node);
44211 *result = UA_STATUSCODE_BADINTERNALERROR;
44212 return;
44213 }
44214
44215 /* TODO: Check if the information model consistency is violated */
44216 /* TODO: Check if the node is a mandatory child of a parent */
44217
44218 /* Relase the node. Don't access the pointer after this! */
44219 UA_NODESTORE_RELEASE(server, node);
44220
44221 /* A node can be referenced with hierarchical references from several
44222 * parents in the information model. (But not in a circular way.) The
44223 * hierarchical references are checked to see if a node can be deleted.
44224 * Getting the type hierarchy can fail in case of low RAM. In that case the
44225 * nodes are always deleted. */
44226 UA_ReferenceTypeSet hierarchRefsSet;
44227 UA_NodeId hr = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
44228 *result = referenceTypeIndices(server, refType: &hr, indices: &hierarchRefsSet, true);
44229 if(*result != UA_STATUSCODE_GOOD)
44230 return;
44231
44232 /* The list of childs is needed for the deconstructing and deleting phase.
44233 * Within the processNodeLayer we generate a RefTree based set of childs
44234 * which can be deleted beside the parent node. */
44235 RefTree refTree;
44236 *result = RefTree_init(rt: &refTree);
44237 if(*result != UA_STATUSCODE_GOOD)
44238 return;
44239 *result = buildDeleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, initial: &item->nodeId,
44240 removeTargetRefs: item->deleteTargetReferences, refTree: &refTree);
44241 if(*result != UA_STATUSCODE_GOOD) {
44242 UA_LOG_WARNING_SESSION(&server->config.logger, session,
44243 "DeleteNode: Incomplete lookup of nodes. "
44244 "Still deleting what we have.");
44245 /* Continue, so the RefTree is cleaned up. Return the error message
44246 * anyway. */
44247 }
44248
44249 /* Deconstruct, then delete, then clean up the set */
44250 deconstructNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, refTree: &refTree);
44251 deleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet,
44252 removeTargetRefs: item->deleteTargetReferences, refTree: &refTree);
44253 RefTree_clear(rt: &refTree);
44254}
44255
44256void
44257Service_DeleteNodes(UA_Server *server, UA_Session *session,
44258 const UA_DeleteNodesRequest *request,
44259 UA_DeleteNodesResponse *response) {
44260 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44261 "Processing DeleteNodesRequest");
44262 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44263
44264 if(server->config.maxNodesPerNodeManagement != 0 &&
44265 request->nodesToDeleteSize > server->config.maxNodesPerNodeManagement) {
44266 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44267 return;
44268 }
44269
44270 response->responseHeader.serviceResult =
44271 UA_Server_processServiceOperations(server, session,
44272 operationCallback: (UA_ServiceOperation)deleteNodeOperation,
44273 NULL, requestOperations: &request->nodesToDeleteSize,
44274 requestOperationsType: &UA_TYPES[UA_TYPES_DELETENODESITEM],
44275 responseOperations: &response->resultsSize,
44276 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44277}
44278
44279UA_StatusCode
44280UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId,
44281 UA_Boolean deleteReferences) {
44282 UA_LOCK(&server->serviceMutex);
44283 UA_StatusCode retval = deleteNode(server, nodeId, deleteReferences);
44284 UA_UNLOCK(&server->serviceMutex);
44285 return retval;
44286}
44287
44288UA_StatusCode
44289deleteNode(UA_Server *server, const UA_NodeId nodeId,
44290 UA_Boolean deleteReferences) {
44291 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44292 UA_DeleteNodesItem item;
44293 item.deleteTargetReferences = deleteReferences;
44294 item.nodeId = nodeId;
44295 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44296 deleteNodeOperation(server, session: &server->adminSession, NULL, item: &item, result: &retval);
44297 return retval;
44298}
44299
44300/******************/
44301/* Add References */
44302/******************/
44303
44304struct AddNodeInfo {
44305 UA_Byte refTypeIndex;
44306 UA_Boolean isForward;
44307 const UA_ExpandedNodeId *targetNodeId;
44308 UA_UInt32 targetBrowseNameHash;
44309};
44310
44311static UA_StatusCode
44312addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
44313 const struct AddNodeInfo *info) {
44314 return UA_Node_addReference(node, refTypeIndex: info->refTypeIndex, isForward: info->isForward,
44315 targetNodeId: info->targetNodeId, targetBrowseNameHash: info->targetBrowseNameHash);
44316}
44317
44318static UA_StatusCode
44319deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node,
44320 const UA_DeleteReferencesItem *item) {
44321 const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
44322 if(!refType)
44323 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44324 if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
44325 UA_NODESTORE_RELEASE(server, refType);
44326 return UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44327 }
44328 UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
44329 UA_NODESTORE_RELEASE(server, refType);
44330 return UA_Node_deleteReference(node, refTypeIndex, isForward: item->isForward, targetNodeId: &item->targetNodeId);
44331}
44332
44333static void
44334Operation_addReference(UA_Server *server, UA_Session *session, void *context,
44335 const UA_AddReferencesItem *item, UA_StatusCode *retval) {
44336 (void)context;
44337 UA_assert(session);
44338
44339 /* Check access rights */
44340 if(session != &server->adminSession && server->config.accessControl.allowAddReference) {
44341 UA_UNLOCK(&server->serviceMutex);
44342 if (!server->config.accessControl.
44343 allowAddReference(server, &server->config.accessControl,
44344 &session->sessionId, session->sessionHandle, item)) {
44345 UA_LOCK(&server->serviceMutex);
44346 *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
44347 return;
44348 }
44349 UA_LOCK(&server->serviceMutex);
44350 }
44351
44352 /* TODO: Currently no expandednodeids are allowed */
44353 if(item->targetServerUri.length > 0) {
44354 *retval = UA_STATUSCODE_BADNOTIMPLEMENTED;
44355 return;
44356 }
44357
44358 /* Check the ReferenceType and get the index */
44359 const UA_Node *refType = UA_NODESTORE_GET(server, &item->referenceTypeId);
44360 if(!refType) {
44361 *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44362 return;
44363 }
44364 if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) {
44365 UA_NODESTORE_RELEASE(server, refType);
44366 *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID;
44367 return;
44368 }
44369 UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex;
44370 UA_NODESTORE_RELEASE(server, refType);
44371
44372 /* Get the source and target node BrowseName hash */
44373 const UA_Node *targetNode = UA_NODESTORE_GET(server, &item->targetNodeId.nodeId);
44374 if(!targetNode) {
44375 *retval = UA_STATUSCODE_BADTARGETNODEIDINVALID;
44376 return;
44377 }
44378 UA_UInt32 targetNameHash = UA_QualifiedName_hash(q: &targetNode->head.browseName);
44379 UA_NODESTORE_RELEASE(server, targetNode);
44380
44381 const UA_Node *sourceNode = UA_NODESTORE_GET(server, &item->sourceNodeId);
44382 if(!sourceNode) {
44383 *retval = UA_STATUSCODE_BADSOURCENODEIDINVALID;
44384 return;
44385 }
44386 UA_UInt32 sourceNameHash = UA_QualifiedName_hash(q: &sourceNode->head.browseName);
44387 UA_NODESTORE_RELEASE(server, sourceNode);
44388
44389 /* Compute the BrowseName hash and release the target */
44390 struct AddNodeInfo info;
44391 info.refTypeIndex = refTypeIndex;
44392 info.targetNodeId = &item->targetNodeId;
44393 info.isForward = item->isForward;
44394 info.targetBrowseNameHash = targetNameHash;
44395
44396 /* Add the first direction */
44397 *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44398 callback: (UA_EditNodeCallback)addOneWayReference, data: &info);
44399 UA_Boolean firstExisted = false;
44400 if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
44401 *retval = UA_STATUSCODE_GOOD;
44402 firstExisted = true;
44403 }
44404 if(*retval != UA_STATUSCODE_GOOD)
44405 return;
44406
44407 /* Add the second direction */
44408 UA_ExpandedNodeId target2;
44409 UA_ExpandedNodeId_init(p: &target2);
44410 target2.nodeId = item->sourceNodeId;
44411 info.targetNodeId = &target2;
44412 info.isForward = !info.isForward;
44413 info.targetBrowseNameHash = sourceNameHash;
44414 *retval = UA_Server_editNode(server, session, nodeId: &item->targetNodeId.nodeId,
44415 callback: (UA_EditNodeCallback)addOneWayReference, data: &info);
44416
44417 /* Second direction existed already */
44418 if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) {
44419 /* Calculate common duplicate reference not allowed result and set bad
44420 * result if BOTH directions already existed */
44421 if(UA_NodeId_equal(n1: &item->sourceNodeId, n2: &item->targetNodeId.nodeId)) {
44422 *retval = UA_STATUSCODE_GOOD;
44423 UA_LOG_INFO_SESSION(&server->config.logger, session, "The source node and the target node are identical. The check for duplicate references is skipped.");
44424 }
44425 else if(firstExisted) {
44426 *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED;
44427 return;
44428 }
44429 *retval = UA_STATUSCODE_GOOD;
44430 }
44431
44432 /* Remove first direction if the second direction failed */
44433 if(*retval != UA_STATUSCODE_GOOD && !firstExisted) {
44434 UA_DeleteReferencesItem deleteItem;
44435 deleteItem.sourceNodeId = item->sourceNodeId;
44436 deleteItem.referenceTypeId = item->referenceTypeId;
44437 deleteItem.isForward = item->isForward;
44438 deleteItem.targetNodeId = item->targetNodeId;
44439 deleteItem.deleteBidirectional = false;
44440 /* Ignore status code */
44441 UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44442 callback: (UA_EditNodeCallback)deleteOneWayReference, data: &deleteItem);
44443 }
44444}
44445
44446void
44447Service_AddReferences(UA_Server *server, UA_Session *session,
44448 const UA_AddReferencesRequest *request,
44449 UA_AddReferencesResponse *response) {
44450 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44451 "Processing AddReferencesRequest");
44452 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44453 UA_assert(session);
44454
44455 if(server->config.maxNodesPerNodeManagement != 0 &&
44456 request->referencesToAddSize > server->config.maxNodesPerNodeManagement) {
44457 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44458 return;
44459 }
44460
44461 response->responseHeader.serviceResult =
44462 UA_Server_processServiceOperations(server, session,
44463 operationCallback: (UA_ServiceOperation)Operation_addReference,
44464 NULL, requestOperations: &request->referencesToAddSize,
44465 requestOperationsType: &UA_TYPES[UA_TYPES_ADDREFERENCESITEM],
44466 responseOperations: &response->resultsSize,
44467 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44468}
44469
44470UA_StatusCode
44471UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId,
44472 const UA_NodeId refTypeId,
44473 const UA_ExpandedNodeId targetId,
44474 UA_Boolean isForward) {
44475 UA_AddReferencesItem item;
44476 UA_AddReferencesItem_init(p: &item);
44477 item.sourceNodeId = sourceId;
44478 item.referenceTypeId = refTypeId;
44479 item.isForward = isForward;
44480 item.targetNodeId = targetId;
44481
44482 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44483 UA_LOCK(&server->serviceMutex);
44484 Operation_addReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval);
44485 UA_UNLOCK(&server->serviceMutex);
44486 return retval;
44487}
44488
44489/*********************/
44490/* Delete References */
44491/*********************/
44492
44493static void
44494Operation_deleteReference(UA_Server *server, UA_Session *session, void *context,
44495 const UA_DeleteReferencesItem *item, UA_StatusCode *retval) {
44496 /* Do not check access for server */
44497 if(session != &server->adminSession &&
44498 server->config.accessControl.allowDeleteReference) {
44499 UA_UNLOCK(&server->serviceMutex);
44500 if (!server->config.accessControl.
44501 allowDeleteReference(server, &server->config.accessControl,
44502 &session->sessionId, session->sessionHandle, item)){
44503 UA_LOCK(&server->serviceMutex);
44504 *retval = UA_STATUSCODE_BADUSERACCESSDENIED;
44505 return;
44506 }
44507 UA_LOCK(&server->serviceMutex);
44508 }
44509
44510 // TODO: Check consistency constraints, remove the references.
44511 *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId,
44512 callback: (UA_EditNodeCallback)deleteOneWayReference,
44513 /* cast away const qualifier because callback
44514 * uses it anyway */
44515 data: (UA_DeleteReferencesItem *)(uintptr_t)item);
44516 if(*retval != UA_STATUSCODE_GOOD)
44517 return;
44518
44519 if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0)
44520 return;
44521
44522 UA_DeleteReferencesItem secondItem;
44523 UA_DeleteReferencesItem_init(p: &secondItem);
44524 secondItem.isForward = !item->isForward;
44525 secondItem.sourceNodeId = item->targetNodeId.nodeId;
44526 secondItem.targetNodeId.nodeId = item->sourceNodeId;
44527 secondItem.referenceTypeId = item->referenceTypeId;
44528 *retval = UA_Server_editNode(server, session, nodeId: &secondItem.sourceNodeId,
44529 callback: (UA_EditNodeCallback)deleteOneWayReference,
44530 data: &secondItem);
44531}
44532
44533void
44534Service_DeleteReferences(UA_Server *server, UA_Session *session,
44535 const UA_DeleteReferencesRequest *request,
44536 UA_DeleteReferencesResponse *response) {
44537 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
44538 "Processing DeleteReferencesRequest");
44539 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44540
44541 if(server->config.maxNodesPerNodeManagement != 0 &&
44542 request->referencesToDeleteSize > server->config.maxNodesPerNodeManagement) {
44543 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS;
44544 return;
44545 }
44546
44547 response->responseHeader.serviceResult =
44548 UA_Server_processServiceOperations(server, session,
44549 operationCallback: (UA_ServiceOperation)Operation_deleteReference,
44550 NULL, requestOperations: &request->referencesToDeleteSize,
44551 requestOperationsType: &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM],
44552 responseOperations: &response->resultsSize,
44553 responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]);
44554}
44555
44556UA_StatusCode
44557UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId,
44558 const UA_NodeId referenceTypeId, UA_Boolean isForward,
44559 const UA_ExpandedNodeId targetNodeId,
44560 UA_Boolean deleteBidirectional) {
44561 UA_DeleteReferencesItem item;
44562 item.sourceNodeId = sourceNodeId;
44563 item.referenceTypeId = referenceTypeId;
44564 item.isForward = isForward;
44565 item.targetNodeId = targetNodeId;
44566 item.deleteBidirectional = deleteBidirectional;
44567
44568 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44569 UA_LOCK(&server->serviceMutex);
44570 Operation_deleteReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval);
44571 UA_UNLOCK(&server->serviceMutex);
44572 return retval;
44573}
44574
44575/**********************/
44576/* Set Value Callback */
44577/**********************/
44578
44579static UA_StatusCode
44580setValueCallback(UA_Server *server, UA_Session *session,
44581 UA_VariableNode *node, const UA_ValueCallback *callback) {
44582 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44583 return UA_STATUSCODE_BADNODECLASSINVALID;
44584 node->value.data.callback = *callback;
44585 return UA_STATUSCODE_GOOD;
44586}
44587
44588UA_StatusCode
44589UA_Server_setVariableNode_valueCallback(UA_Server *server,
44590 const UA_NodeId nodeId,
44591 const UA_ValueCallback callback) {
44592 UA_LOCK(&server->serviceMutex);
44593 UA_StatusCode retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44594 callback: (UA_EditNodeCallback)setValueCallback,
44595 /* cast away const because
44596 * callback uses const anyway */
44597 data: (UA_ValueCallback *)(uintptr_t) &callback);
44598 UA_UNLOCK(&server->serviceMutex);
44599 return retval;
44600}
44601
44602/***************************************************/
44603/* Special Handling of Variables with Data Sources */
44604/***************************************************/
44605
44606UA_StatusCode
44607UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId,
44608 const UA_NodeId parentNodeId,
44609 const UA_NodeId referenceTypeId,
44610 const UA_QualifiedName browseName,
44611 const UA_NodeId typeDefinition,
44612 const UA_VariableAttributes attr,
44613 const UA_DataSource dataSource,
44614 void *nodeContext, UA_NodeId *outNewNodeId) {
44615 UA_AddNodesItem item;
44616 UA_AddNodesItem_init(p: &item);
44617 item.nodeClass = UA_NODECLASS_VARIABLE;
44618 item.requestedNewNodeId.nodeId = requestedNewNodeId;
44619 item.browseName = browseName;
44620 UA_ExpandedNodeId typeDefinitionId;
44621 UA_ExpandedNodeId_init(p: &typeDefinitionId);
44622 typeDefinitionId.nodeId = typeDefinition;
44623 item.typeDefinition = typeDefinitionId;
44624 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)&attr,
44625 type: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]);
44626 UA_NodeId newNodeId;
44627 if(!outNewNodeId) {
44628 newNodeId = UA_NODEID_NULL;
44629 outNewNodeId = &newNodeId;
44630 }
44631
44632 UA_LOCK(&server->serviceMutex);
44633 /* Create the node and add it to the nodestore */
44634 UA_StatusCode retval = AddNode_raw(server, session: &server->adminSession, nodeContext,
44635 item: &item, outNewNodeId);
44636 if(retval != UA_STATUSCODE_GOOD)
44637 goto cleanup;
44638
44639 /* Set the data source */
44640 retval = setVariableNode_dataSource(server, nodeId: *outNewNodeId, dataSource);
44641 if(retval != UA_STATUSCODE_GOOD)
44642 goto cleanup;
44643
44644 /* Typecheck and add references to parent and type definition */
44645 retval = AddNode_addRefs(server, session: &server->adminSession, nodeId: outNewNodeId, parentNodeId: &parentNodeId,
44646 referenceTypeId: &referenceTypeId, typeDefinitionId: &typeDefinition);
44647 if(retval != UA_STATUSCODE_GOOD)
44648 goto cleanup;
44649
44650 /* Call the constructors */
44651 retval = AddNode_finish(server, session: &server->adminSession, nodeId: outNewNodeId);
44652
44653 cleanup:
44654 UA_UNLOCK(&server->serviceMutex);
44655 if(outNewNodeId == &newNodeId)
44656 UA_NodeId_clear(p: &newNodeId);
44657
44658 return retval;
44659}
44660
44661static UA_StatusCode
44662setDataSource(UA_Server *server, UA_Session *session,
44663 UA_VariableNode *node, const UA_DataSource *dataSource) {
44664 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44665 return UA_STATUSCODE_BADNODECLASSINVALID;
44666 if(node->valueSource == UA_VALUESOURCE_DATA)
44667 UA_DataValue_clear(p: &node->value.data.value);
44668 node->value.dataSource = *dataSource;
44669 node->valueSource = UA_VALUESOURCE_DATASOURCE;
44670 return UA_STATUSCODE_GOOD;
44671}
44672
44673UA_StatusCode
44674setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
44675 const UA_DataSource dataSource) {
44676 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44677 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44678 callback: (UA_EditNodeCallback)setDataSource,
44679 /* casting away const because callback casts it back anyway */
44680 data: (UA_DataSource *) (uintptr_t)&dataSource);
44681}
44682
44683UA_StatusCode
44684UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId,
44685 const UA_DataSource dataSource) {
44686 UA_LOCK(&server->serviceMutex);
44687 UA_StatusCode retval = setVariableNode_dataSource(server, nodeId, dataSource);
44688 UA_UNLOCK(&server->serviceMutex);
44689 return retval;
44690}
44691
44692/******************************/
44693/* Set External Value Source */
44694/******************************/
44695static UA_StatusCode
44696setExternalValueSource(UA_Server *server, UA_Session *session,
44697 UA_VariableNode *node, const UA_ValueBackend *externalValueSource) {
44698 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44699 return UA_STATUSCODE_BADNODECLASSINVALID;
44700 node->valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL;
44701 node->valueBackend.backend.external.value =
44702 externalValueSource->backend.external.value;
44703 node->valueBackend.backend.external.callback.notificationRead =
44704 externalValueSource->backend.external.callback.notificationRead;
44705 node->valueBackend.backend.external.callback.userWrite =
44706 externalValueSource->backend.external.callback.userWrite;
44707 return UA_STATUSCODE_GOOD;
44708}
44709
44710/****************************/
44711/* Set Data Source Callback */
44712/****************************/
44713static UA_StatusCode
44714setDataSourceCallback(UA_Server *server, UA_Session *session,
44715 UA_VariableNode *node, const UA_DataSource *dataSource) {
44716 if(node->head.nodeClass != UA_NODECLASS_VARIABLE)
44717 return UA_STATUSCODE_BADNODECLASSINVALID;
44718 node->valueBackend.backendType = UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK;
44719 node->valueBackend.backend.dataSource.read = dataSource->read;
44720 node->valueBackend.backend.dataSource.write = dataSource->write;
44721 return UA_STATUSCODE_GOOD;
44722}
44723
44724/**********************/
44725/* Set Value Backend */
44726/**********************/
44727
44728UA_StatusCode
44729UA_Server_setVariableNode_valueBackend(UA_Server *server, const UA_NodeId nodeId,
44730 const UA_ValueBackend valueBackend){
44731 UA_StatusCode retval = UA_STATUSCODE_GOOD;
44732 UA_LOCK(&server->serviceMutex);
44733 switch(valueBackend.backendType){
44734 case UA_VALUEBACKENDTYPE_NONE:
44735 UA_UNLOCK(&server->serviceMutex);
44736 return UA_STATUSCODE_BADCONFIGURATIONERROR;
44737 case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK:
44738 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44739 callback: (UA_EditNodeCallback) setDataSourceCallback,
44740 data: (UA_DataSource *)(uintptr_t) &valueBackend.backend.dataSource);
44741 break;
44742 case UA_VALUEBACKENDTYPE_INTERNAL:
44743 break;
44744 case UA_VALUEBACKENDTYPE_EXTERNAL:
44745 retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
44746 callback: (UA_EditNodeCallback) setExternalValueSource,
44747 /* cast away const because callback uses const anyway */
44748 data: (UA_ValueCallback *)(uintptr_t) &valueBackend);
44749 break;
44750 }
44751
44752
44753 // UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId,
44754 // (UA_EditNodeCallback)setValueCallback,
44755 /* cast away const because callback uses const anyway */
44756 // (UA_ValueCallback *)(uintptr_t) &callback);
44757
44758
44759 UA_UNLOCK(&server->serviceMutex);
44760 return retval;
44761}
44762
44763
44764/************************************/
44765/* Special Handling of Method Nodes */
44766/************************************/
44767
44768#ifdef UA_ENABLE_METHODCALLS
44769
44770static const UA_NodeId hasproperty = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASPROPERTY}};
44771static const UA_NodeId propertytype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_PROPERTYTYPE}};
44772
44773static UA_StatusCode
44774UA_Server_addMethodNodeEx_finish(UA_Server *server, const UA_NodeId nodeId,
44775 UA_MethodCallback method,
44776 const size_t inputArgumentsSize,
44777 const UA_Argument *inputArguments,
44778 const UA_NodeId inputArgumentsRequestedNewNodeId,
44779 UA_NodeId *inputArgumentsOutNewNodeId,
44780 const size_t outputArgumentsSize,
44781 const UA_Argument *outputArguments,
44782 const UA_NodeId outputArgumentsRequestedNewNodeId,
44783 UA_NodeId *outputArgumentsOutNewNodeId) {
44784 /* Browse to see which argument nodes exist */
44785 UA_BrowseDescription bd;
44786 UA_BrowseDescription_init(p: &bd);
44787 bd.nodeId = nodeId;
44788 bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY);
44789 bd.includeSubtypes = false;
44790 bd.browseDirection = UA_BROWSEDIRECTION_FORWARD;
44791 bd.nodeClassMask = UA_NODECLASS_VARIABLE;
44792 bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME;
44793
44794 UA_BrowseResult br;
44795 UA_BrowseResult_init(p: &br);
44796 UA_UInt32 maxrefs = 0;
44797 Operation_Browse(server, session: &server->adminSession, maxrefs: &maxrefs, descr: &bd, result: &br);
44798
44799 UA_StatusCode retval = br.statusCode;
44800 if(retval != UA_STATUSCODE_GOOD) {
44801 deleteNode(server, nodeId, true);
44802 UA_BrowseResult_clear(p: &br);
44803 return retval;
44804 }
44805
44806 /* Filter out the argument nodes */
44807 UA_NodeId inputArgsId = UA_NODEID_NULL;
44808 UA_NodeId outputArgsId = UA_NODEID_NULL;
44809 const UA_QualifiedName inputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "InputArguments");
44810 const UA_QualifiedName outputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "OutputArguments");
44811 for(size_t i = 0; i < br.referencesSize; i++) {
44812 UA_ReferenceDescription *rd = &br.references[i];
44813 if(rd->browseName.namespaceIndex == 0 &&
44814 UA_String_equal(s1: &rd->browseName.name, s2: &inputArgsName.name))
44815 inputArgsId = rd->nodeId.nodeId;
44816 else if(rd->browseName.namespaceIndex == 0 &&
44817 UA_String_equal(s1: &rd->browseName.name, s2: &outputArgsName.name))
44818 outputArgsId = rd->nodeId.nodeId;
44819 }
44820
44821 /* Add the Input Arguments VariableNode */
44822 if(inputArgumentsSize > 0 && UA_NodeId_isNull(p: &inputArgsId)) {
44823 UA_VariableAttributes attr = UA_VariableAttributes_default;
44824 char *name = "InputArguments";
44825 attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
44826 attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
44827 attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
44828 UA_UInt32 inputArgsSize32 = (UA_UInt32)inputArgumentsSize;
44829 attr.arrayDimensions = &inputArgsSize32;
44830 attr.arrayDimensionsSize = 1;
44831 UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)inputArguments,
44832 arraySize: inputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
44833 retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: &inputArgumentsRequestedNewNodeId,
44834 parentNodeId: &nodeId, referenceTypeId: &hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
44835 typeDefinition: &propertytype, attr: (const UA_NodeAttributes*)&attr,
44836 attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
44837 NULL, outNewNodeId: &inputArgsId);
44838 if(retval != UA_STATUSCODE_GOOD)
44839 goto error;
44840 }
44841
44842 /* Add the Output Arguments VariableNode */
44843 if(outputArgumentsSize > 0 && UA_NodeId_isNull(p: &outputArgsId)) {
44844 UA_VariableAttributes attr = UA_VariableAttributes_default;
44845 char *name = "OutputArguments";
44846 attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name);
44847 attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId;
44848 attr.valueRank = UA_VALUERANK_ONE_DIMENSION;
44849 UA_UInt32 outputArgsSize32 = (UA_UInt32)outputArgumentsSize;
44850 attr.arrayDimensions = &outputArgsSize32;
44851 attr.arrayDimensionsSize = 1;
44852 UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)outputArguments,
44853 arraySize: outputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
44854 retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: &outputArgumentsRequestedNewNodeId,
44855 parentNodeId: &nodeId, referenceTypeId: &hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name),
44856 typeDefinition: &propertytype, attr: (const UA_NodeAttributes*)&attr,
44857 attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],
44858 NULL, outNewNodeId: &outputArgsId);
44859 if(retval != UA_STATUSCODE_GOOD)
44860 goto error;
44861 }
44862
44863 retval = setMethodNode_callback(server, methodNodeId: nodeId, methodCallback: method);
44864 if(retval != UA_STATUSCODE_GOOD)
44865 goto error;
44866
44867 /* Call finish to add the parent reference */
44868 retval = AddNode_finish(server, session: &server->adminSession, nodeId: &nodeId);
44869 if(retval != UA_STATUSCODE_GOOD)
44870 goto error;
44871
44872 if(inputArgumentsOutNewNodeId != NULL) {
44873 UA_NodeId_copy(src: &inputArgsId, dst: inputArgumentsOutNewNodeId);
44874 }
44875 if(outputArgumentsOutNewNodeId != NULL) {
44876 UA_NodeId_copy(src: &outputArgsId, dst: outputArgumentsOutNewNodeId);
44877 }
44878 UA_BrowseResult_clear(p: &br);
44879 return retval;
44880
44881error:
44882 deleteNode(server, nodeId, true);
44883 deleteNode(server, nodeId: inputArgsId, true);
44884 deleteNode(server, nodeId: outputArgsId, true);
44885 UA_BrowseResult_clear(p: &br);
44886 return retval;
44887}
44888
44889UA_StatusCode
44890UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId,
44891 UA_MethodCallback method,
44892 size_t inputArgumentsSize,
44893 const UA_Argument* inputArguments,
44894 size_t outputArgumentsSize,
44895 const UA_Argument* outputArguments) {
44896 UA_LOCK(&server->serviceMutex);
44897 UA_StatusCode retval =
44898 UA_Server_addMethodNodeEx_finish(server, nodeId, method,
44899 inputArgumentsSize, inputArguments,
44900 inputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL,
44901 outputArgumentsSize, outputArguments,
44902 outputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL);
44903 UA_UNLOCK(&server->serviceMutex);
44904 return retval;
44905}
44906
44907UA_StatusCode
44908UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId,
44909 const UA_NodeId parentNodeId,
44910 const UA_NodeId referenceTypeId,
44911 const UA_QualifiedName browseName,
44912 const UA_MethodAttributes attr, UA_MethodCallback method,
44913 size_t inputArgumentsSize, const UA_Argument *inputArguments,
44914 const UA_NodeId inputArgumentsRequestedNewNodeId,
44915 UA_NodeId *inputArgumentsOutNewNodeId,
44916 size_t outputArgumentsSize, const UA_Argument *outputArguments,
44917 const UA_NodeId outputArgumentsRequestedNewNodeId,
44918 UA_NodeId *outputArgumentsOutNewNodeId,
44919 void *nodeContext, UA_NodeId *outNewNodeId) {
44920 UA_AddNodesItem item;
44921 UA_AddNodesItem_init(p: &item);
44922 item.nodeClass = UA_NODECLASS_METHOD;
44923 item.requestedNewNodeId.nodeId = requestedNewNodeId;
44924 item.browseName = browseName;
44925 UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)&attr,
44926 type: &UA_TYPES[UA_TYPES_METHODATTRIBUTES]);
44927 UA_NodeId newId;
44928 if(!outNewNodeId) {
44929 UA_NodeId_init(p: &newId);
44930 outNewNodeId = &newId;
44931 }
44932 UA_LOCK(&server->serviceMutex);
44933 UA_StatusCode retval = Operation_addNode_begin(server, session: &server->adminSession,
44934 nodeContext, item: &item, parentNodeId: &parentNodeId,
44935 referenceTypeId: &referenceTypeId, outNewNodeId);
44936 if(retval != UA_STATUSCODE_GOOD) {
44937 UA_UNLOCK(&server->serviceMutex);
44938 return retval;
44939 }
44940
44941 retval = UA_Server_addMethodNodeEx_finish(server, nodeId: *outNewNodeId, method,
44942 inputArgumentsSize, inputArguments,
44943 inputArgumentsRequestedNewNodeId,
44944 inputArgumentsOutNewNodeId,
44945 outputArgumentsSize, outputArguments,
44946 outputArgumentsRequestedNewNodeId,
44947 outputArgumentsOutNewNodeId);
44948 UA_UNLOCK(&server->serviceMutex);
44949 if(outNewNodeId == &newId)
44950 UA_NodeId_clear(p: &newId);
44951 return retval;
44952}
44953
44954static UA_StatusCode
44955editMethodCallback(UA_Server *server, UA_Session* session,
44956 UA_Node *node, UA_MethodCallback methodCallback) {
44957 if(node->head.nodeClass != UA_NODECLASS_METHOD)
44958 return UA_STATUSCODE_BADNODECLASSINVALID;
44959 node->methodNode.method = methodCallback;
44960 return UA_STATUSCODE_GOOD;
44961}
44962
44963static UA_StatusCode
44964setMethodNode_callback(UA_Server *server,
44965 const UA_NodeId methodNodeId,
44966 UA_MethodCallback methodCallback) {
44967 UA_LOCK_ASSERT(&server->serviceMutex, 1);
44968 return UA_Server_editNode(server, session: &server->adminSession, nodeId: &methodNodeId,
44969 callback: (UA_EditNodeCallback)editMethodCallback,
44970 data: (void*)(uintptr_t)methodCallback);
44971}
44972
44973UA_StatusCode
44974UA_Server_setMethodNodeCallback(UA_Server *server,
44975 const UA_NodeId methodNodeId,
44976 UA_MethodCallback methodCallback) {
44977 UA_LOCK(&server->serviceMutex);
44978 UA_StatusCode retVal = setMethodNode_callback(server, methodNodeId, methodCallback);
44979 UA_UNLOCK(&server->serviceMutex);
44980 return retVal;
44981}
44982
44983UA_StatusCode
44984UA_Server_getMethodNodeCallback(UA_Server *server,
44985 const UA_NodeId methodNodeId,
44986 UA_MethodCallback *outMethodCallback) {
44987 UA_LOCK(&server->serviceMutex);
44988 const UA_Node *node = UA_NODESTORE_GET(server, &methodNodeId);
44989 if(!node) {
44990 UA_UNLOCK(&server->serviceMutex);
44991 return UA_STATUSCODE_BADNODEIDUNKNOWN;
44992 }
44993
44994 if(node->head.nodeClass != UA_NODECLASS_METHOD) {
44995 UA_NODESTORE_RELEASE(server, node);
44996 UA_UNLOCK(&server->serviceMutex);
44997 return UA_STATUSCODE_BADNODECLASSINVALID;
44998 }
44999
45000 *outMethodCallback = node->methodNode.method;
45001 UA_NODESTORE_RELEASE(server, node);
45002 UA_UNLOCK(&server->serviceMutex);
45003 return UA_STATUSCODE_GOOD;
45004}
45005
45006#endif
45007
45008/************************/
45009/* Lifecycle Management */
45010/************************/
45011
45012void UA_EXPORT
45013UA_Server_setAdminSessionContext(UA_Server *server,
45014 void *context) {
45015 server->adminSession.sessionHandle = context;
45016}
45017
45018static UA_StatusCode
45019setNodeTypeLifecycle(UA_Server *server, UA_Session *session,
45020 UA_Node *node, UA_NodeTypeLifecycle *lifecycle) {
45021 if(node->head.nodeClass == UA_NODECLASS_OBJECTTYPE) {
45022 node->objectTypeNode.lifecycle = *lifecycle;
45023 } else if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) {
45024 node->variableTypeNode.lifecycle = *lifecycle;
45025 } else {
45026 return UA_STATUSCODE_BADNODECLASSINVALID;
45027 }
45028 return UA_STATUSCODE_GOOD;
45029}
45030
45031UA_StatusCode
45032UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId,
45033 UA_NodeTypeLifecycle lifecycle) {
45034 UA_LOCK(&server->serviceMutex);
45035 UA_StatusCode retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId,
45036 callback: (UA_EditNodeCallback)setNodeTypeLifecycle,
45037 data: &lifecycle);
45038 UA_UNLOCK(&server->serviceMutex);
45039 return retval;
45040}
45041
45042/**** amalgamated original file "/src/server/ua_services_discovery_multicast.c" ****/
45043
45044/* This Source Code Form is subject to the terms of the Mozilla Public
45045 * License, v. 2.0. If a copy of the MPL was not distributed with this
45046 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
45047 *
45048 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
45049 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
45050 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
45051 */
45052
45053
45054#if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST)
45055
45056#if UA_MULTITHREADING >= 100
45057
45058static void *
45059multicastWorkerLoop(UA_Server *server) {
45060 struct timeval next_sleep = {.tv_sec = 0, .tv_usec = 0};
45061 volatile UA_Boolean *running = &server->discoveryManager.mdnsRunning;
45062 fd_set fds;
45063
45064 while(*running) {
45065 FD_ZERO(&fds);
45066 UA_fd_set(server->discoveryManager.mdnsSocket, &fds);
45067 select(server->discoveryManager.mdnsSocket + 1, &fds, 0, 0, &next_sleep);
45068
45069 if(!*running)
45070 break;
45071
45072 unsigned short retVal =
45073 mdnsd_step(server->discoveryManager.mdnsDaemon, server->discoveryManager.mdnsSocket,
45074 FD_ISSET(server->discoveryManager.mdnsSocket, &fds), true, &next_sleep);
45075 if(retVal == 1) {
45076 UA_LOG_SOCKET_ERRNO_WRAP(
45077 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
45078 "Multicast error: Can not read from socket. %s", errno_str));
45079 break;
45080 } else if (retVal == 2) {
45081 UA_LOG_SOCKET_ERRNO_WRAP(
45082 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45083 "Multicast error: Can not write to socket. %s", errno_str));
45084 break;
45085 }
45086 }
45087 return NULL;
45088}
45089
45090static UA_StatusCode
45091multicastListenStart(UA_Server* server) {
45092 int err = pthread_create(&server->discoveryManager.mdnsThread, NULL,
45093 (void* (*)(void*))multicastWorkerLoop, server);
45094 if(err != 0) {
45095 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
45096 "Multicast error: Can not create multicast thread.");
45097 return UA_STATUSCODE_BADUNEXPECTEDERROR;
45098 }
45099 return UA_STATUSCODE_GOOD;
45100}
45101
45102static UA_StatusCode
45103multicastListenStop(UA_Server* server) {
45104 mdnsd_shutdown(server->discoveryManager.mdnsDaemon);
45105 // wake up select
45106 if (write(server->discoveryManager.mdnsSocket, "\0", 1)) {
45107 // TODO: if makes no sense here?
45108 } // TODO: move to arch?
45109 if (pthread_join(server->discoveryManager.mdnsThread, NULL)) {
45110 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Multicast error: Can not stop thread.");
45111 return UA_STATUSCODE_BADUNEXPECTEDERROR;
45112 }
45113 return UA_STATUSCODE_BADNOTIMPLEMENTED;
45114}
45115
45116# endif /* UA_MULTITHREADING */
45117
45118static UA_StatusCode
45119addMdnsRecordForNetworkLayer(UA_Server *server, const UA_String *appName,
45120 const UA_ServerNetworkLayer* nl) {
45121 UA_String hostname = UA_STRING_NULL;
45122 UA_UInt16 port = 4840;
45123 UA_String path = UA_STRING_NULL;
45124 UA_StatusCode retval = UA_parseEndpointUrl(&nl->discoveryUrl, &hostname,
45125 &port, &path);
45126 if(retval != UA_STATUSCODE_GOOD) {
45127 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
45128 "Server url is invalid: %.*s",
45129 (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
45130 return retval;
45131 }
45132
45133 retval = UA_Discovery_addRecord(server, appName, &hostname, port,
45134 &path, UA_DISCOVERY_TCP, true,
45135 server->config.mdnsConfig.serverCapabilities,
45136 server->config.mdnsConfig.serverCapabilitiesSize,
45137 true);
45138 if(retval != UA_STATUSCODE_GOOD) {
45139 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
45140 "Cannot add mDNS Record: %s",
45141 UA_StatusCode_name(retval));
45142 return retval;
45143 }
45144 return UA_STATUSCODE_GOOD;
45145}
45146
45147void startMulticastDiscoveryServer(UA_Server *server) {
45148 initMulticastDiscoveryServer(&server->discoveryManager, server);
45149
45150 UA_String *appName = &server->config.mdnsConfig.mdnsServerName;
45151 for(size_t i = 0; i < server->config.networkLayersSize; i++)
45152 addMdnsRecordForNetworkLayer(server, appName, &server->config.networkLayers[i]);
45153
45154 /* find any other server on the net */
45155 UA_Discovery_multicastQuery(server);
45156
45157#if UA_MULTITHREADING >= 100
45158 multicastListenStart(server);
45159# endif
45160}
45161
45162void
45163stopMulticastDiscoveryServer(UA_Server *server) {
45164 if (!server->discoveryManager.mdnsDaemon)
45165 return;
45166
45167 for (size_t i=0; i<server->config.networkLayersSize; i++) {
45168
45169 UA_String hostname = UA_STRING_NULL;
45170 UA_String path = UA_STRING_NULL;
45171 UA_UInt16 port = 0;
45172
45173 UA_StatusCode retval = UA_parseEndpointUrl(&server->config.networkLayers[i].discoveryUrl, &hostname,
45174 &port, &path);
45175
45176 if (retval != UA_STATUSCODE_GOOD)
45177 continue;
45178
45179 UA_Discovery_removeRecord(server, &server->config.mdnsConfig.mdnsServerName,
45180 &hostname, port, true);
45181
45182 }
45183
45184#if UA_MULTITHREADING >= 100
45185 multicastListenStop(server);
45186# else
45187 // send out last package with TTL = 0
45188 iterateMulticastDiscoveryServer(server, NULL, false);
45189# endif
45190}
45191
45192/* All filter criteria must be fulfilled in the list entry. The comparison is case
45193 * insensitive.
45194 * @returns true if the entry matches the filter. False if the filter does not match.
45195 * */
45196static UA_Boolean
45197entryMatchesCapabilityFilter(size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
45198 serverOnNetwork_list_entry* current) {
45199 // if the entry has less capabilities defined than the filter, there's no match
45200 if (serverCapabilityFilterSize > current->serverOnNetwork.serverCapabilitiesSize)
45201 return UA_FALSE;
45202 for(size_t i = 0; i < serverCapabilityFilterSize; i++) {
45203 UA_Boolean capabilityFound = UA_FALSE;
45204 for(size_t j = 0; j < current->serverOnNetwork.serverCapabilitiesSize; j++) {
45205 if(UA_String_equal_ignorecase(&serverCapabilityFilter[i],
45206 &current->serverOnNetwork.serverCapabilities[j])) {
45207 capabilityFound = UA_TRUE;
45208 break;
45209 }
45210 }
45211 if (!capabilityFound)
45212 return UA_FALSE; // entry does not match capability
45213 }
45214 return UA_TRUE;
45215}
45216
45217void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session,
45218 const UA_FindServersOnNetworkRequest *request,
45219 UA_FindServersOnNetworkResponse *response) {
45220 UA_LOCK_ASSERT(&server->serviceMutex, 1);
45221
45222 if (!server->config.mdnsEnabled) {
45223 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED;
45224 return;
45225 }
45226
45227 /* Set LastCounterResetTime */
45228 UA_DateTime_copy(&server->discoveryManager.serverOnNetworkRecordIdLastReset,
45229 &response->lastCounterResetTime);
45230
45231 /* Compute the max number of records to return */
45232 UA_UInt32 recordCount = 0;
45233 if(request->startingRecordId < server->discoveryManager.serverOnNetworkRecordIdCounter)
45234 recordCount = server->discoveryManager.serverOnNetworkRecordIdCounter -
45235 request->startingRecordId;
45236 if(request->maxRecordsToReturn && recordCount > request->maxRecordsToReturn)
45237 recordCount = UA_MIN(recordCount, request->maxRecordsToReturn);
45238 if(recordCount == 0) {
45239 response->serversSize = 0;
45240 return;
45241 }
45242
45243 /* Iterate over all records and add to filtered list */
45244 UA_UInt32 filteredCount = 0;
45245 UA_STACKARRAY(UA_ServerOnNetwork*, filtered, recordCount);
45246 serverOnNetwork_list_entry* current;
45247 LIST_FOREACH(current, &server->discoveryManager.serverOnNetwork, pointers) {
45248 if(filteredCount >= recordCount)
45249 break;
45250 if(current->serverOnNetwork.recordId < request->startingRecordId)
45251 continue;
45252 if(!entryMatchesCapabilityFilter(request->serverCapabilityFilterSize,
45253 request->serverCapabilityFilter, current))
45254 continue;
45255 filtered[filteredCount++] = &current->serverOnNetwork;
45256 }
45257
45258 if(filteredCount == 0)
45259 return;
45260
45261 /* Allocate the array for the response */
45262 response->servers =
45263 (UA_ServerOnNetwork*)UA_malloc(sizeof(UA_ServerOnNetwork)*filteredCount);
45264 if(!response->servers) {
45265 response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
45266 return;
45267 }
45268 response->serversSize = filteredCount;
45269
45270 /* Copy the server names */
45271 for(size_t i = 0; i < filteredCount; i++)
45272 UA_ServerOnNetwork_copy(filtered[i], &response->servers[filteredCount-i-1]);
45273}
45274
45275void
45276UA_Server_updateMdnsForDiscoveryUrl(UA_Server *server, const UA_String *serverName,
45277 const UA_MdnsDiscoveryConfiguration *mdnsConfig,
45278 const UA_String *discoveryUrl,
45279 UA_Boolean isOnline, UA_Boolean updateTxt) {
45280 UA_String hostname = UA_STRING_NULL;
45281 UA_UInt16 port = 4840;
45282 UA_String path = UA_STRING_NULL;
45283 UA_StatusCode retval = UA_parseEndpointUrl(discoveryUrl, &hostname, &port, &path);
45284 if(retval != UA_STATUSCODE_GOOD) {
45285 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_NETWORK,
45286 "Server url invalid: %.*s",
45287 (int)discoveryUrl->length, discoveryUrl->data);
45288 return;
45289 }
45290
45291 if(!isOnline) {
45292 UA_StatusCode removeRetval =
45293 UA_Discovery_removeRecord(server, serverName, &hostname,
45294 port, updateTxt);
45295 if(removeRetval != UA_STATUSCODE_GOOD)
45296 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45297 "Could not remove mDNS record for hostname %.*s.",
45298 (int)serverName->length, serverName->data);
45299 return;
45300 }
45301
45302 UA_String *capabilities = NULL;
45303 size_t capabilitiesSize = 0;
45304 if(mdnsConfig) {
45305 capabilities = mdnsConfig->serverCapabilities;
45306 capabilitiesSize = mdnsConfig->serverCapabilitiesSize;
45307 }
45308
45309 UA_StatusCode addRetval =
45310 UA_Discovery_addRecord(server, serverName, &hostname,
45311 port, &path, UA_DISCOVERY_TCP, updateTxt,
45312 capabilities, capabilitiesSize,
45313 false);
45314 if(addRetval != UA_STATUSCODE_GOOD)
45315 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45316 "Could not add mDNS record for hostname %.*s.",
45317 (int)serverName->length, serverName->data);
45318}
45319
45320void
45321UA_Server_setServerOnNetworkCallback(UA_Server *server,
45322 UA_Server_serverOnNetworkCallback cb,
45323 void* data) {
45324 UA_LOCK(&server->serviceMutex);
45325 server->discoveryManager.serverOnNetworkCallback = cb;
45326 server->discoveryManager.serverOnNetworkCallbackData = data;
45327 UA_UNLOCK(&server->serviceMutex);
45328}
45329
45330static void
45331UA_Discovery_multicastConflict(char *name, int type, void *arg) {
45332 // cppcheck-suppress unreadVariable
45333 UA_Server *server = (UA_Server*) arg;
45334 UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER,
45335 "Multicast DNS name conflict detected: "
45336 "'%s' for type %d", name, type);
45337}
45338
45339/* Create a service domain with the format [servername]-[hostname]._opcua-tcp._tcp.local. */
45340static void
45341createFullServiceDomain(char *outServiceDomain, size_t maxLen,
45342 const UA_String *servername, const UA_String *hostname) {
45343 size_t hostnameLen = hostname->length;
45344 size_t servernameLen = servername->length;
45345
45346 maxLen -= 24; /* the length we have remaining before the opc ua postfix and
45347 * the trailing zero */
45348
45349 /* Can we use hostname and servername with full length? */
45350 if(hostnameLen + servernameLen + 1 > maxLen) {
45351 if(servernameLen + 2 > maxLen) {
45352 servernameLen = maxLen;
45353 hostnameLen = 0;
45354 } else {
45355 hostnameLen = maxLen - servernameLen - 1;
45356 }
45357 }
45358
45359 size_t offset = 0;
45360 if (hostnameLen > 0) {
45361 UA_snprintf(outServiceDomain, maxLen + 1, "%.*s-%.*s",
45362 (int) servernameLen, (char *) servername->data,
45363 (int) hostnameLen, (char *) hostname->data);
45364 offset = servernameLen + hostnameLen + 1;
45365 //replace all dots with minus. Otherwise mDNS is not valid
45366 for (size_t i=servernameLen+1; i<offset; i++) {
45367 if (outServiceDomain[i] == '.')
45368 outServiceDomain[i] = '-';
45369 }
45370 }
45371 else {
45372 UA_snprintf(outServiceDomain, maxLen + 1, "%.*s",
45373 (int) servernameLen, (char *) servername->data);
45374 offset = servernameLen;
45375 }
45376 UA_snprintf(&outServiceDomain[offset], 24, "._opcua-tcp._tcp.local.");
45377}
45378
45379/* Check if mDNS already has an entry for given hostname and port combination */
45380static UA_Boolean
45381UA_Discovery_recordExists(UA_Server* server, const char* fullServiceDomain,
45382 unsigned short port, const UA_DiscoveryProtocol protocol) {
45383 // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
45384 mdns_record_t *r = mdnsd_get_published(server->discoveryManager.mdnsDaemon, fullServiceDomain);
45385 while(r) {
45386 const mdns_answer_t *data = mdnsd_record_data(r);
45387 if(data->type == QTYPE_SRV && (port == 0 || data->srv.port == port))
45388 return true;
45389 r = mdnsd_record_next(r);
45390 }
45391 return false;
45392}
45393
45394static int
45395discovery_multicastQueryAnswer(mdns_answer_t *a, void *arg) {
45396 UA_Server *server = (UA_Server*) arg;
45397 if(a->type != QTYPE_PTR)
45398 return 0;
45399
45400 if(a->rdname == NULL)
45401 return 0;
45402
45403 /* Skip, if we already know about this server */
45404 UA_Boolean exists =
45405 UA_Discovery_recordExists(server, a->rdname, 0, UA_DISCOVERY_TCP);
45406 if(exists == true)
45407 return 0;
45408
45409 if(mdnsd_has_query(server->discoveryManager.mdnsDaemon, a->rdname))
45410 return 0;
45411
45412 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45413 "mDNS send query for: %s SRV&TXT %s", a->name, a->rdname);
45414
45415 mdnsd_query(server->discoveryManager.mdnsDaemon, a->rdname, QTYPE_SRV,
45416 discovery_multicastQueryAnswer, server);
45417 mdnsd_query(server->discoveryManager.mdnsDaemon, a->rdname, QTYPE_TXT,
45418 discovery_multicastQueryAnswer, server);
45419 return 0;
45420}
45421
45422UA_StatusCode
45423UA_Discovery_multicastQuery(UA_Server* server) {
45424 mdnsd_query(server->discoveryManager.mdnsDaemon, "_opcua-tcp._tcp.local.",
45425 QTYPE_PTR,discovery_multicastQueryAnswer, server);
45426 return UA_STATUSCODE_GOOD;
45427}
45428
45429UA_StatusCode
45430UA_Discovery_addRecord(UA_Server *server, const UA_String *servername,
45431 const UA_String *hostname, UA_UInt16 port,
45432 const UA_String *path, const UA_DiscoveryProtocol protocol,
45433 UA_Boolean createTxt, const UA_String* capabilites,
45434 const size_t capabilitiesSize,
45435 UA_Boolean isSelf) {
45436 // we assume that the hostname is not an IP address, but a valid domain name
45437 // It is required by the OPC UA spec (see Part 12, DiscoveryURL to DNS SRV mapping)
45438 // to always use the hostname instead of the IP address
45439
45440 if(capabilitiesSize > 0 && !capabilites)
45441 return UA_STATUSCODE_BADINVALIDARGUMENT;
45442
45443 size_t hostnameLen = hostname->length;
45444 size_t servernameLen = servername->length;
45445 if(hostnameLen == 0 || servernameLen == 0)
45446 return UA_STATUSCODE_BADOUTOFRANGE;
45447
45448 // use a limit for the hostname length to make sure full string fits into 63
45449 // chars (limited by DNS spec)
45450 if(hostnameLen+servernameLen + 1 > 63) { // include dash between servername-hostname
45451 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45452 "Multicast DNS: Combination of hostname+servername exceeds "
45453 "maximum of 62 chars. It will be truncated.");
45454 } else if(hostnameLen > 63) {
45455 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45456 "Multicast DNS: Hostname length exceeds maximum of 63 chars. "
45457 "It will be truncated.");
45458 }
45459
45460 if(!server->discoveryManager.mdnsMainSrvAdded) {
45461 mdns_record_t *r =
45462 mdnsd_shared(server->discoveryManager.mdnsDaemon, "_services._dns-sd._udp.local.",
45463 QTYPE_PTR, 600);
45464 mdnsd_set_host(server->discoveryManager.mdnsDaemon, r, "_opcua-tcp._tcp.local.");
45465 server->discoveryManager.mdnsMainSrvAdded = true;
45466 }
45467
45468 // [servername]-[hostname]._opcua-tcp._tcp.local.
45469 char fullServiceDomain[63+24];
45470 createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
45471
45472 UA_Boolean exists = UA_Discovery_recordExists(server, fullServiceDomain, port, protocol);
45473 if(exists == true)
45474 return UA_STATUSCODE_GOOD;
45475
45476 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
45477 "Multicast DNS: add record for domain: %s", fullServiceDomain);
45478
45479
45480 if (isSelf && server->discoveryManager.selfFqdnMdnsRecord.length == 0) {
45481 server->discoveryManager.selfFqdnMdnsRecord = UA_STRING_ALLOC(fullServiceDomain);
45482 if (!server->discoveryManager.selfFqdnMdnsRecord.data)
45483 return UA_STATUSCODE_BADOUTOFMEMORY;
45484 }
45485
45486
45487 struct serverOnNetwork_list_entry *listEntry;
45488 // The servername is servername + hostname. It is the same which we get through mDNS and therefore we need to match servername
45489 UA_StatusCode retval = UA_DiscoveryManager_addEntryToServersOnNetwork(server, fullServiceDomain, fullServiceDomain,
45490 UA_MIN(63, (servernameLen+hostnameLen)+1), &listEntry);
45491 if (retval != UA_STATUSCODE_GOOD && retval != UA_STATUSCODE_BADALREADYEXISTS)
45492 return retval;
45493
45494 // If entry is already in list, skip initialization of capabilities and txt+srv
45495 if (retval != UA_STATUSCODE_BADALREADYEXISTS) {
45496 // if capabilitiesSize is 0, then add default cap 'NA'
45497 listEntry->serverOnNetwork.serverCapabilitiesSize = UA_MAX(1, capabilitiesSize);
45498 listEntry->serverOnNetwork.serverCapabilities =
45499 (UA_String *) UA_Array_new(listEntry->serverOnNetwork.serverCapabilitiesSize, &UA_TYPES[UA_TYPES_STRING]);
45500 if (!listEntry->serverOnNetwork.serverCapabilities)
45501 return UA_STATUSCODE_BADOUTOFMEMORY;
45502 if (capabilitiesSize == 0) {
45503 UA_String na;
45504 na.length = 2;
45505 na.data = (UA_Byte *) (uintptr_t) "NA";
45506 UA_String_copy(&na, &listEntry->serverOnNetwork.serverCapabilities[0]);
45507 } else {
45508 for (size_t i = 0; i < capabilitiesSize; i++) {
45509 UA_String_copy(&capabilites[i], &listEntry->serverOnNetwork.serverCapabilities[i]);
45510 }
45511 }
45512
45513 listEntry->txtSet = true;
45514
45515 UA_STACKARRAY(char, newUrl, 10 + hostnameLen + 8 + path->length + 1);
45516 UA_snprintf(newUrl, 10 + hostnameLen + 8 + path->length + 1, "opc.tcp://%.*s:%d%s%.*s", (int) hostnameLen,
45517 hostname->data, port, path->length > 0 ? "/" : "", (int) path->length, path->data);
45518 listEntry->serverOnNetwork.discoveryUrl = UA_String_fromChars(newUrl);
45519 listEntry->srvSet = true;
45520 }
45521
45522 // _services._dns-sd._udp.local. PTR _opcua-tcp._tcp.local
45523
45524 // check if there is already a PTR entry for the given service.
45525
45526 // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
45527 mdns_record_t *r = mdns_find_record(server->discoveryManager.mdnsDaemon, QTYPE_PTR,
45528 "_opcua-tcp._tcp.local.", fullServiceDomain);
45529 if(!r) {
45530 r = mdnsd_shared(server->discoveryManager.mdnsDaemon, "_opcua-tcp._tcp.local.", QTYPE_PTR, 600);
45531 mdnsd_set_host(server->discoveryManager.mdnsDaemon, r, fullServiceDomain);
45532 }
45533
45534 /* The first 63 characters of the hostname (or less) */
45535 size_t maxHostnameLen = UA_MIN(hostnameLen, 63);
45536 char localDomain[65];
45537 memcpy(localDomain, hostname->data, maxHostnameLen);
45538 localDomain[maxHostnameLen] = '.';
45539 localDomain[maxHostnameLen+1] = '\0';
45540
45541 // [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port [hostname].
45542 r = mdnsd_unique(server->discoveryManager.mdnsDaemon, fullServiceDomain, QTYPE_SRV, 600,
45543 UA_Discovery_multicastConflict, server);
45544 mdnsd_set_srv(server->discoveryManager.mdnsDaemon, r, 0, 0, port, localDomain);
45545
45546 // A/AAAA record for all ip addresses.
45547 // [servername]-[hostname]._opcua-tcp._tcp.local. A [ip].
45548 // [hostname]. A [ip].
45549 mdns_set_address_record(server, fullServiceDomain, localDomain);
45550
45551 // TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
45552 UA_STACKARRAY(char, pathChars, path->length + 1);
45553 if(createTxt) {
45554 if(path->length > 0)
45555 memcpy(pathChars, path->data, path->length);
45556 pathChars[path->length] = 0;
45557 mdns_create_txt(server, fullServiceDomain, pathChars, capabilites,
45558 capabilitiesSize, UA_Discovery_multicastConflict);
45559 }
45560
45561 return UA_STATUSCODE_GOOD;
45562}
45563
45564UA_StatusCode
45565UA_Discovery_removeRecord(UA_Server *server, const UA_String *servername,
45566 const UA_String *hostname, UA_UInt16 port,
45567 UA_Boolean removeTxt) {
45568 // use a limit for the hostname length to make sure full string fits into 63
45569 // chars (limited by DNS spec)
45570 size_t hostnameLen = hostname->length;
45571 size_t servernameLen = servername->length;
45572 if(hostnameLen == 0 || servernameLen == 0)
45573 return UA_STATUSCODE_BADOUTOFRANGE;
45574
45575 if(hostnameLen+servernameLen+1 > 63) { // include dash between servername-hostname
45576 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45577 "Multicast DNS: Combination of hostname+servername exceeds "
45578 "maximum of 62 chars. It will be truncated.");
45579 }
45580
45581 // [servername]-[hostname]._opcua-tcp._tcp.local.
45582 char fullServiceDomain[63 + 24];
45583 createFullServiceDomain(fullServiceDomain, 63+24, servername, hostname);
45584
45585 UA_LOG_INFO(&server->config.logger, UA_LOGCATEGORY_SERVER,
45586 "Multicast DNS: remove record for domain: %s", fullServiceDomain);
45587
45588 UA_StatusCode retval = UA_DiscoveryManager_removeEntryFromServersOnNetwork(
45589 server, fullServiceDomain, fullServiceDomain, UA_MIN(63, (servernameLen+hostnameLen)+1));
45590 if (retval != UA_STATUSCODE_GOOD)
45591 return retval;
45592
45593 // _opcua-tcp._tcp.local. PTR [servername]-[hostname]._opcua-tcp._tcp.local.
45594 mdns_record_t *r = mdns_find_record(server->discoveryManager.mdnsDaemon, QTYPE_PTR,
45595 "_opcua-tcp._tcp.local.", fullServiceDomain);
45596 if(!r) {
45597 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45598 "Multicast DNS: could not remove record. "
45599 "PTR Record not found for domain: %s", fullServiceDomain);
45600 return UA_STATUSCODE_BADNOTHINGTODO;
45601 }
45602 mdnsd_done(server->discoveryManager.mdnsDaemon, r);
45603
45604 // looks for [servername]-[hostname]._opcua-tcp._tcp.local. 86400 IN SRV 0 5 port hostname.local.
45605 // and TXT record: [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,...
45606 // and A record: [servername]-[hostname]._opcua-tcp._tcp.local. A [ip]
45607 mdns_record_t *r2 = mdnsd_get_published(server->discoveryManager.mdnsDaemon, fullServiceDomain);
45608 if(!r2) {
45609 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
45610 "Multicast DNS: could not remove record. Record not "
45611 "found for domain: %s", fullServiceDomain);
45612 return UA_STATUSCODE_BADNOTHINGTODO;
45613 }
45614
45615 while(r2) {
45616 const mdns_answer_t *data = mdnsd_record_data(r2);
45617 mdns_record_t *next = mdnsd_record_next(r2);
45618 if((removeTxt && data->type == QTYPE_TXT) ||
45619 (removeTxt && data->type == QTYPE_A) ||
45620 data->srv.port == port) {
45621 mdnsd_done(server->discoveryManager.mdnsDaemon, r2);
45622 }
45623 r2 = next;
45624 }
45625
45626 return UA_STATUSCODE_GOOD;
45627}
45628
45629UA_StatusCode
45630iterateMulticastDiscoveryServer(UA_Server* server, UA_DateTime *nextRepeat,
45631 UA_Boolean processIn) {
45632 struct timeval next_sleep = { 0, 0 };
45633 unsigned short retval = mdnsd_step(server->discoveryManager.mdnsDaemon,
45634 (int)server->discoveryManager.mdnsSocket,
45635 processIn, true, &next_sleep);
45636 if(retval == 1) {
45637 UA_LOG_SOCKET_ERRNO_WRAP(
45638 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45639 "Multicast error: Can not read from socket. %s", errno_str));
45640 return UA_STATUSCODE_BADNOCOMMUNICATION;
45641 } else if(retval == 2) {
45642 UA_LOG_SOCKET_ERRNO_WRAP(
45643 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
45644 "Multicast error: Can not write to socket. %s", errno_str));
45645 return UA_STATUSCODE_BADNOCOMMUNICATION;
45646 }
45647
45648 if(nextRepeat)
45649 *nextRepeat = UA_DateTime_now() +
45650 (UA_DateTime)((next_sleep.tv_sec * UA_DATETIME_SEC) +
45651 (next_sleep.tv_usec * UA_DATETIME_USEC));
45652 return UA_STATUSCODE_GOOD;
45653}
45654
45655#endif /* defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) */
45656
45657/**** amalgamated original file "/src/client/ua_client.c" ****/
45658
45659/* This Source Code Form is subject to the terms of the Mozilla Public
45660 * License, v. 2.0. If a copy of the MPL was not distributed with this
45661 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
45662 *
45663 * Copyright 2015-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
45664 * Copyright 2015-2016 (c) Sten Grüner
45665 * Copyright 2015-2016 (c) Chris Iatrou
45666 * Copyright 2015 (c) hfaham
45667 * Copyright 2015-2017 (c) Florian Palm
45668 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
45669 * Copyright 2015 (c) Holger Jeromin
45670 * Copyright 2015 (c) Oleksiy Vasylyev
45671 * Copyright 2016 (c) TorbenD
45672 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
45673 * Copyright 2016 (c) Lykurg
45674 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
45675 * Copyright 2018 (c) Kalycito Infotech Private Limited
45676 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart
45677 */
45678
45679
45680
45681/********************/
45682/* Client Lifecycle */
45683/********************/
45684
45685static void
45686UA_Client_init(UA_Client* client) {
45687 UA_SecureChannel_init(channel: &client->channel, config: &client->config.localConnectionConfig);
45688 client->connectStatus = UA_STATUSCODE_GOOD;
45689 UA_Timer_init(t: &client->timer);
45690 notifyClientState(client);
45691}
45692
45693UA_Client UA_EXPORT *
45694UA_Client_newWithConfig(const UA_ClientConfig *config) {
45695 if(!config)
45696 return NULL;
45697 UA_Client *client = (UA_Client*)UA_malloc(size: sizeof(UA_Client));
45698 if(!client)
45699 return NULL;
45700 memset(s: client, c: 0, n: sizeof(UA_Client));
45701 client->config = *config;
45702 UA_Client_init(client);
45703 return client;
45704}
45705
45706static void
45707UA_ClientConfig_clear(UA_ClientConfig *config) {
45708 UA_ApplicationDescription_clear(p: &config->clientDescription);
45709
45710 UA_ExtensionObject_clear(p: &config->userIdentityToken);
45711 UA_String_clear(p: &config->securityPolicyUri);
45712
45713 UA_EndpointDescription_clear(p: &config->endpoint);
45714 UA_UserTokenPolicy_clear(p: &config->userTokenPolicy);
45715
45716 UA_String_clear(p: &config->applicationUri);
45717
45718 if(config->certificateVerification.clear)
45719 config->certificateVerification.clear(&config->certificateVerification);
45720
45721 /* Delete the SecurityPolicies */
45722 if(config->securityPolicies == 0)
45723 return;
45724 for(size_t i = 0; i < config->securityPoliciesSize; i++)
45725 config->securityPolicies[i].clear(&config->securityPolicies[i]);
45726 UA_free(ptr: config->securityPolicies);
45727 config->securityPolicies = 0;
45728
45729 /* Logger */
45730 if(config->logger.clear)
45731 config->logger.clear(config->logger.context);
45732 config->logger.log = NULL;
45733 config->logger.clear = NULL;
45734
45735 if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
45736 UA_Array_delete(p: config->sessionLocaleIds, size: config->sessionLocaleIdsSize, type: &UA_TYPES[UA_TYPES_LOCALEID]);
45737 }
45738 config->sessionLocaleIds = NULL;
45739 config->sessionLocaleIdsSize = 0;
45740}
45741
45742static void
45743UA_Client_clear(UA_Client *client) {
45744 /* Prevent new async service calls in UA_Client_AsyncService_removeAll */
45745 UA_SessionState oldState = client->sessionState;
45746 client->sessionState = UA_SESSIONSTATE_CLOSING;
45747
45748 /* Delete the async service calls with BADHSUTDOWN */
45749 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN);
45750
45751 /* Reset to the old state to properly close the session */
45752 client->sessionState = oldState;
45753
45754 UA_Client_disconnect(client);
45755 UA_String_clear(p: &client->endpointUrl);
45756 UA_String_clear(p: &client->discoveryUrl);
45757
45758 UA_String_clear(p: &client->remoteNonce);
45759 UA_String_clear(p: &client->localNonce);
45760
45761 /* Delete the subscriptions */
45762#ifdef UA_ENABLE_SUBSCRIPTIONS
45763 UA_Client_Subscriptions_clean(client);
45764#endif
45765
45766 /* Delete the timed work */
45767 UA_Timer_clear(t: &client->timer);
45768}
45769
45770void
45771UA_Client_delete(UA_Client* client) {
45772 UA_Client_clear(client);
45773 UA_ClientConfig_clear(config: &client->config);
45774 UA_free(ptr: client);
45775}
45776
45777void
45778UA_Client_getState(UA_Client *client, UA_SecureChannelState *channelState,
45779 UA_SessionState *sessionState, UA_StatusCode *connectStatus) {
45780 if(channelState)
45781 *channelState = client->channel.state;
45782 if(sessionState)
45783 *sessionState = client->sessionState;
45784 if(connectStatus)
45785 *connectStatus = client->connectStatus;
45786}
45787
45788UA_ClientConfig *
45789UA_Client_getConfig(UA_Client *client) {
45790 if(!client)
45791 return NULL;
45792 return &client->config;
45793}
45794
45795#if UA_LOGLEVEL <= 300
45796static const char *channelStateTexts[9] = {
45797 "Fresh", "HELSent", "HELReceived", "ACKSent",
45798 "AckReceived", "OPNSent", "Open", "Closing", "Closed"};
45799static const char *sessionStateTexts[6] =
45800 {"Closed", "CreateRequested", "Created",
45801 "ActivateRequested", "Activated", "Closing"};
45802#endif
45803
45804void
45805notifyClientState(UA_Client *client) {
45806 if(client->connectStatus == client->oldConnectStatus &&
45807 client->channel.state == client->oldChannelState &&
45808 client->sessionState == client->oldSessionState)
45809 return;
45810
45811#if UA_LOGLEVEL <= 300
45812 UA_Boolean info = (client->connectStatus != UA_STATUSCODE_GOOD);
45813 if(client->oldChannelState != client->channel.state)
45814 info |= (client->channel.state == UA_SECURECHANNELSTATE_OPEN ||
45815 client->channel.state == UA_SECURECHANNELSTATE_CLOSED);
45816 if(client->oldSessionState != client->sessionState)
45817 info |= (client->sessionState == UA_SESSIONSTATE_CREATED ||
45818 client->sessionState == UA_SESSIONSTATE_ACTIVATED ||
45819 client->sessionState == UA_SESSIONSTATE_CLOSED);
45820
45821 const char *channelStateText = channelStateTexts[client->channel.state];
45822 const char *sessionStateText = sessionStateTexts[client->sessionState];
45823 const char *connectStatusText = UA_StatusCode_name(code: client->connectStatus);
45824
45825 if(info)
45826 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45827 msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s",
45828 channelStateText, sessionStateText, connectStatusText);
45829 else
45830 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45831 msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s",
45832 channelStateText, sessionStateText, connectStatusText);
45833#endif
45834
45835 client->oldConnectStatus = client->connectStatus;
45836 client->oldChannelState = client->channel.state;
45837 client->oldSessionState = client->sessionState;
45838
45839 if(client->config.stateCallback)
45840 client->config.stateCallback(client, client->channel.state,
45841 client->sessionState, client->connectStatus);
45842}
45843
45844/****************/
45845/* Raw Services */
45846/****************/
45847
45848/* For synchronous service calls. Execute async responses with a callback. When
45849 * the response with the correct requestId turns up, return it via the
45850 * SyncResponseDescription pointer. */
45851typedef struct {
45852 UA_Client *client;
45853 UA_Boolean received;
45854 UA_UInt32 requestId;
45855 void *response;
45856 const UA_DataType *responseType;
45857} SyncResponseDescription;
45858
45859/* For both synchronous and asynchronous service calls */
45860static UA_StatusCode
45861sendSymmetricServiceRequest(UA_Client *client, const void *request,
45862 const UA_DataType *requestType, UA_UInt32 *requestId) {
45863 /* Renew SecureChannel if necessary */
45864 UA_Client_renewSecureChannel(client);
45865 if(client->connectStatus != UA_STATUSCODE_GOOD)
45866 return client->connectStatus;
45867
45868 /* Adjusting the request header. The const attribute is violated, but we
45869 * only touch the following members: */
45870 UA_RequestHeader *rr = (UA_RequestHeader*)(uintptr_t)request;
45871 UA_NodeId oldToken = rr->authenticationToken; /* Put back in place later */
45872 rr->authenticationToken = client->authenticationToken;
45873 rr->timestamp = UA_DateTime_now();
45874 rr->requestHandle = ++client->requestHandle;
45875 UA_UInt32 rqId = ++client->requestId;
45876
45877#ifdef UA_ENABLE_TYPEDESCRIPTION
45878 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
45879 "Sending request with RequestId %u of type %s",
45880 (unsigned)rqId, requestType->typeName);
45881#else
45882 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
45883 "Sending request with RequestId %u of type %" PRIu32,
45884 (unsigned)rqId, requestType->binaryEncodingId.identifier.numeric);
45885#endif
45886
45887 /* Send the message */
45888 UA_StatusCode retval =
45889 UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: rqId,
45890 messageType: UA_MESSAGETYPE_MSG, payload: rr, payloadType: requestType);
45891 rr->authenticationToken = oldToken; /* Set the original token */
45892
45893 *requestId = rqId;
45894 return retval;
45895}
45896
45897static const UA_NodeId
45898serviceFaultId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_SERVICEFAULT_ENCODING_DEFAULTBINARY}};
45899
45900/* Look for the async callback in the linked list, execute and delete it */
45901static UA_StatusCode
45902processAsyncResponse(UA_Client *client, UA_UInt32 requestId, const UA_NodeId *responseTypeId,
45903 const UA_ByteString *responseMessage, size_t *offset) {
45904 /* Find the callback */
45905 AsyncServiceCall *ac;
45906 LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
45907 if(ac->requestId == requestId)
45908 break;
45909 }
45910
45911 /* Part 6, 6.7.6: After the security validation is complete the receiver
45912 * shall verify the RequestId and the SequenceNumber. If these checks fail a
45913 * Bad_SecurityChecksFailed error is reported. The RequestId only needs to
45914 * be verified by the Client since only the Client knows if it is valid or
45915 * not.*/
45916 if(!ac)
45917 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
45918
45919 /* Dequeue ac. We might disconnect (remove all ac) in the callback. */
45920 LIST_REMOVE(ac, pointers);
45921
45922 /* Verify the type of the response */
45923 UA_Response response;
45924 const UA_DataType *responseType = ac->responseType;
45925 UA_StatusCode retval = UA_STATUSCODE_GOOD;
45926 if(!UA_NodeId_equal(n1: responseTypeId, n2: &ac->responseType->binaryEncodingId)) {
45927 UA_init(p: &response, type: ac->responseType);
45928 if(UA_NodeId_equal(n1: responseTypeId, n2: &serviceFaultId)) {
45929 /* Decode as a ServiceFault, i.e. only the response header */
45930 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45931 msg: "Received a ServiceFault response");
45932 responseType = &UA_TYPES[UA_TYPES_SERVICEFAULT];
45933 } else {
45934 /* Close the connection */
45935 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45936 msg: "Reply contains the wrong service response");
45937 retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
45938 goto process;
45939 }
45940 }
45941
45942 /* Decode the response */
45943 retval = UA_decodeBinaryInternal(src: responseMessage, offset, dst: &response, type: responseType,
45944 customTypes: client->config.customDataTypes);
45945
45946 process:
45947 if(retval != UA_STATUSCODE_GOOD) {
45948 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45949 msg: "Could not decode the response with id %u due to %s",
45950 (unsigned)requestId, UA_StatusCode_name(code: retval));
45951 response.responseHeader.serviceResult = retval;
45952 } else if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
45953 /* Decode as a ServiceFault, i.e. only the response header */
45954 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
45955 msg: "The ServiceResult has the StatusCode %s",
45956 UA_StatusCode_name(code: response.responseHeader.serviceResult));
45957 }
45958
45959 /* Call the callback */
45960 if(ac->callback)
45961 ac->callback(client, ac->userdata, requestId, &response);
45962 UA_clear(p: &response, type: ac->responseType);
45963
45964 /* Remove the callback */
45965 UA_free(ptr: ac);
45966 return retval;
45967}
45968
45969/* Processes the received service response. Either with an async callback or by
45970 * decoding the message and returning it "upwards" in the
45971 * SyncResponseDescription. */
45972static UA_StatusCode
45973processServiceResponse(void *application, UA_SecureChannel *channel,
45974 UA_MessageType messageType, UA_UInt32 requestId,
45975 UA_ByteString *message) {
45976 SyncResponseDescription *rd = (SyncResponseDescription*)application;
45977
45978 /* Process ACK response */
45979 switch(messageType) {
45980 case UA_MESSAGETYPE_ACK:
45981 processACKResponse(client: rd->client, chunk: message);
45982 return UA_STATUSCODE_GOOD;
45983 case UA_MESSAGETYPE_OPN:
45984 processOPNResponse(client: rd->client, message);
45985 return UA_STATUSCODE_GOOD;
45986 case UA_MESSAGETYPE_ERR:
45987 processERRResponse(client: rd->client, chunk: message);
45988 return UA_STATUSCODE_GOOD;
45989 case UA_MESSAGETYPE_MSG:
45990 /* Continue below */
45991 break;
45992 default:
45993 UA_LOG_TRACE_CHANNEL(&rd->client->config.logger, channel, "Invalid message type");
45994 channel->state = UA_SECURECHANNELSTATE_CLOSING;
45995 return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID;
45996 }
45997
45998 /* Decode the data type identifier of the response */
45999 size_t offset = 0;
46000 UA_NodeId responseId;
46001 UA_StatusCode retval = UA_NodeId_decodeBinary(src: message, offset: &offset, dst: &responseId);
46002 if(retval != UA_STATUSCODE_GOOD)
46003 goto finish;
46004
46005 /* Got an asynchronous response. Don't expected a synchronous response
46006 * (responseType NULL) or the id does not match. */
46007 if(!rd->responseType || requestId != rd->requestId) {
46008 retval = processAsyncResponse(client: rd->client, requestId, responseTypeId: &responseId, responseMessage: message, offset: &offset);
46009 goto finish;
46010 }
46011
46012 /* Got the synchronous response */
46013 rd->received = true;
46014
46015 /* Check that the response type matches */
46016 if(!UA_NodeId_equal(n1: &responseId, n2: &rd->responseType->binaryEncodingId)) {
46017 if(UA_NodeId_equal(n1: &responseId, n2: &serviceFaultId)) {
46018 UA_init(p: rd->response, type: rd->responseType);
46019 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: rd->response,
46020 type: &UA_TYPES[UA_TYPES_SERVICEFAULT],
46021 customTypes: rd->client->config.customDataTypes);
46022 if(retval != UA_STATUSCODE_GOOD)
46023 ((UA_ResponseHeader*)rd->response)->serviceResult = retval;
46024 UA_LOG_INFO(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46025 msg: "Received a ServiceFault response with StatusCode %s",
46026 UA_StatusCode_name(code: ((UA_ResponseHeader*)rd->response)->serviceResult));
46027 } else {
46028 /* Close the connection */
46029 UA_LOG_ERROR(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46030 msg: "Reply contains the wrong service response");
46031 retval = UA_STATUSCODE_BADCOMMUNICATIONERROR;
46032 }
46033 goto finish;
46034 }
46035
46036#ifdef UA_ENABLE_TYPEDESCRIPTION
46037 UA_LOG_DEBUG(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46038 msg: "Decode a message of type %s", rd->responseType->typeName);
46039#else
46040 UA_LOG_DEBUG(&rd->client->config.logger, UA_LOGCATEGORY_CLIENT,
46041 "Decode a message of type %" PRIu32, responseId.identifier.numeric);
46042#endif
46043
46044 /* Decode the response */
46045 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: rd->response, type: rd->responseType,
46046 customTypes: rd->client->config.customDataTypes);
46047
46048finish:
46049 UA_NodeId_clear(p: &responseId);
46050 if(retval != UA_STATUSCODE_GOOD) {
46051 if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
46052 retval = UA_STATUSCODE_BADRESPONSETOOLARGE;
46053 UA_LOG_INFO(logger: &rd->client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46054 msg: "Error receiving the response with status code %s",
46055 UA_StatusCode_name(code: retval));
46056
46057 if(rd->response) {
46058 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)rd->response;
46059 respHeader->serviceResult = retval;
46060 }
46061 }
46062
46063 return retval;
46064}
46065
46066/* Receive and process messages until a synchronous message arrives or the
46067 * timout finishes */
46068static UA_StatusCode
46069receiveResponse(UA_Client *client, void *response, const UA_DataType *responseType,
46070 UA_DateTime maxDate, const UA_UInt32 *synchronousRequestId) {
46071 /* Prepare the response and the structure we give into processServiceResponse */
46072 SyncResponseDescription rd = { client, false, 0, response, responseType };
46073
46074 /* Return upon receiving the synchronized response. All other responses are
46075 * processed with a callback "in the background". */
46076 if(synchronousRequestId)
46077 rd.requestId = *synchronousRequestId;
46078
46079 UA_StatusCode retval = UA_STATUSCODE_GOOD;
46080 UA_DateTime now = UA_DateTime_nowMonotonic();
46081 do {
46082 UA_UInt32 timeout2 = (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC);
46083 if(maxDate < now)
46084 timeout2 = 0;
46085 retval = UA_SecureChannel_receive(channel: &client->channel, application: &rd, callback: processServiceResponse, timeout: timeout2);
46086 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
46087 break;
46088 if(retval != UA_STATUSCODE_GOOD ||
46089 client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
46090 UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel,
46091 "Receiving the response failed with StatusCode %s",
46092 UA_StatusCode_name(retval));
46093 closeSecureChannel(client);
46094 retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
46095 break;
46096 }
46097 now = UA_DateTime_nowMonotonic();
46098 if(maxDate < now)
46099 break;
46100 } while(!rd.received && responseType); /* Return if we don't wait for an async response */
46101
46102 return retval;
46103}
46104
46105UA_StatusCode
46106receiveResponseAsync(UA_Client *client, UA_UInt32 timeout) {
46107 UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
46108 UA_StatusCode res = receiveResponse(client, NULL, NULL, maxDate, NULL);
46109 return (res != UA_STATUSCODE_GOODNONCRITICALTIMEOUT) ? res : UA_STATUSCODE_GOOD;
46110}
46111
46112void
46113__UA_Client_Service(UA_Client *client, const void *request,
46114 const UA_DataType *requestType, void *response,
46115 const UA_DataType *responseType) {
46116 /* Initialize. Response is valied in case of aborting. */
46117 UA_init(p: response, type: responseType);
46118
46119 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
46120 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46121 msg: "SecureChannel must be connected before sending requests");
46122 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
46123 respHeader->serviceResult = UA_STATUSCODE_BADCONNECTIONCLOSED;
46124 return;
46125 }
46126
46127 /* Send the request */
46128 UA_UInt32 requestId;
46129 UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, requestId: &requestId);
46130
46131 UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
46132 if(retval == UA_STATUSCODE_GOOD) {
46133 /* Retrieve the response */
46134 UA_DateTime maxDate = UA_DateTime_nowMonotonic() + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
46135 retval = receiveResponse(client, response, responseType, maxDate, synchronousRequestId: &requestId);
46136 } else if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) {
46137 respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
46138 return;
46139 }
46140
46141 /* In synchronous service, if we have don't have a reply we need to close
46142 * the connection. For all other error cases, receiveResponse has already
46143 * closed the channel. */
46144 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT ||
46145 client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
46146 closeSecureChannel(client);
46147 retval = UA_STATUSCODE_BADCONNECTIONCLOSED;
46148 }
46149
46150 if(retval != UA_STATUSCODE_GOOD)
46151 respHeader->serviceResult = retval;
46152
46153 notifyClientState(client);
46154}
46155
46156void
46157UA_Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac,
46158 UA_StatusCode statusCode) {
46159 /* Create an empty response with the statuscode */
46160 UA_Response response;
46161 UA_init(p: &response, type: ac->responseType);
46162 response.responseHeader.serviceResult = statusCode;
46163
46164 if(ac->callback)
46165 ac->callback(client, ac->userdata, ac->requestId, &response);
46166
46167 /* Clean up the response. Users might move data into it. For whatever reasons. */
46168 UA_clear(p: &response, type: ac->responseType);
46169}
46170
46171void UA_Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) {
46172 AsyncServiceCall *ac, *ac_tmp;
46173 LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
46174 LIST_REMOVE(ac, pointers);
46175 UA_Client_AsyncService_cancel(client, ac, statusCode);
46176 UA_free(ptr: ac);
46177 }
46178}
46179
46180UA_StatusCode UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId,
46181 void *userdata, UA_ClientAsyncServiceCallback callback) {
46182 AsyncServiceCall *ac;
46183 LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) {
46184 if(ac->requestId == requestId) {
46185 ac->callback = callback;
46186 ac->userdata = userdata;
46187 return UA_STATUSCODE_GOOD;
46188 }
46189 }
46190
46191 return UA_STATUSCODE_BADNOTFOUND;
46192}
46193
46194UA_StatusCode
46195__UA_Client_AsyncServiceEx(UA_Client *client, const void *request,
46196 const UA_DataType *requestType,
46197 UA_ClientAsyncServiceCallback callback,
46198 const UA_DataType *responseType,
46199 void *userdata, UA_UInt32 *requestId,
46200 UA_UInt32 timeout) {
46201 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) {
46202 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46203 msg: "SecureChannel must be connected before sending requests");
46204 return UA_STATUSCODE_BADSERVERNOTCONNECTED;
46205 }
46206
46207 /* Prepare the entry for the linked list */
46208 AsyncServiceCall *ac = (AsyncServiceCall*)UA_malloc(size: sizeof(AsyncServiceCall));
46209 if(!ac)
46210 return UA_STATUSCODE_BADOUTOFMEMORY;
46211 ac->callback = callback;
46212 ac->responseType = responseType;
46213 ac->userdata = userdata;
46214 ac->timeout = timeout;
46215
46216 /* Call the service and set the requestId */
46217 UA_StatusCode retval = sendSymmetricServiceRequest(client, request, requestType, requestId: &ac->requestId);
46218 if(retval != UA_STATUSCODE_GOOD) {
46219 UA_free(ptr: ac);
46220 closeSecureChannel(client);
46221 notifyClientState(client);
46222 return retval;
46223 }
46224
46225 ac->start = UA_DateTime_nowMonotonic();
46226
46227 /* Store the entry for async processing */
46228 LIST_INSERT_HEAD(&client->asyncServiceCalls, ac, pointers);
46229 if(requestId)
46230 *requestId = ac->requestId;
46231
46232 notifyClientState(client);
46233 return UA_STATUSCODE_GOOD;
46234}
46235
46236UA_StatusCode
46237__UA_Client_AsyncService(UA_Client *client, const void *request,
46238 const UA_DataType *requestType,
46239 UA_ClientAsyncServiceCallback callback,
46240 const UA_DataType *responseType,
46241 void *userdata, UA_UInt32 *requestId) {
46242 return __UA_Client_AsyncServiceEx(client, request, requestType, callback, responseType,
46243 userdata, requestId, timeout: client->config.timeout);
46244}
46245
46246UA_StatusCode
46247UA_Client_sendAsyncRequest(UA_Client *client, const void *request,
46248 const UA_DataType *requestType,
46249 UA_ClientAsyncServiceCallback callback,
46250 const UA_DataType *responseType, void *userdata,
46251 UA_UInt32 *requestId) {
46252 return __UA_Client_AsyncService(client, request, requestType, callback,
46253 responseType, userdata, requestId);
46254}
46255
46256UA_StatusCode UA_EXPORT
46257UA_Client_addTimedCallback(UA_Client *client, UA_ClientCallback callback,
46258 void *data, UA_DateTime date, UA_UInt64 *callbackId) {
46259 return UA_Timer_addTimedCallback(t: &client->timer, callback: (UA_ApplicationCallback)callback,
46260 application: client, data, date, callbackId);
46261}
46262
46263UA_StatusCode
46264UA_Client_addRepeatedCallback(UA_Client *client, UA_ClientCallback callback,
46265 void *data, UA_Double interval_ms, UA_UInt64 *callbackId) {
46266 return UA_Timer_addRepeatedCallback(t: &client->timer, callback: (UA_ApplicationCallback)callback,
46267 application: client, data, interval_ms, NULL,
46268 timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId);
46269}
46270
46271UA_StatusCode
46272UA_Client_changeRepeatedCallbackInterval(UA_Client *client, UA_UInt64 callbackId,
46273 UA_Double interval_ms) {
46274 return UA_Timer_changeRepeatedCallback(t: &client->timer, callbackId, interval_ms, NULL, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME);
46275}
46276
46277void
46278UA_Client_removeCallback(UA_Client *client, UA_UInt64 callbackId) {
46279 UA_Timer_removeCallback(t: &client->timer, callbackId);
46280}
46281
46282static void
46283asyncServiceTimeoutCheck(UA_Client *client) {
46284 AsyncServiceCall *ac, *ac_tmp;
46285 UA_DateTime now = UA_DateTime_nowMonotonic();
46286 LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) {
46287 if(!ac->timeout)
46288 continue;
46289 if(ac->start + (UA_DateTime)(ac->timeout * UA_DATETIME_MSEC) <= now) {
46290 LIST_REMOVE(ac, pointers);
46291 UA_Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT);
46292 UA_free(ptr: ac);
46293 }
46294 }
46295}
46296
46297static void
46298backgroundConnectivityCallback(UA_Client *client, void *userdata,
46299 UA_UInt32 requestId, const UA_ReadResponse *response) {
46300 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
46301 if(client->config.inactivityCallback)
46302 client->config.inactivityCallback(client);
46303 }
46304 client->pendingConnectivityCheck = false;
46305 client->lastConnectivityCheck = UA_DateTime_nowMonotonic();
46306}
46307
46308static void
46309UA_Client_backgroundConnectivity(UA_Client *client) {
46310 if(!client->config.connectivityCheckInterval)
46311 return;
46312
46313 if(client->pendingConnectivityCheck)
46314 return;
46315
46316 UA_DateTime now = UA_DateTime_nowMonotonic();
46317 UA_DateTime nextDate = client->lastConnectivityCheck +
46318 (UA_DateTime)(client->config.connectivityCheckInterval * UA_DATETIME_MSEC);
46319 if(now <= nextDate)
46320 return;
46321
46322 /* Prepare the request */
46323 UA_ReadValueId rvid;
46324 UA_ReadValueId_init(p: &rvid);
46325 rvid.attributeId = UA_ATTRIBUTEID_VALUE;
46326 rvid.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE);
46327 UA_ReadRequest request;
46328 UA_ReadRequest_init(p: &request);
46329 request.nodesToRead = &rvid;
46330 request.nodesToReadSize = 1;
46331 UA_StatusCode retval =
46332 __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST],
46333 callback: (UA_ClientAsyncServiceCallback)backgroundConnectivityCallback,
46334 responseType: &UA_TYPES[UA_TYPES_READRESPONSE], NULL, NULL);
46335 if(retval == UA_STATUSCODE_GOOD)
46336 client->pendingConnectivityCheck = true;
46337}
46338
46339static void
46340clientExecuteRepeatedCallback(void *executionApplication, UA_ApplicationCallback cb,
46341 void *callbackApplication, void *data) {
46342 cb(callbackApplication, data);
46343}
46344
46345UA_StatusCode
46346UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) {
46347 /* Process timed (repeated) jobs */
46348 UA_DateTime now = UA_DateTime_nowMonotonic();
46349 UA_DateTime maxDate =
46350 UA_Timer_process(t: &client->timer, nowMonotonic: now, executionCallback: (UA_TimerExecutionCallback)
46351 clientExecuteRepeatedCallback, executionApplication: client);
46352 if(maxDate > now + ((UA_DateTime)timeout * UA_DATETIME_MSEC))
46353 maxDate = now + ((UA_DateTime)timeout * UA_DATETIME_MSEC);
46354
46355 /* Make sure we have an open channel */
46356 UA_StatusCode retval = UA_STATUSCODE_GOOD;
46357 if(client->endpointsHandshake || client->findServersHandshake ||
46358 client->discoveryUrl.length == 0 ||
46359 (client->noSession && client->channel.state != UA_SECURECHANNELSTATE_OPEN) ||
46360 client->sessionState < UA_SESSIONSTATE_ACTIVATED) {
46361 retval = connectIterate(client, timeout);
46362 notifyClientState(client);
46363 return retval;
46364 }
46365
46366 /* Renew Secure Channel */
46367 UA_Client_renewSecureChannel(client);
46368 if(client->connectStatus != UA_STATUSCODE_GOOD)
46369 return client->connectStatus;
46370
46371 /* Feed the server PublishRequests for the Subscriptions */
46372#ifdef UA_ENABLE_SUBSCRIPTIONS
46373 UA_Client_Subscriptions_backgroundPublish(client);
46374#endif
46375
46376 /* Send read requests from time to time to test the connectivity */
46377 UA_Client_backgroundConnectivity(client);
46378
46379 /* Listen on the network for the given timeout */
46380 retval = receiveResponse(client, NULL, NULL, maxDate, NULL);
46381 if(retval == UA_STATUSCODE_GOODNONCRITICALTIMEOUT)
46382 retval = UA_STATUSCODE_GOOD;
46383 if(retval != UA_STATUSCODE_GOOD) {
46384 UA_LOG_WARNING_CHANNEL(&client->config.logger, &client->channel,
46385 "Could not receive with StatusCode %s",
46386 UA_StatusCode_name(retval));
46387 }
46388
46389#ifdef UA_ENABLE_SUBSCRIPTIONS
46390 /* The inactivity check must be done after receiveServiceResponse*/
46391 UA_Client_Subscriptions_backgroundPublishInactivityCheck(client);
46392#endif
46393
46394 /* Did async services time out? Process callbacks with an error code */
46395 asyncServiceTimeoutCheck(client);
46396
46397 /* Log and notify user if the client state has changed */
46398 notifyClientState(client);
46399
46400 return client->connectStatus;
46401}
46402
46403const UA_DataType *
46404UA_Client_findDataType(UA_Client *client, const UA_NodeId *typeId) {
46405 return UA_findDataTypeWithCustom(typeId, customTypes: client->config.customDataTypes);
46406}
46407
46408/**** amalgamated original file "/src/client/ua_client_connect.c" ****/
46409
46410/* This Source Code Form is subject to the terms of the Mozilla Public
46411 * License, v. 2.0. If a copy of the MPL was not distributed with this
46412 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
46413 *
46414 * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
46415 * Copyright 2017-2019 (c) Fraunhofer IOSB (Author: Mark Giraud)
46416 */
46417
46418
46419
46420/* Some OPC UA servers only return all Endpoints if the EndpointURL used during
46421 * the HEL/ACK handshake exactly matches -- including the path following the
46422 * address and port! Hence for the first connection we only call FindServers and
46423 * reopen a new TCP connection using then EndpointURL found there.
46424 *
46425 * The overall process is this:
46426 * - Connect with the EndpointURL provided by the user (HEL/ACK)
46427 * - Call FindServers
46428 * - If one of the results has an exactly matching EndpointUrl, continue.
46429 * - Otherwise select a matching server, update the endpointURL member of
46430 * UA_Client and reconnect. -
46431 * - Call GetEndpoints and select an Endpoint
46432 * - Open a SecureChannel and Session for that Endpoint
46433 */
46434
46435#define UA_MINMESSAGESIZE 8192
46436#define UA_SESSION_LOCALNONCELENGTH 32
46437#define MAX_DATA_SIZE 4096
46438
46439static void closeSession(UA_Client *client);
46440static UA_StatusCode createSessionAsync(UA_Client *client);
46441
46442static UA_SecurityPolicy *
46443getSecurityPolicy(UA_Client *client, UA_String policyUri) {
46444 for(size_t i = 0; i < client->config.securityPoliciesSize; i++) {
46445 if(UA_String_equal(s1: &policyUri, s2: &client->config.securityPolicies[i].policyUri))
46446 return &client->config.securityPolicies[i];
46447 }
46448 return NULL;
46449}
46450
46451static UA_Boolean
46452endpointUnconfigured(UA_Client *client) {
46453 char test = 0;
46454 char *pos = (char *)&client->config.endpoint;
46455 for(size_t i = 0; i < sizeof(UA_EndpointDescription); i++)
46456 test = test | *(pos + i);
46457 pos = (char *)&client->config.userTokenPolicy;
46458 for(size_t i = 0; i < sizeof(UA_UserTokenPolicy); i++)
46459 test = test | *(pos + i);
46460 return (test == 0);
46461}
46462
46463#ifdef UA_ENABLE_ENCRYPTION
46464
46465/* Function to create a signature using remote certificate and nonce */
46466static UA_StatusCode
46467signActivateSessionRequest(UA_Client *client, UA_SecureChannel *channel,
46468 UA_ActivateSessionRequest *request) {
46469 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
46470 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
46471 return UA_STATUSCODE_GOOD;
46472
46473 const UA_SecurityPolicy *sp = channel->securityPolicy;
46474 UA_SignatureData *sd = &request->clientSignature;
46475
46476 /* Prepare the signature */
46477 size_t signatureSize = sp->certificateSigningAlgorithm.
46478 getLocalSignatureSize(channel->channelContext);
46479 UA_StatusCode retval = UA_String_copy(src: &sp->certificateSigningAlgorithm.uri,
46480 dst: &sd->algorithm);
46481 if(retval != UA_STATUSCODE_GOOD)
46482 return retval;
46483
46484 retval = UA_ByteString_allocBuffer(bs: &sd->signature, length: signatureSize);
46485 if(retval != UA_STATUSCODE_GOOD)
46486 return retval;
46487
46488 /* Allocate a temporary buffer */
46489 size_t dataToSignSize = channel->remoteCertificate.length + client->remoteNonce.length;
46490 if(dataToSignSize > MAX_DATA_SIZE)
46491 return UA_STATUSCODE_BADINTERNALERROR;
46492
46493 UA_ByteString dataToSign;
46494 retval = UA_ByteString_allocBuffer(bs: &dataToSign, length: dataToSignSize);
46495 if(retval != UA_STATUSCODE_GOOD)
46496 return retval; /* sd->signature is cleaned up with the response */
46497
46498 /* Sign the signature */
46499 memcpy(dest: dataToSign.data, src: channel->remoteCertificate.data,
46500 n: channel->remoteCertificate.length);
46501 memcpy(dest: dataToSign.data + channel->remoteCertificate.length,
46502 src: client->remoteNonce.data, n: client->remoteNonce.length);
46503 retval = sp->certificateSigningAlgorithm.sign(channel->channelContext,
46504 &dataToSign, &sd->signature);
46505
46506 /* Clean up */
46507 UA_ByteString_clear(p: &dataToSign);
46508 return retval;
46509}
46510
46511static UA_StatusCode
46512encryptUserIdentityToken(UA_Client *client, const UA_String *userTokenSecurityPolicy,
46513 UA_ExtensionObject *userIdentityToken) {
46514 UA_IssuedIdentityToken *iit = NULL;
46515 UA_UserNameIdentityToken *unit = NULL;
46516 UA_ByteString *tokenData;
46517 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) {
46518 iit = (UA_IssuedIdentityToken*)userIdentityToken->content.decoded.data;
46519 tokenData = &iit->tokenData;
46520 } else if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
46521 unit = (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
46522 tokenData = &unit->password;
46523 } else {
46524 return UA_STATUSCODE_GOOD;
46525 }
46526
46527 /* No encryption */
46528 const UA_String none = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
46529 if(userTokenSecurityPolicy->length == 0 ||
46530 UA_String_equal(s1: userTokenSecurityPolicy, s2: &none)) {
46531 return UA_STATUSCODE_GOOD;
46532 }
46533
46534 UA_SecurityPolicy *sp = getSecurityPolicy(client, policyUri: *userTokenSecurityPolicy);
46535 if(!sp) {
46536 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46537 msg: "Could not find the required SecurityPolicy for the UserToken");
46538 return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
46539 }
46540
46541 /* Create a temp channel context */
46542
46543 void *channelContext;
46544 UA_StatusCode retval = sp->channelModule.
46545 newContext(sp, &client->config.endpoint.serverCertificate, &channelContext);
46546 if(retval != UA_STATUSCODE_GOOD) {
46547 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46548 msg: "Could not instantiate the SecurityPolicy for the UserToken");
46549 return UA_STATUSCODE_BADINTERNALERROR;
46550 }
46551
46552 /* Compute the encrypted length (at least one byte padding) */
46553 size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule.
46554 encryptionAlgorithm.getRemotePlainTextBlockSize(channelContext);
46555 size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule.
46556 encryptionAlgorithm.getRemoteBlockSize(channelContext);
46557 UA_UInt32 length = (UA_UInt32)(tokenData->length + client->remoteNonce.length);
46558 UA_UInt32 totalLength = length + 4; /* Including the length field */
46559 size_t blocks = totalLength / plainTextBlockSize;
46560 if(totalLength % plainTextBlockSize != 0)
46561 blocks++;
46562 size_t encryptedLength = blocks * encryptedBlockSize;
46563
46564 /* Allocate memory for encryption overhead */
46565 UA_ByteString encrypted;
46566 retval = UA_ByteString_allocBuffer(bs: &encrypted, length: encryptedLength);
46567 if(retval != UA_STATUSCODE_GOOD) {
46568 sp->channelModule.deleteContext(channelContext);
46569 return UA_STATUSCODE_BADOUTOFMEMORY;
46570 }
46571
46572 UA_Byte *pos = encrypted.data;
46573 const UA_Byte *end = &encrypted.data[encrypted.length];
46574 retval = UA_UInt32_encodeBinary(src: &length, bufPos: &pos, bufEnd: end);
46575 memcpy(dest: pos, src: tokenData->data, n: tokenData->length);
46576 memcpy(dest: &pos[tokenData->length], src: client->remoteNonce.data, n: client->remoteNonce.length);
46577 UA_assert(retval == UA_STATUSCODE_GOOD);
46578
46579 /* Add padding
46580 *
46581 * 7.36.2.2 Legacy Encrypted Token Secret Format: A Client should not add any
46582 * padding after the secret. If a Client adds padding then all bytes shall
46583 * be zero. A Server shall check for padding added by Clients and ensure
46584 * that all padding bytes are zeros. */
46585 size_t paddedLength = plainTextBlockSize * blocks;
46586 for(size_t i = totalLength; i < paddedLength; i++)
46587 encrypted.data[i] = 0;
46588 encrypted.length = paddedLength;
46589
46590 retval = sp->asymmetricModule.cryptoModule.encryptionAlgorithm.
46591 encrypt(channelContext, &encrypted);
46592 encrypted.length = encryptedLength;
46593
46594 if(iit) {
46595 retval |= UA_String_copy(src: &sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri,
46596 dst: &iit->encryptionAlgorithm);
46597 } else {
46598 retval |= UA_String_copy(src: &sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri,
46599 dst: &unit->encryptionAlgorithm);
46600 }
46601
46602 UA_ByteString_clear(p: tokenData);
46603 *tokenData = encrypted;
46604
46605 /* Delete the temp channel context */
46606 sp->channelModule.deleteContext(channelContext);
46607
46608 return retval;
46609}
46610
46611/* Function to verify the signature corresponds to ClientNonce
46612 * using the local certificate */
46613static UA_StatusCode
46614checkCreateSessionSignature(UA_Client *client, const UA_SecureChannel *channel,
46615 const UA_CreateSessionResponse *response) {
46616 if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
46617 channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
46618 return UA_STATUSCODE_GOOD;
46619
46620 if(!channel->securityPolicy)
46621 return UA_STATUSCODE_BADINTERNALERROR;
46622
46623 const UA_SecurityPolicy *sp = channel->securityPolicy;
46624 const UA_ByteString *lc = &sp->localCertificate;
46625
46626 size_t dataToVerifySize = lc->length + client->localNonce.length;
46627 UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
46628 UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize);
46629 if(retval != UA_STATUSCODE_GOOD)
46630 return retval;
46631
46632 memcpy(dest: dataToVerify.data, src: lc->data, n: lc->length);
46633 memcpy(dest: dataToVerify.data + lc->length,
46634 src: client->localNonce.data, n: client->localNonce.length);
46635
46636 retval = sp->certificateSigningAlgorithm.verify(channel->channelContext, &dataToVerify,
46637 &response->serverSignature.signature);
46638 UA_ByteString_clear(p: &dataToVerify);
46639 return retval;
46640}
46641
46642#endif
46643
46644/***********************/
46645/* Open the Connection */
46646/***********************/
46647
46648void
46649processERRResponse(UA_Client *client, const UA_ByteString *chunk) {
46650 client->channel.state = UA_SECURECHANNELSTATE_CLOSING;
46651
46652 size_t offset = 0;
46653 UA_TcpErrorMessage errMessage;
46654 UA_StatusCode res =
46655 UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &errMessage,
46656 type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], NULL);
46657 if(res != UA_STATUSCODE_GOOD) {
46658 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46659 "Received an ERR response that could not be decoded with StatusCode %s",
46660 UA_StatusCode_name(res));
46661 client->connectStatus = res;
46662 return;
46663 }
46664
46665 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46666 "Received an ERR response with StatusCode %s and the following reason: %.*s",
46667 UA_StatusCode_name(errMessage.error), (int)errMessage.reason.length, errMessage.reason.data);
46668 client->connectStatus = errMessage.error;
46669 UA_TcpErrorMessage_clear(p: &errMessage);
46670}
46671
46672void
46673processACKResponse(UA_Client *client, const UA_ByteString *chunk) {
46674 UA_SecureChannel *channel = &client->channel;
46675 if(channel->state != UA_SECURECHANNELSTATE_HEL_SENT) {
46676 UA_LOG_ERROR_CHANNEL(&client->config.logger, channel,
46677 "Expected an ACK response");
46678 channel->state = UA_SECURECHANNELSTATE_CLOSING;
46679 return;
46680 }
46681
46682 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Received ACK message");
46683
46684 /* Decode the message */
46685 size_t offset = 0;
46686 UA_TcpAcknowledgeMessage ackMessage;
46687 client->connectStatus =
46688 UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &ackMessage,
46689 type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL);
46690 if(client->connectStatus != UA_STATUSCODE_GOOD) {
46691 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46692 msg: "Decoding ACK message failed");
46693 closeSecureChannel(client);
46694 return;
46695 }
46696
46697 client->connectStatus =
46698 UA_SecureChannel_processHELACK(channel, remoteConfig: &ackMessage);
46699 if(client->connectStatus != UA_STATUSCODE_GOOD) {
46700 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK,
46701 msg: "Processing the ACK message failed with StatusCode %s",
46702 UA_StatusCode_name(code: client->connectStatus));
46703 closeSecureChannel(client);
46704 return;
46705 }
46706
46707 client->channel.state = UA_SECURECHANNELSTATE_ACK_RECEIVED;
46708}
46709
46710static UA_StatusCode
46711sendHELMessage(UA_Client *client) {
46712 /* Get a buffer */
46713 UA_ByteString message;
46714 UA_Connection *conn = &client->connection;
46715 UA_StatusCode retval = conn->getSendBuffer(conn, UA_MINMESSAGESIZE, &message);
46716 if(retval != UA_STATUSCODE_GOOD)
46717 return retval;
46718
46719 /* Prepare the HEL message and encode at offset 8 */
46720 UA_TcpHelloMessage hello;
46721 hello.protocolVersion = 0;
46722 hello.receiveBufferSize = client->config.localConnectionConfig.recvBufferSize;
46723 hello.sendBufferSize = client->config.localConnectionConfig.sendBufferSize;
46724 hello.maxMessageSize = client->config.localConnectionConfig.localMaxMessageSize;
46725 hello.maxChunkCount = client->config.localConnectionConfig.localMaxChunkCount;
46726
46727 /* Use the DiscoveryUrl -- if already known via FindServers */
46728 if(client->discoveryUrl.length > 0) {
46729 hello.endpointUrl = client->discoveryUrl;
46730 } else {
46731 hello.endpointUrl = client->endpointUrl;
46732 }
46733
46734 UA_Byte *bufPos = &message.data[8]; /* skip the header */
46735 const UA_Byte *bufEnd = &message.data[message.length];
46736 client->connectStatus =
46737 UA_encodeBinaryInternal(src: &hello, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE],
46738 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
46739
46740 /* Encode the message header at offset 0 */
46741 UA_TcpMessageHeader messageHeader;
46742 messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
46743 messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data);
46744 bufPos = message.data;
46745 retval = UA_encodeBinaryInternal(src: &messageHeader,
46746 type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER],
46747 bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL);
46748 if(retval != UA_STATUSCODE_GOOD) {
46749 conn->releaseSendBuffer(conn, &message);
46750 return retval;
46751 }
46752
46753 /* Send the HEL message */
46754 message.length = messageHeader.messageSize;
46755 retval = conn->send(conn, &message);
46756 if(retval == UA_STATUSCODE_GOOD) {
46757 client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT;
46758 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Sent HEL message");
46759 } else {
46760 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_NETWORK, msg: "Sending HEL failed");
46761 }
46762 return retval;
46763}
46764
46765void
46766processOPNResponse(UA_Client *client, const UA_ByteString *message) {
46767 /* Is the content of the expected type? */
46768 size_t offset = 0;
46769 UA_NodeId responseId;
46770 UA_NodeId expectedId =
46771 UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_OPENSECURECHANNELRESPONSE_ENCODING_DEFAULTBINARY);
46772 UA_StatusCode retval = UA_NodeId_decodeBinary(src: message, offset: &offset, dst: &responseId);
46773 if(retval != UA_STATUSCODE_GOOD) {
46774 closeSecureChannel(client);
46775 return;
46776 }
46777
46778 if(!UA_NodeId_equal(n1: &responseId, n2: &expectedId)) {
46779 UA_NodeId_clear(p: &responseId);
46780 closeSecureChannel(client);
46781 return;
46782 }
46783
46784 /* Decode the response */
46785 UA_OpenSecureChannelResponse response;
46786 retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: &response,
46787 type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL);
46788 if(retval != UA_STATUSCODE_GOOD) {
46789 closeSecureChannel(client);
46790 return;
46791 }
46792
46793 /* Check whether the nonce was reused */
46794 if(client->channel.securityMode != UA_MESSAGESECURITYMODE_NONE &&
46795 UA_ByteString_equal(string1: &client->channel.remoteNonce,
46796 string2: &response.serverNonce)) {
46797 UA_LOG_ERROR_CHANNEL(&client->config.logger, &client->channel,
46798 "The server reused the last nonce");
46799 client->connectStatus = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
46800 closeSecureChannel(client);
46801 return;
46802 }
46803
46804 /* Response.securityToken.revisedLifetime is UInt32 we need to cast it to
46805 * DateTime=Int64 we take 75% of lifetime to start renewing as described in
46806 * standard */
46807 client->nextChannelRenewal = UA_DateTime_nowMonotonic()
46808 + (UA_DateTime) (response.securityToken.revisedLifetime
46809 * (UA_Double) UA_DATETIME_MSEC * 0.75);
46810
46811 /* Move the nonce out of the response */
46812 UA_ByteString_clear(p: &client->channel.remoteNonce);
46813 client->channel.remoteNonce = response.serverNonce;
46814 UA_ByteString_init(p: &response.serverNonce);
46815 UA_ResponseHeader_clear(p: &response.responseHeader);
46816
46817 /* Replace the token. Keep the current token as the old token. Messages
46818 * might still arrive for the old token. */
46819 client->channel.altSecurityToken = client->channel.securityToken;
46820 client->channel.securityToken = response.securityToken;
46821 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT;
46822
46823 /* Compute the new local keys. The remote keys are updated when a message
46824 * with the new SecurityToken is received. */
46825 retval = UA_SecureChannel_generateLocalKeys(channel: &client->channel);
46826 if(retval != UA_STATUSCODE_GOOD) {
46827 closeSecureChannel(client);
46828 return;
46829 }
46830
46831 UA_Float lifetime = (UA_Float)response.securityToken.revisedLifetime / 1000;
46832 UA_Boolean renew = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
46833 if(renew) {
46834 UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel, "SecureChannel "
46835 "renewed with a revised lifetime of %.2fs", lifetime);
46836 } else {
46837 UA_LOG_INFO_CHANNEL(&client->config.logger, &client->channel,
46838 "SecureChannel opened with SecurityPolicy %.*s "
46839 "and a revised lifetime of %.2fs",
46840 (int)client->channel.securityPolicy->policyUri.length,
46841 client->channel.securityPolicy->policyUri.data, lifetime);
46842 }
46843
46844 client->channel.state = UA_SECURECHANNELSTATE_OPEN;
46845}
46846
46847/* OPN messges to renew the channel are sent asynchronous */
46848static UA_StatusCode
46849sendOPNAsync(UA_Client *client, UA_Boolean renew) {
46850 UA_Connection *conn = &client->connection;
46851 if(conn->state != UA_CONNECTIONSTATE_ESTABLISHED) {
46852 closeSecureChannel(client);
46853 return UA_STATUSCODE_BADNOTCONNECTED;
46854 }
46855
46856 UA_StatusCode retval = UA_SecureChannel_generateLocalNonce(channel: &client->channel);
46857 if(retval != UA_STATUSCODE_GOOD)
46858 return retval;
46859
46860 /* Prepare the OpenSecureChannelRequest */
46861 UA_OpenSecureChannelRequest opnSecRq;
46862 UA_OpenSecureChannelRequest_init(p: &opnSecRq);
46863 opnSecRq.requestHeader.timestamp = UA_DateTime_now();
46864 opnSecRq.requestHeader.authenticationToken = client->authenticationToken;
46865 opnSecRq.securityMode = client->channel.securityMode;
46866 opnSecRq.clientNonce = client->channel.localNonce;
46867 opnSecRq.requestedLifetime = client->config.secureChannelLifeTime;
46868 if(renew) {
46869 opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW;
46870 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
46871 "Requesting to renew the SecureChannel");
46872 } else {
46873 opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE;
46874 UA_LOG_DEBUG_CHANNEL(&client->config.logger, &client->channel,
46875 "Requesting to open a SecureChannel");
46876 }
46877
46878 /* Prepare the entry for the linked list */
46879 UA_UInt32 requestId = ++client->requestId;
46880
46881 /* Send the OPN message */
46882 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL,
46883 msg: "Requesting to open a SecureChannel");
46884 retval =
46885 UA_SecureChannel_sendAsymmetricOPNMessage(channel: &client->channel, requestId, content: &opnSecRq,
46886 contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]);
46887 if(retval != UA_STATUSCODE_GOOD) {
46888 client->connectStatus = retval;
46889 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL,
46890 msg: "Sending OPN message failed with error %s",
46891 UA_StatusCode_name(code: retval));
46892 closeSecureChannel(client);
46893 return retval;
46894 }
46895
46896 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_SENT;
46897 if(client->channel.state < UA_SECURECHANNELSTATE_OPN_SENT)
46898 client->channel.state = UA_SECURECHANNELSTATE_OPN_SENT;
46899 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_SECURECHANNEL, msg: "OPN message sent");
46900 return UA_STATUSCODE_GOOD;
46901}
46902
46903UA_StatusCode
46904UA_Client_renewSecureChannel(UA_Client *client) {
46905 /* Check if OPN has been sent or the SecureChannel is still valid */
46906 if(client->channel.state != UA_SECURECHANNELSTATE_OPEN ||
46907 client->channel.renewState == UA_SECURECHANNELRENEWSTATE_SENT ||
46908 client->nextChannelRenewal > UA_DateTime_nowMonotonic())
46909 return UA_STATUSCODE_GOODCALLAGAIN;
46910 sendOPNAsync(client, true);
46911 return client->connectStatus;
46912}
46913
46914static void
46915responseActivateSession(UA_Client *client, void *userdata, UA_UInt32 requestId,
46916 void *response) {
46917 UA_ActivateSessionResponse *activateResponse =
46918 (UA_ActivateSessionResponse *)response;
46919 if(activateResponse->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
46920 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46921 msg: "ActivateSession failed with error code %s",
46922 UA_StatusCode_name(code: activateResponse->responseHeader.serviceResult));
46923 if(activateResponse->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID ||
46924 activateResponse->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) {
46925 /* The session is lost. Create a new one. */
46926 closeSession(client);
46927 createSessionAsync(client);
46928 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
46929 msg: "Session cannot be activated. Create a new Session.");
46930 } else {
46931 /* Something else is wrong. Give up. */
46932 client->connectStatus = activateResponse->responseHeader.serviceResult;
46933 }
46934 return;
46935 }
46936
46937 /* Replace the nonce */
46938 UA_ByteString_clear(p: &client->remoteNonce);
46939 client->remoteNonce = activateResponse->serverNonce;
46940 UA_ByteString_init(p: &activateResponse->serverNonce);
46941
46942 client->sessionState = UA_SESSIONSTATE_ACTIVATED;
46943 notifyClientState(client);
46944}
46945
46946static UA_StatusCode
46947activateSessionAsync(UA_Client *client) {
46948 UA_ActivateSessionRequest request;
46949 UA_ActivateSessionRequest_init(p: &request);
46950 request.requestHeader.requestHandle = ++client->requestHandle;
46951 request.requestHeader.timestamp = UA_DateTime_now ();
46952 request.requestHeader.timeoutHint = 600000;
46953 UA_StatusCode retval =
46954 UA_ExtensionObject_copy(src: &client->config.userIdentityToken, dst: &request.userIdentityToken);
46955 if(retval != UA_STATUSCODE_GOOD)
46956 return retval;
46957
46958 if (client->config.sessionLocaleIdsSize && client->config.sessionLocaleIds) {
46959 retval = UA_Array_copy(src: client->config.sessionLocaleIds, size: client->config.sessionLocaleIdsSize,
46960 dst: (void **)&request.localeIds, type: &UA_TYPES[UA_TYPES_LOCALEID]);
46961 if (retval != UA_STATUSCODE_GOOD)
46962 return retval;
46963
46964 request.localeIdsSize = client->config.sessionLocaleIdsSize;
46965 }
46966
46967 /* If not token is set, use anonymous */
46968 if(request.userIdentityToken.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
46969 UA_AnonymousIdentityToken *t = UA_AnonymousIdentityToken_new();
46970 if(!t) {
46971 UA_ActivateSessionRequest_clear(p: &request);
46972 return UA_STATUSCODE_BADOUTOFMEMORY;
46973 }
46974 request.userIdentityToken.content.decoded.data = t;
46975 request.userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN];
46976 request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED;
46977 }
46978
46979 /* Set the policy-Id from the endpoint. Every IdentityToken starts with a
46980 * string. */
46981 retval = UA_String_copy(src: &client->config.userTokenPolicy.policyId,
46982 dst: (UA_String*)request.userIdentityToken.content.decoded.data);
46983
46984#ifdef UA_ENABLE_ENCRYPTION
46985 /* Encrypt the UserIdentityToken */
46986 const UA_String *userTokenPolicy = &client->channel.securityPolicy->policyUri;
46987 if(client->config.userTokenPolicy.securityPolicyUri.length > 0)
46988 userTokenPolicy = &client->config.userTokenPolicy.securityPolicyUri;
46989 retval |= encryptUserIdentityToken(client, userTokenSecurityPolicy: userTokenPolicy, userIdentityToken: &request.userIdentityToken);
46990 retval |= signActivateSessionRequest(client, channel: &client->channel, request: &request);
46991#endif
46992
46993 if(retval == UA_STATUSCODE_GOOD)
46994 retval = UA_Client_sendAsyncRequest(client, request: &request,
46995 requestType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST],
46996 callback: (UA_ClientAsyncServiceCallback) responseActivateSession,
46997 responseType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], NULL, NULL);
46998
46999 UA_ActivateSessionRequest_clear(p: &request);
47000 if(retval == UA_STATUSCODE_GOOD)
47001 client->sessionState = UA_SESSIONSTATE_ACTIVATE_REQUESTED;
47002 else
47003 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47004 msg: "ActivateSession failed when sending the request with error code %s",
47005 UA_StatusCode_name(code: retval));
47006
47007 return retval;
47008}
47009
47010/* Combination of UA_Client_getEndpointsInternal and getEndpoints */
47011static void
47012responseGetEndpoints(UA_Client *client, void *userdata, UA_UInt32 requestId,
47013 void *response) {
47014 client->endpointsHandshake = false;
47015
47016 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47017 msg: "Received GetEndpointsResponse");
47018
47019 UA_GetEndpointsResponse *resp = (UA_GetEndpointsResponse*)response;
47020 /* GetEndpoints not possible. Fail the connection */
47021 if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
47022 client->connectStatus = resp->responseHeader.serviceResult;
47023 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47024 msg: "GetEndpointRequest failed with error code %s",
47025 UA_StatusCode_name(code: client->connectStatus));
47026 UA_GetEndpointsResponse_clear(p: resp);
47027 return;
47028 }
47029
47030 /* Warn if the Endpoints look incomplete / don't match the EndpointUrl */
47031 Client_warnEndpointsResult(client, response: resp, endpointUrl: &client->discoveryUrl);
47032
47033 UA_Boolean endpointFound = false;
47034 UA_Boolean tokenFound = false;
47035 const UA_String binaryTransport = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/"
47036 "Transport/uatcp-uasc-uabinary");
47037
47038 /* Find a matching combination of Endpoint and UserTokenPolicy */
47039 for(size_t i = 0; i < resp->endpointsSize; ++i) {
47040 UA_EndpointDescription* endpoint = &resp->endpoints[i];
47041
47042 /* Filter by the ApplicationURI if defined */
47043 if(client->config.applicationUri.length > 0 &&
47044 !UA_String_equal(s1: &client->config.applicationUri,
47045 s2: &endpoint->server.applicationUri))
47046 continue;
47047
47048 /* Look out for binary transport endpoints.
47049 * Note: Siemens returns empty ProfileUrl, we will accept it as binary. */
47050 if(endpoint->transportProfileUri.length != 0 &&
47051 !UA_String_equal (s1: &endpoint->transportProfileUri, s2: &binaryTransport))
47052 continue;
47053
47054 /* Valid SecurityMode? */
47055 if(endpoint->securityMode < 1 || endpoint->securityMode > 3) {
47056 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47057 msg: "Rejecting endpoint %lu: invalid security mode",
47058 (long unsigned)i);
47059 continue;
47060 }
47061
47062 /* Selected SecurityMode? */
47063 if(client->config.securityMode > 0 &&
47064 client->config.securityMode != endpoint->securityMode) {
47065 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47066 msg: "Rejecting endpoint %lu: security mode doesn't match",
47067 (long unsigned)i);
47068 continue;
47069 }
47070
47071 /* Matching SecurityPolicy? */
47072 if(client->config.securityPolicyUri.length > 0 &&
47073 !UA_String_equal(s1: &client->config.securityPolicyUri,
47074 s2: &endpoint->securityPolicyUri)) {
47075 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47076 msg: "Rejecting endpoint %lu: security policy doesn't match",
47077 (long unsigned)i);
47078 continue;
47079 }
47080
47081 /* SecurityPolicy available? */
47082 if(!getSecurityPolicy(client, policyUri: endpoint->securityPolicyUri)) {
47083 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47084 msg: "Rejecting endpoint %lu: security policy not available",
47085 (long unsigned)i);
47086 continue;
47087 }
47088
47089 endpointFound = true;
47090
47091 /* Look for a user token policy with an anonymous token */
47092 for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) {
47093 UA_UserTokenPolicy* tokenPolicy = &endpoint->userIdentityTokens[j];
47094 const UA_DataType *tokenType = client->config.userIdentityToken.content.decoded.type;
47095
47096 /* Usertokens also have a security policy... */
47097 if(tokenPolicy->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
47098 tokenPolicy->securityPolicyUri.length > 0 &&
47099 !getSecurityPolicy(client, policyUri: tokenPolicy->securityPolicyUri)) {
47100 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47101 msg: "Rejecting UserTokenPolicy %lu in endpoint %lu: "
47102 "security policy '%.*s' not available", (long unsigned)j, (long unsigned)i,
47103 (int)tokenPolicy->securityPolicyUri.length,
47104 tokenPolicy->securityPolicyUri.data);
47105 continue;
47106 }
47107
47108 if(tokenPolicy->tokenType > 3) {
47109 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47110 msg: "Rejecting UserTokenPolicy %lu in endpoint %lu: invalid token type",
47111 (long unsigned)j, (long unsigned)i);
47112 continue;
47113 }
47114
47115 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ANONYMOUS &&
47116 tokenType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN] &&
47117 tokenType != NULL) {
47118 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47119 msg: "Rejecting UserTokenPolicy %lu (anonymous) in endpoint %lu: "
47120 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
47121 continue;
47122 }
47123 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_USERNAME &&
47124 tokenType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
47125 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47126 msg: "Rejecting UserTokenPolicy %lu (username) in endpoint %lu: "
47127 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
47128 continue;
47129 }
47130 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_CERTIFICATE &&
47131 tokenType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
47132 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47133 msg: "Rejecting UserTokenPolicy %lu (certificate) in endpoint %lu: "
47134 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
47135 continue;
47136 }
47137 if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN &&
47138 tokenType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) {
47139 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47140 msg: "Rejecting UserTokenPolicy %lu (token) in endpoint %lu: "
47141 "configuration doesn't match", (long unsigned)j, (long unsigned)i);
47142 continue;
47143 }
47144
47145 /* Endpoint with matching usertokenpolicy found */
47146
47147#if UA_LOGLEVEL <= 300
47148 const char *securityModeNames[3] = {"None", "Sign", "SignAndEncrypt"};
47149 const char *userTokenTypeNames[4] = {"Anonymous", "UserName",
47150 "Certificate", "IssuedToken"};
47151 UA_String *securityPolicyUri = &tokenPolicy->securityPolicyUri;
47152 if(securityPolicyUri->length == 0)
47153 securityPolicyUri = &endpoint->securityPolicyUri;
47154
47155 /* Log the selected endpoint */
47156 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47157 msg: "Selected endpoint %lu in URL %.*s with SecurityMode %s and SecurityPolicy %.*s",
47158 (long unsigned)i, (int)endpoint->endpointUrl.length,
47159 endpoint->endpointUrl.data,
47160 securityModeNames[endpoint->securityMode - 1],
47161 (int)endpoint->securityPolicyUri.length,
47162 endpoint->securityPolicyUri.data);
47163
47164 /* Log the selected UserTokenPolicy */
47165 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47166 msg: "Selected UserTokenPolicy %.*s with UserTokenType %s and SecurityPolicy %.*s",
47167 (int)tokenPolicy->policyId.length, tokenPolicy->policyId.data,
47168 userTokenTypeNames[tokenPolicy->tokenType],
47169 (int)securityPolicyUri->length, securityPolicyUri->data);
47170#endif
47171
47172 /* Move to the client config */
47173 tokenFound = true;
47174 UA_EndpointDescription_clear(p: &client->config.endpoint);
47175 client->config.endpoint = *endpoint;
47176 UA_EndpointDescription_init(p: endpoint);
47177 UA_UserTokenPolicy_clear(p: &client->config.userTokenPolicy);
47178 client->config.userTokenPolicy = *tokenPolicy;
47179 UA_UserTokenPolicy_init(p: tokenPolicy);
47180
47181 break;
47182 }
47183
47184 if(tokenFound)
47185 break;
47186 }
47187
47188 if(!endpointFound) {
47189 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47190 msg: "No suitable endpoint found");
47191 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47192 } else if(!tokenFound) {
47193 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47194 msg: "No suitable UserTokenPolicy found for the possible endpoints");
47195 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47196 }
47197
47198 /* Close the SecureChannel if a different SecurityPolicy is defined by the Endpoint */
47199 if(client->config.endpoint.securityMode != client->channel.securityMode ||
47200 !UA_String_equal(s1: &client->config.endpoint.securityPolicyUri,
47201 s2: &client->channel.securityPolicy->policyUri))
47202 closeSecureChannel(client);
47203}
47204
47205static UA_StatusCode
47206requestGetEndpoints(UA_Client *client) {
47207 UA_GetEndpointsRequest request;
47208 UA_GetEndpointsRequest_init(p: &request);
47209 request.requestHeader.timestamp = UA_DateTime_now();
47210 request.requestHeader.timeoutHint = 10000;
47211 if(client->discoveryUrl.length > 0)
47212 request.endpointUrl = client->discoveryUrl;
47213 else
47214 request.endpointUrl = client->endpointUrl;
47215 UA_StatusCode retval =
47216 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
47217 callback: (UA_ClientAsyncServiceCallback) responseGetEndpoints,
47218 responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL, NULL);
47219 if(retval == UA_STATUSCODE_GOOD)
47220 client->endpointsHandshake = true;
47221 else
47222 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47223 msg: "RequestGetEndpoints failed when sending the request with error code %s",
47224 UA_StatusCode_name(code: retval));
47225 return retval;
47226}
47227
47228static void
47229responseFindServers(UA_Client *client, void *userdata,
47230 UA_UInt32 requestId, void *response) {
47231 client->findServersHandshake = false;
47232
47233 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47234 msg: "Received FindServersResponse");
47235
47236 /* Error handling. Log the error but continue to connect with the current
47237 * EndpointURL. */
47238 UA_FindServersResponse *fsr = (UA_FindServersResponse*)response;
47239 if(fsr->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
47240 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47241 msg: "FindServers failed with error code %s. Continue with the "
47242 "EndpointURL %.*s.",
47243 UA_StatusCode_name(code: fsr->responseHeader.serviceResult),
47244 (int)client->endpointUrl.length, client->endpointUrl.data);
47245 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47246 return;
47247 }
47248
47249 /* Check if one of the returned servers matches the EndpointURL already used */
47250 for(size_t i = 0; i < fsr->serversSize; i++) {
47251 UA_ApplicationDescription *server = &fsr->servers[i];
47252
47253 /* Filter by the ApplicationURI if defined */
47254 if(client->config.applicationUri.length > 0 &&
47255 !UA_String_equal(s1: &client->config.applicationUri,
47256 s2: &server->applicationUri))
47257 continue;
47258
47259 for(size_t j = 0; j < server->discoveryUrlsSize; j++) {
47260 if(UA_String_equal(s1: &client->endpointUrl, s2: &server->discoveryUrls[j])) {
47261 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47262 msg: "The initially defined EndpointURL %.*s"
47263 "is valid for the server",
47264 (int)client->endpointUrl.length,
47265 client->endpointUrl.data);
47266 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47267 return;
47268 }
47269 }
47270 }
47271
47272 /* The current EndpointURL is not usable. Pick the first "opc.tcp" DiscoveryUrl of a
47273 * returned server. */
47274 for(size_t i = 0; i < fsr->serversSize; i++) {
47275 UA_ApplicationDescription *server = &fsr->servers[i];
47276 if(server->applicationType != UA_APPLICATIONTYPE_SERVER)
47277 continue;
47278
47279 /* Filter by the ApplicationURI if defined */
47280 if(client->config.applicationUri.length > 0 &&
47281 !UA_String_equal(s1: &client->config.applicationUri,
47282 s2: &server->applicationUri))
47283 continue;
47284
47285 for(size_t j = 0; j < server->discoveryUrlsSize; j++) {
47286 /* Try to parse the DiscoveryUrl. This weeds out http schemas (etc.)
47287 * and invalid DiscoveryUrls in general. */
47288 UA_String hostname, path;
47289 UA_UInt16 port;
47290 UA_StatusCode res =
47291 UA_parseEndpointUrl(endpointUrl: &server->discoveryUrls[j], outHostname: &hostname,
47292 outPort: &port, outPath: &path);
47293 if(res != UA_STATUSCODE_GOOD)
47294 continue;
47295
47296 /* Use this DiscoveryUrl in the client */
47297 UA_String_clear(p: &client->discoveryUrl);
47298 client->discoveryUrl = server->discoveryUrls[j];
47299 UA_String_init(p: &server->discoveryUrls[j]);
47300
47301 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47302 msg: "Use the EndpointURL %.*s returned from FindServers",
47303 (int)client->discoveryUrl.length, client->discoveryUrl.data);
47304
47305 /* Close the SecureChannel to build it up new with the correct
47306 * EndpointURL in the HEL/ACK handshake */
47307 closeSecureChannel(client);
47308 return;
47309 }
47310 }
47311
47312 /* Could not find a suitable server. Try to continue with the
47313 * original EndpointURL. */
47314 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47315 msg: "FindServers did not returned a suitable DiscoveryURL. "
47316 "Continue with the EndpointURL %.*s.",
47317 (int)client->endpointUrl.length, client->endpointUrl.data);
47318 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47319}
47320
47321static UA_StatusCode
47322requestFindServers(UA_Client *client) {
47323 UA_FindServersRequest request;
47324 UA_FindServersRequest_init(p: &request);
47325 request.requestHeader.timestamp = UA_DateTime_now();
47326 request.requestHeader.timeoutHint = 10000;
47327 request.endpointUrl = client->endpointUrl;
47328 UA_StatusCode retval =
47329 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
47330 callback: (UA_ClientAsyncServiceCallback) responseFindServers,
47331 responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], NULL, NULL);
47332 if(retval != UA_STATUSCODE_GOOD) {
47333 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47334 msg: "FindServers failed when sending the request with error code %s",
47335 UA_StatusCode_name(code: retval));
47336 return retval;
47337 }
47338
47339 client->findServersHandshake = true;
47340 return UA_STATUSCODE_GOOD;
47341}
47342
47343static void
47344responseSessionCallback(UA_Client *client, void *userdata,
47345 UA_UInt32 requestId, void *response) {
47346 UA_CreateSessionResponse *sessionResponse = (UA_CreateSessionResponse*)response;
47347 UA_StatusCode res = sessionResponse->responseHeader.serviceResult;
47348 if(res != UA_STATUSCODE_GOOD)
47349 goto cleanup;
47350
47351#ifdef UA_ENABLE_ENCRYPTION
47352 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47353 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47354 /* Verify the session response was created with the same certificate as
47355 * the SecureChannel */
47356 if(!UA_ByteString_equal(string1: &sessionResponse->serverCertificate,
47357 string2: &client->channel.remoteCertificate)) {
47358 res = UA_STATUSCODE_BADCERTIFICATEINVALID;
47359 goto cleanup;
47360 }
47361
47362 /* Verify the client signature */
47363 res = checkCreateSessionSignature(client, channel: &client->channel, response: sessionResponse);
47364 if(res != UA_STATUSCODE_GOOD)
47365 goto cleanup;
47366 }
47367#endif
47368
47369 /* Copy nonce and AuthenticationToken */
47370 UA_ByteString_clear(p: &client->remoteNonce);
47371 UA_NodeId_clear(p: &client->authenticationToken);
47372 res |= UA_ByteString_copy(src: &sessionResponse->serverNonce, dst: &client->remoteNonce);
47373 res |= UA_NodeId_copy(src: &sessionResponse->authenticationToken, dst: &client->authenticationToken);
47374 if(res != UA_STATUSCODE_GOOD)
47375 goto cleanup;
47376
47377 /* Activate the new Session */
47378 client->sessionState = UA_SESSIONSTATE_CREATED;
47379
47380 cleanup:
47381 client->connectStatus = res;
47382 if(client->connectStatus != UA_STATUSCODE_GOOD)
47383 client->sessionState = UA_SESSIONSTATE_CLOSED;
47384}
47385
47386static UA_StatusCode
47387createSessionAsync(UA_Client *client) {
47388 UA_StatusCode retval = UA_STATUSCODE_GOOD;
47389 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47390 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47391 if(client->localNonce.length != UA_SESSION_LOCALNONCELENGTH) {
47392 UA_ByteString_clear(p: &client->localNonce);
47393 retval = UA_ByteString_allocBuffer(bs: &client->localNonce,
47394 UA_SESSION_LOCALNONCELENGTH);
47395 if(retval != UA_STATUSCODE_GOOD)
47396 return retval;
47397 }
47398 retval = client->channel.securityPolicy->symmetricModule.
47399 generateNonce(client->channel.securityPolicy->policyContext,
47400 &client->localNonce);
47401 if(retval != UA_STATUSCODE_GOOD)
47402 return retval;
47403 }
47404
47405 UA_CreateSessionRequest request;
47406 UA_CreateSessionRequest_init(p: &request);
47407 request.requestHeader.requestHandle = ++client->requestHandle;
47408 request.requestHeader.timestamp = UA_DateTime_now();
47409 request.requestHeader.timeoutHint = 10000;
47410 UA_ByteString_copy(src: &client->localNonce, dst: &request.clientNonce);
47411 request.requestedSessionTimeout = client->config.requestedSessionTimeout;
47412 request.maxResponseMessageSize = UA_INT32_MAX;
47413 UA_String_copy(src: &client->config.endpoint.endpointUrl, dst: &request.endpointUrl);
47414 UA_ApplicationDescription_copy(src: &client->config.clientDescription,
47415 dst: &request.clientDescription);
47416
47417 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN ||
47418 client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
47419 UA_ByteString_copy(src: &client->channel.securityPolicy->localCertificate,
47420 dst: &request.clientCertificate);
47421 }
47422
47423 retval = UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST],
47424 callback: (UA_ClientAsyncServiceCallback)responseSessionCallback,
47425 responseType: &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL, NULL);
47426 UA_CreateSessionRequest_clear(p: &request);
47427
47428 if(retval == UA_STATUSCODE_GOOD)
47429 client->sessionState = UA_SESSIONSTATE_CREATE_REQUESTED;
47430 else
47431 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47432 msg: "CreateSession failed when sending the request with error code %s",
47433 UA_StatusCode_name(code: retval));
47434
47435 return retval;
47436}
47437
47438static UA_StatusCode
47439initConnect(UA_Client *client);
47440
47441/* A workaround if the DiscoveryUrl returned by the FindServers service doesn't work.
47442 * Then default back to the initial EndpointUrl and pretend that was returned
47443 * by FindServers. */
47444static void
47445fixBadDiscoveryUrl(UA_Client* client) {
47446 if(client->connectStatus == UA_STATUSCODE_GOOD)
47447 return;
47448 if(client->discoveryUrl.length == 0 ||
47449 UA_String_equal(s1: &client->discoveryUrl, s2: &client->endpointUrl))
47450 return;
47451
47452 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47453 msg: "The DiscoveryUrl returned by the FindServers service (%.*s) could not be "
47454 "connected. Trying with the original EndpointUrl.",
47455 (int)client->discoveryUrl.length, client->discoveryUrl.data);
47456
47457 UA_String_clear(p: &client->discoveryUrl);
47458 UA_String_copy(src: &client->endpointUrl, dst: &client->discoveryUrl);
47459 client->connectStatus = UA_STATUSCODE_GOOD;
47460}
47461
47462UA_StatusCode
47463connectIterate(UA_Client *client, UA_UInt32 timeout) {
47464 UA_LOG_TRACE(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47465 msg: "Client connect iterate");
47466
47467 /* Already connected */
47468 if(client->sessionState == UA_SESSIONSTATE_ACTIVATED)
47469 return UA_STATUSCODE_GOOD;
47470
47471 /* Could not connect */
47472 if(client->connectStatus != UA_STATUSCODE_GOOD)
47473 return client->connectStatus;
47474
47475 /* The connection was already closed */
47476 if(client->channel.state == UA_SECURECHANNELSTATE_CLOSING) {
47477 client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED;
47478 return UA_STATUSCODE_BADCONNECTIONCLOSED;
47479 }
47480
47481 /* The connection is closed. Reset the SecureChannel and open a new TCP
47482 * connection */
47483 if(client->connection.state == UA_CONNECTIONSTATE_CLOSED)
47484 return initConnect(client);
47485
47486 /* Poll the connection status */
47487 if(client->connection.state == UA_CONNECTIONSTATE_OPENING) {
47488 client->connectStatus =
47489 client->config.pollConnectionFunc(&client->connection, timeout,
47490 &client->config.logger);
47491 return client->connectStatus;
47492 }
47493
47494 /* Attach the connection to the SecureChannel */
47495 if(!client->channel.connection)
47496 UA_Connection_attachSecureChannel(connection: &client->connection, channel: &client->channel);
47497
47498 /* Set the SecurityPolicy */
47499 if(!client->channel.securityPolicy) {
47500 client->channel.securityMode = client->config.endpoint.securityMode;
47501 if(client->channel.securityMode == UA_MESSAGESECURITYMODE_INVALID)
47502 client->channel.securityMode = UA_MESSAGESECURITYMODE_NONE;
47503
47504 UA_SecurityPolicy *sp = NULL;
47505 if(client->config.endpoint.securityPolicyUri.length == 0) {
47506 sp = getSecurityPolicy(client,
47507 policyUri: UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"));
47508 } else {
47509 sp = getSecurityPolicy(client, policyUri: client->config.endpoint.securityPolicyUri);
47510 }
47511 if(!sp) {
47512 client->connectStatus = UA_STATUSCODE_BADINTERNALERROR;
47513 return client->connectStatus;
47514 }
47515
47516 client->connectStatus =
47517 UA_SecureChannel_setSecurityPolicy(channel: &client->channel, securityPolicy: sp,
47518 remoteCertificate: &client->config.endpoint.serverCertificate);
47519 if(client->connectStatus != UA_STATUSCODE_GOOD)
47520 return client->connectStatus;
47521 }
47522
47523 /* Open the SecureChannel */
47524 switch(client->channel.state) {
47525 case UA_SECURECHANNELSTATE_FRESH:
47526 client->connectStatus = sendHELMessage(client);
47527 if(client->connectStatus == UA_STATUSCODE_GOOD) {
47528 client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT;
47529 } else {
47530 client->connection.close(&client->connection);
47531 client->connection.free(&client->connection);
47532 }
47533 fixBadDiscoveryUrl(client);
47534 return client->connectStatus;
47535 case UA_SECURECHANNELSTATE_ACK_RECEIVED:
47536 client->connectStatus = sendOPNAsync(client, false);
47537 fixBadDiscoveryUrl(client);
47538 return client->connectStatus;
47539 case UA_SECURECHANNELSTATE_HEL_SENT:
47540 case UA_SECURECHANNELSTATE_OPN_SENT:
47541 client->connectStatus = receiveResponseAsync(client, timeout);
47542 fixBadDiscoveryUrl(client);
47543 return client->connectStatus;
47544 default:
47545 break;
47546 }
47547
47548 /* Call FindServers to see whether we need to reconnect with the correct
47549 * EndpointUrl */
47550 if(!client->findServersHandshake && client->discoveryUrl.length == 0) {
47551 client->connectStatus = requestFindServers(client);
47552 return client->connectStatus;
47553 }
47554
47555 /* FindServers was sent out, but we are still waiting for the response */
47556 if(client->discoveryUrl.length == 0) {
47557 receiveResponseAsync(client, timeout);
47558 return client->connectStatus;
47559 }
47560
47561 /* Have a SecureChannel but no session */
47562 if(client->noSession)
47563 return client->connectStatus;
47564
47565 /* Create and Activate the Session */
47566 switch(client->sessionState) {
47567 case UA_SESSIONSTATE_CLOSED:
47568 if(!endpointUnconfigured(client)) {
47569 client->connectStatus = createSessionAsync(client);
47570 return client->connectStatus;
47571 }
47572 if(!client->endpointsHandshake) {
47573 client->connectStatus = requestGetEndpoints(client);
47574 return client->connectStatus;
47575 }
47576 receiveResponseAsync(client, timeout);
47577 return client->connectStatus;
47578 case UA_SESSIONSTATE_CREATE_REQUESTED:
47579 case UA_SESSIONSTATE_ACTIVATE_REQUESTED:
47580 receiveResponseAsync(client, timeout);
47581 return client->connectStatus;
47582 case UA_SESSIONSTATE_CREATED:
47583 client->connectStatus = activateSessionAsync(client);
47584 return client->connectStatus;
47585 default:
47586 break;
47587 }
47588
47589 return client->connectStatus;
47590}
47591
47592/* The local ApplicationURI has to match the certificates of the
47593 * SecurityPolicies */
47594static void
47595verifyClientApplicationURI(const UA_Client *client) {
47596#if defined(UA_ENABLE_ENCRYPTION) && (UA_LOGLEVEL <= 400)
47597 for(size_t i = 0; i < client->config.securityPoliciesSize; i++) {
47598 UA_SecurityPolicy *sp = &client->config.securityPolicies[i];
47599 UA_StatusCode retval =
47600 client->config.certificateVerification.
47601 verifyApplicationURI(client->config.certificateVerification.context,
47602 &sp->localCertificate,
47603 &client->config.clientDescription.applicationUri);
47604 if(retval != UA_STATUSCODE_GOOD) {
47605 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47606 msg: "The configured ApplicationURI does not match the URI "
47607 "specified in the certificate for the SecurityPolicy %.*s",
47608 (int)sp->policyUri.length, sp->policyUri.data);
47609 }
47610 }
47611#endif
47612}
47613
47614static UA_StatusCode
47615client_configure_securechannel(void *application, UA_SecureChannel *channel,
47616 const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) {
47617 // TODO: Verify if certificate is the same as configured in the client endpoint config
47618 return UA_STATUSCODE_GOOD;
47619}
47620
47621static UA_StatusCode
47622initConnect(UA_Client *client) {
47623 if(client->connection.state > UA_CONNECTIONSTATE_CLOSED) {
47624 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47625 msg: "Client already connected");
47626 return UA_STATUSCODE_GOOD;
47627 }
47628
47629 if(client->config.initConnectionFunc == NULL) {
47630 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47631 msg: "Client connection not configured");
47632 return UA_STATUSCODE_BADINTERNALERROR;
47633 }
47634
47635 /* Consistency check the client's own ApplicationURI */
47636 verifyClientApplicationURI(client);
47637
47638 /* Reset the connect status */
47639 client->connectStatus = UA_STATUSCODE_GOOD;
47640 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
47641 client->endpointsHandshake = false;
47642
47643 /* Initialize the SecureChannel */
47644 UA_SecureChannel_init(channel: &client->channel, config: &client->config.localConnectionConfig);
47645 client->channel.certificateVerification = &client->config.certificateVerification;
47646 client->channel.processOPNHeader = client_configure_securechannel;
47647
47648 if(client->connection.free)
47649 client->connection.free(&client->connection);
47650
47651 /* Initialize the TCP connection */
47652 client->connection =
47653 client->config.initConnectionFunc(client->config.localConnectionConfig,
47654 client->endpointUrl, client->config.timeout,
47655 &client->config.logger);
47656 if(client->connection.state != UA_CONNECTIONSTATE_OPENING) {
47657 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47658 msg: "Could not open a TCP connection to %.*s",
47659 (int)client->endpointUrl.length, client->endpointUrl.data);
47660 client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED;
47661 closeSecureChannel(client);
47662 }
47663
47664 return client->connectStatus;
47665}
47666
47667UA_StatusCode
47668UA_Client_connectAsync(UA_Client *client, const char *endpointUrl) {
47669 /* Set the endpoint URL the client connects to */
47670 UA_String_clear(p: &client->endpointUrl);
47671 UA_String_clear(p: &client->discoveryUrl);
47672 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47673
47674 /* Open a Session when possible */
47675 client->noSession = false;
47676
47677 /* Connect Async */
47678 return initConnect(client);
47679}
47680
47681UA_StatusCode
47682UA_Client_connectSecureChannelAsync(UA_Client *client, const char *endpointUrl) {
47683 /* Set the endpoint URL the client connects to */
47684 UA_String_clear(p: &client->endpointUrl);
47685 UA_String_clear(p: &client->discoveryUrl);
47686 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47687
47688 /* Don't open a Session */
47689 client->noSession = true;
47690
47691 /* Connect Async */
47692 return initConnect(client);
47693}
47694
47695UA_StatusCode
47696connectSync(UA_Client *client) {
47697 UA_DateTime now = UA_DateTime_nowMonotonic();
47698 UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC);
47699
47700 UA_StatusCode retval = initConnect(client);
47701 if(retval != UA_STATUSCODE_GOOD)
47702 return retval;
47703
47704 while(retval == UA_STATUSCODE_GOOD) {
47705 if(!client->endpointsHandshake && !client->findServersHandshake &&
47706 client->discoveryUrl.length > 0 &&
47707 (client->sessionState == UA_SESSIONSTATE_ACTIVATED ||
47708 (client->noSession && client->channel.state == UA_SECURECHANNELSTATE_OPEN)))
47709 break;
47710 now = UA_DateTime_nowMonotonic();
47711 if(maxDate < now)
47712 return UA_STATUSCODE_BADTIMEOUT;
47713 retval = UA_Client_run_iterate(client,
47714 timeout: (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC));
47715 }
47716
47717 return retval;
47718}
47719
47720UA_StatusCode
47721UA_Client_connect(UA_Client *client, const char *endpointUrl) {
47722 /* Set the endpoint URL the client connects to */
47723 UA_String_clear(p: &client->endpointUrl);
47724 UA_String_clear(p: &client->discoveryUrl);
47725 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47726
47727 /* Open a Session when possible */
47728 client->noSession = false;
47729
47730 /* Connect Synchronous */
47731 return connectSync(client);
47732}
47733
47734UA_StatusCode
47735UA_Client_connectSecureChannel(UA_Client *client, const char *endpointUrl) {
47736 /* Set the endpoint URL the client connects to */
47737 UA_String_clear(p: &client->endpointUrl);
47738 UA_String_clear(p: &client->discoveryUrl);
47739 client->endpointUrl = UA_STRING_ALLOC(endpointUrl);
47740
47741 /* Don't open a Session */
47742 client->noSession = true;
47743
47744 /* Connect Synchronous */
47745 return connectSync(client);
47746}
47747
47748/************************/
47749/* Close the Connection */
47750/************************/
47751
47752void
47753closeSecureChannel(UA_Client *client) {
47754 /* Send CLO if the SecureChannel is open */
47755 if(client->channel.state == UA_SECURECHANNELSTATE_OPEN) {
47756 UA_CloseSecureChannelRequest request;
47757 UA_CloseSecureChannelRequest_init(p: &request);
47758 request.requestHeader.requestHandle = ++client->requestHandle;
47759 request.requestHeader.timestamp = UA_DateTime_now();
47760 request.requestHeader.timeoutHint = 10000;
47761 request.requestHeader.authenticationToken = client->authenticationToken;
47762 UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: ++client->requestId,
47763 messageType: UA_MESSAGETYPE_CLO, payload: &request,
47764 payloadType: &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]);
47765 }
47766
47767 /* Clean up */
47768 client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL;
47769 UA_SecureChannel_close(channel: &client->channel);
47770 if(client->connection.free)
47771 client->connection.free(&client->connection);
47772
47773 /* Set the Session to "Created" if it was "Activated" */
47774 if(client->sessionState > UA_SESSIONSTATE_CREATED)
47775 client->sessionState = UA_SESSIONSTATE_CREATED;
47776
47777 /* Delete outstanding async services - the RequestId is no longr valid. Do
47778 * this after setting the Session state. Otherwise we send out new Publish
47779 * Requests immediately. */
47780 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSECURECHANNELCLOSED);
47781}
47782
47783static void
47784sendCloseSession(UA_Client *client) {
47785 /* Set before sending the message to prevent recursion */
47786 client->sessionState = UA_SESSIONSTATE_CLOSING;
47787
47788 UA_CloseSessionRequest request;
47789 UA_CloseSessionRequest_init(p: &request);
47790 request.requestHeader.timestamp = UA_DateTime_now();
47791 request.requestHeader.timeoutHint = 10000;
47792 request.deleteSubscriptions = true;
47793 UA_CloseSessionResponse response;
47794 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
47795 response: &response, responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]);
47796 UA_CloseSessionRequest_clear(p: &request);
47797 UA_CloseSessionResponse_clear(p: &response);
47798}
47799
47800static void
47801closeSession(UA_Client *client) {
47802 /* Is a session established? */
47803 if(client->sessionState == UA_SESSIONSTATE_ACTIVATED)
47804 sendCloseSession(client);
47805
47806 UA_NodeId_clear(p: &client->authenticationToken);
47807 client->requestHandle = 0;
47808 client->sessionState = UA_SESSIONSTATE_CLOSED;
47809
47810#ifdef UA_ENABLE_SUBSCRIPTIONS
47811 /* We need to clean up the subscriptions */
47812 UA_Client_Subscriptions_clean(client);
47813#endif
47814
47815 /* Reset so the next async connect creates a session by default */
47816 client->noSession = false;
47817
47818 /* Delete outstanding async services */
47819 UA_Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSESSIONCLOSED);
47820
47821#ifdef UA_ENABLE_SUBSCRIPTIONS
47822 client->currentlyOutStandingPublishRequests = 0;
47823#endif
47824}
47825
47826static void
47827closeSessionCallback(UA_Client *client, void *userdata,
47828 UA_UInt32 requestId, void *response) {
47829 closeSession(client);
47830 closeSecureChannel(client);
47831 notifyClientState(client);
47832}
47833
47834UA_StatusCode UA_EXPORT
47835UA_Client_disconnectAsync(UA_Client *client) {
47836 /* Set before sending the message to prevent recursion */
47837 client->sessionState = UA_SESSIONSTATE_CLOSING;
47838
47839 UA_CloseSessionRequest request;
47840 UA_CloseSessionRequest_init(p: &request);
47841 request.requestHeader.timestamp = UA_DateTime_now();
47842 request.requestHeader.timeoutHint = 10000;
47843 request.deleteSubscriptions = true;
47844 UA_StatusCode res =
47845 UA_Client_sendAsyncRequest(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST],
47846 callback: (UA_ClientAsyncServiceCallback)closeSessionCallback,
47847 responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], NULL, NULL);
47848 notifyClientState(client);
47849 return res;
47850}
47851
47852UA_StatusCode
47853UA_Client_disconnectSecureChannel(UA_Client *client) {
47854 closeSecureChannel(client);
47855 notifyClientState(client);
47856 return UA_STATUSCODE_GOOD;
47857}
47858
47859UA_StatusCode
47860UA_Client_disconnect(UA_Client *client) {
47861 closeSession(client);
47862 closeSecureChannel(client);
47863 notifyClientState(client);
47864 return UA_STATUSCODE_GOOD;
47865}
47866
47867
47868/**** amalgamated original file "/src/client/ua_client_discovery.c" ****/
47869
47870/* This Source Code Form is subject to the terms of the Mozilla Public
47871 * License, v. 2.0. If a copy of the MPL was not distributed with this
47872 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
47873 *
47874 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
47875 * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
47876 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
47877 */
47878
47879
47880/* Helper method for additional warnings */
47881void
47882Client_warnEndpointsResult(UA_Client *client,
47883 const UA_GetEndpointsResponse *response,
47884 const UA_String *endpointUrl) {
47885 if(response->endpointsSize == 0) {
47886 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47887 msg: "The server did not return any endpoints. "
47888 "Did you use the correct endpointUrl?");
47889 return;
47890 }
47891
47892 if(!UA_String_equal(s1: endpointUrl, s2: &response->endpoints[0].endpointUrl) ||
47893 (response->endpoints[0].server.discoveryUrlsSize > 0 &&
47894 !UA_String_equal(s1: endpointUrl, s2: &response->endpoints[0].server.discoveryUrls[0]))) {
47895 UA_String *betterUrl = &response->endpoints[0].endpointUrl;
47896 if(response->endpoints[0].server.discoveryUrlsSize > 0)
47897 betterUrl = &response->endpoints[0].server.discoveryUrls[0];
47898 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47899 msg: "The server returned Endpoints with a different EndpointUrl %.*s than was "
47900 "used to initialize the connection: %.*s. Some servers require a complete "
47901 "match of the EndpointUrl/DiscoveryUrl (including the path) "
47902 "to return all endpoints.",
47903 (int)betterUrl->length, betterUrl->data,
47904 (int)endpointUrl->length, endpointUrl->data);
47905 }
47906}
47907
47908/* Gets a list of endpoints. Memory is allocated for endpointDescription array */
47909static UA_StatusCode
47910UA_Client_getEndpointsInternal(UA_Client *client, const UA_String endpointUrl,
47911 size_t *endpointDescriptionsSize,
47912 UA_EndpointDescription **endpointDescriptions) {
47913 UA_GetEndpointsRequest request;
47914 UA_GetEndpointsRequest_init(p: &request);
47915 request.requestHeader.timestamp = UA_DateTime_now();
47916 request.requestHeader.timeoutHint = 10000;
47917 // assume the endpointurl outlives the service call
47918 request.endpointUrl = endpointUrl;
47919
47920 UA_GetEndpointsResponse response;
47921 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST],
47922 response: &response, responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]);
47923
47924 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
47925 UA_StatusCode retval = response.responseHeader.serviceResult;
47926 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
47927 msg: "GetEndpointRequest failed with error code %s",
47928 UA_StatusCode_name(code: retval));
47929 UA_GetEndpointsResponse_clear(p: &response);
47930 return retval;
47931 }
47932
47933 *endpointDescriptions = response.endpoints;
47934 *endpointDescriptionsSize = response.endpointsSize;
47935 response.endpoints = NULL;
47936 response.endpointsSize = 0;
47937 UA_GetEndpointsResponse_clear(p: &response);
47938 return UA_STATUSCODE_GOOD;
47939}
47940
47941UA_StatusCode
47942UA_Client_getEndpoints(UA_Client *client, const char *serverUrl,
47943 size_t* endpointDescriptionsSize,
47944 UA_EndpointDescription** endpointDescriptions) {
47945 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
47946 /* Client is already connected to a different server */
47947 if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl,
47948 n: client->config.endpoint.endpointUrl.length) != 0) {
47949 return UA_STATUSCODE_BADINVALIDARGUMENT;
47950 }
47951
47952 UA_StatusCode retval;
47953 const UA_String url = UA_STRING(chars: (char*)(uintptr_t)serverUrl);
47954 if(!connected) {
47955 retval = UA_Client_connectSecureChannel(client, endpointUrl: serverUrl);
47956 if(retval != UA_STATUSCODE_GOOD)
47957 return retval;
47958 }
47959 retval = UA_Client_getEndpointsInternal(client, endpointUrl: url, endpointDescriptionsSize,
47960 endpointDescriptions);
47961
47962 if(!connected)
47963 UA_Client_disconnect(client);
47964 return retval;
47965}
47966
47967UA_StatusCode
47968UA_Client_findServers(UA_Client *client, const char *serverUrl,
47969 size_t serverUrisSize, UA_String *serverUris,
47970 size_t localeIdsSize, UA_String *localeIds,
47971 size_t *registeredServersSize,
47972 UA_ApplicationDescription **registeredServers) {
47973 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
47974 /* Client is already connected to a different server */
47975 if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl,
47976 n: client->config.endpoint.endpointUrl.length) != 0) {
47977 return UA_STATUSCODE_BADINVALIDARGUMENT;
47978 }
47979
47980 UA_StatusCode retval;
47981 if(!connected) {
47982 retval = UA_Client_connectSecureChannel(client, endpointUrl: serverUrl);
47983 if(retval != UA_STATUSCODE_GOOD)
47984 return retval;
47985 }
47986
47987 /* Prepare the request */
47988 UA_FindServersRequest request;
47989 UA_FindServersRequest_init(p: &request);
47990 request.serverUrisSize = serverUrisSize;
47991 request.serverUris = serverUris;
47992 request.localeIdsSize = localeIdsSize;
47993 request.localeIds = localeIds;
47994
47995 /* Send the request */
47996 UA_FindServersResponse response;
47997 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST],
47998 response: &response, responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]);
47999
48000 /* Process the response */
48001 retval = response.responseHeader.serviceResult;
48002 if(retval == UA_STATUSCODE_GOOD) {
48003 *registeredServersSize = response.serversSize;
48004 *registeredServers = response.servers;
48005 response.serversSize = 0;
48006 response.servers = NULL;
48007 } else {
48008 *registeredServersSize = 0;
48009 *registeredServers = NULL;
48010 }
48011
48012 /* Clean up */
48013 UA_FindServersResponse_clear(p: &response);
48014 if(!connected)
48015 UA_Client_disconnect(client);
48016 return retval;
48017}
48018
48019#ifdef UA_ENABLE_DISCOVERY
48020
48021UA_StatusCode
48022UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl,
48023 UA_UInt32 startingRecordId, UA_UInt32 maxRecordsToReturn,
48024 size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter,
48025 size_t *serverOnNetworkSize, UA_ServerOnNetwork **serverOnNetwork) {
48026 UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN);
48027 /* Client is already connected to a different server */
48028 if(connected && strncmp((const char*)client->config.endpoint.endpointUrl.data, serverUrl,
48029 client->config.endpoint.endpointUrl.length) != 0) {
48030 return UA_STATUSCODE_BADINVALIDARGUMENT;
48031 }
48032
48033 UA_StatusCode retval;
48034 if(!connected) {
48035 retval = UA_Client_connectSecureChannel(client, serverUrl);
48036 if(retval != UA_STATUSCODE_GOOD)
48037 return retval;
48038 }
48039
48040 /* Prepare the request */
48041 UA_FindServersOnNetworkRequest request;
48042 UA_FindServersOnNetworkRequest_init(&request);
48043 request.startingRecordId = startingRecordId;
48044 request.maxRecordsToReturn = maxRecordsToReturn;
48045 request.serverCapabilityFilterSize = serverCapabilityFilterSize;
48046 request.serverCapabilityFilter = serverCapabilityFilter;
48047
48048 /* Send the request */
48049 UA_FindServersOnNetworkResponse response;
48050 __UA_Client_Service(client, &request, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST],
48051 &response, &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]);
48052
48053 /* Process the response */
48054 retval = response.responseHeader.serviceResult;
48055 if(retval == UA_STATUSCODE_GOOD) {
48056 *serverOnNetworkSize = response.serversSize;
48057 *serverOnNetwork = response.servers;
48058 response.serversSize = 0;
48059 response.servers = NULL;
48060 } else {
48061 *serverOnNetworkSize = 0;
48062 *serverOnNetwork = NULL;
48063 }
48064
48065 /* Clean up */
48066 UA_FindServersOnNetworkResponse_clear(&response);
48067 if(!connected)
48068 UA_Client_disconnect(client);
48069 return retval;
48070}
48071
48072#endif
48073
48074/**** amalgamated original file "/src/client/ua_client_highlevel.c" ****/
48075
48076/* This Source Code Form is subject to the terms of the Mozilla Public
48077 * License, v. 2.0. If a copy of the MPL was not distributed with this
48078 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
48079 *
48080 * Copyright 2015-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
48081 * Copyright 2015 (c) Oleksiy Vasylyev
48082 * Copyright 2017 (c) Florian Palm
48083 * Copyright 2016 (c) Chris Iatrou
48084 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
48085 * Copyright 2018 (c) Fabian Arndt
48086 * Copyright 2018 (c) Peter Rustler, basyskom GmbH
48087 */
48088
48089
48090/* The highlevel client API is an "outer onion layer". This file does not
48091 * include ua_client_internal.h on purpose. */
48092
48093UA_StatusCode
48094UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri,
48095 UA_UInt16 *namespaceIndex) {
48096 UA_ReadRequest request;
48097 UA_ReadRequest_init(p: &request);
48098 UA_ReadValueId id;
48099 UA_ReadValueId_init(p: &id);
48100 id.attributeId = UA_ATTRIBUTEID_VALUE;
48101 id.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY);
48102 request.nodesToRead = &id;
48103 request.nodesToReadSize = 1;
48104
48105 UA_ReadResponse response = UA_Client_Service_read(client, request);
48106
48107 UA_StatusCode retval = UA_STATUSCODE_GOOD;
48108 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
48109 retval = response.responseHeader.serviceResult;
48110 else if(response.resultsSize != 1 || !response.results[0].hasValue)
48111 retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
48112 else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
48113 retval = UA_STATUSCODE_BADTYPEMISMATCH;
48114
48115 if(retval != UA_STATUSCODE_GOOD) {
48116 UA_ReadResponse_clear(p: &response);
48117 return retval;
48118 }
48119
48120 retval = UA_STATUSCODE_BADNOTFOUND;
48121 UA_String *ns = (UA_String *)response.results[0].value.data;
48122 for(size_t i = 0; i < response.results[0].value.arrayLength; ++i) {
48123 if(UA_String_equal(s1: namespaceUri, s2: &ns[i])) {
48124 *namespaceIndex = (UA_UInt16)i;
48125 retval = UA_STATUSCODE_GOOD;
48126 break;
48127 }
48128 }
48129
48130 UA_ReadResponse_clear(p: &response);
48131 return retval;
48132}
48133
48134UA_StatusCode
48135UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId,
48136 UA_NodeIteratorCallback callback, void *handle) {
48137 UA_BrowseRequest bReq;
48138 UA_BrowseRequest_init(p: &bReq);
48139 bReq.requestedMaxReferencesPerNode = 0;
48140 bReq.nodesToBrowse = UA_BrowseDescription_new();
48141 bReq.nodesToBrowseSize = 1;
48142 UA_NodeId_copy(src: &parentNodeId, dst: &bReq.nodesToBrowse[0].nodeId);
48143 bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything
48144 bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH;
48145
48146 UA_BrowseResponse bResp = UA_Client_Service_browse(client, request: bReq);
48147
48148 UA_StatusCode retval = bResp.responseHeader.serviceResult;
48149 if(retval == UA_STATUSCODE_GOOD) {
48150 for(size_t i = 0; i < bResp.resultsSize; ++i) {
48151 for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) {
48152 UA_ReferenceDescription *ref = &bResp.results[i].references[j];
48153 retval |= callback(ref->nodeId.nodeId, !ref->isForward,
48154 ref->referenceTypeId, handle);
48155 }
48156 }
48157 }
48158
48159 UA_BrowseRequest_clear(p: &bReq);
48160 UA_BrowseResponse_clear(p: &bResp);
48161 return retval;
48162}
48163
48164/*******************/
48165/* Node Management */
48166/*******************/
48167
48168UA_StatusCode
48169UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId,
48170 const UA_NodeId referenceTypeId, UA_Boolean isForward,
48171 const UA_String targetServerUri,
48172 const UA_ExpandedNodeId targetNodeId,
48173 UA_NodeClass targetNodeClass) {
48174 UA_AddReferencesItem item;
48175 UA_AddReferencesItem_init(p: &item);
48176 item.sourceNodeId = sourceNodeId;
48177 item.referenceTypeId = referenceTypeId;
48178 item.isForward = isForward;
48179 item.targetServerUri = targetServerUri;
48180 item.targetNodeId = targetNodeId;
48181 item.targetNodeClass = targetNodeClass;
48182 UA_AddReferencesRequest request;
48183 UA_AddReferencesRequest_init(p: &request);
48184 request.referencesToAdd = &item;
48185 request.referencesToAddSize = 1;
48186 UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request);
48187 UA_StatusCode retval = response.responseHeader.serviceResult;
48188 if(retval != UA_STATUSCODE_GOOD) {
48189 UA_AddReferencesResponse_clear(p: &response);
48190 return retval;
48191 }
48192 if(response.resultsSize != 1) {
48193 UA_AddReferencesResponse_clear(p: &response);
48194 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48195 }
48196 retval = response.results[0];
48197 UA_AddReferencesResponse_clear(p: &response);
48198 return retval;
48199}
48200
48201UA_StatusCode
48202UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId,
48203 const UA_NodeId referenceTypeId, UA_Boolean isForward,
48204 const UA_ExpandedNodeId targetNodeId,
48205 UA_Boolean deleteBidirectional) {
48206 UA_DeleteReferencesItem item;
48207 UA_DeleteReferencesItem_init(p: &item);
48208 item.sourceNodeId = sourceNodeId;
48209 item.referenceTypeId = referenceTypeId;
48210 item.isForward = isForward;
48211 item.targetNodeId = targetNodeId;
48212 item.deleteBidirectional = deleteBidirectional;
48213 UA_DeleteReferencesRequest request;
48214 UA_DeleteReferencesRequest_init(p: &request);
48215 request.referencesToDelete = &item;
48216 request.referencesToDeleteSize = 1;
48217 UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request);
48218 UA_StatusCode retval = response.responseHeader.serviceResult;
48219 if(retval != UA_STATUSCODE_GOOD) {
48220 UA_DeleteReferencesResponse_clear(p: &response);
48221 return retval;
48222 }
48223 if(response.resultsSize != 1) {
48224 UA_DeleteReferencesResponse_clear(p: &response);
48225 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48226 }
48227 retval = response.results[0];
48228 UA_DeleteReferencesResponse_clear(p: &response);
48229 return retval;
48230}
48231
48232UA_StatusCode
48233UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId,
48234 UA_Boolean deleteTargetReferences) {
48235 UA_DeleteNodesItem item;
48236 UA_DeleteNodesItem_init(p: &item);
48237 item.nodeId = nodeId;
48238 item.deleteTargetReferences = deleteTargetReferences;
48239 UA_DeleteNodesRequest request;
48240 UA_DeleteNodesRequest_init(p: &request);
48241 request.nodesToDelete = &item;
48242 request.nodesToDeleteSize = 1;
48243 UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request);
48244 UA_StatusCode retval = response.responseHeader.serviceResult;
48245 if(retval != UA_STATUSCODE_GOOD) {
48246 UA_DeleteNodesResponse_clear(p: &response);
48247 return retval;
48248 }
48249 if(response.resultsSize != 1) {
48250 UA_DeleteNodesResponse_clear(p: &response);
48251 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48252 }
48253 retval = response.results[0];
48254 UA_DeleteNodesResponse_clear(p: &response);
48255 return retval;
48256}
48257
48258UA_StatusCode
48259__UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClass,
48260 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
48261 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
48262 const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
48263 const UA_DataType *attributeType, UA_NodeId *outNewNodeId) {
48264 UA_AddNodesRequest request;
48265 UA_AddNodesRequest_init(p: &request);
48266 UA_AddNodesItem item;
48267 UA_AddNodesItem_init(p: &item);
48268 item.parentNodeId.nodeId = parentNodeId;
48269 item.referenceTypeId = referenceTypeId;
48270 item.requestedNewNodeId.nodeId = requestedNewNodeId;
48271 item.browseName = browseName;
48272 item.nodeClass = nodeClass;
48273 item.typeDefinition.nodeId = typeDefinition;
48274 item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
48275 item.nodeAttributes.content.decoded.type = attributeType;
48276 item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into.
48277 request.nodesToAdd = &item;
48278 request.nodesToAddSize = 1;
48279 UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request);
48280
48281 UA_StatusCode retval = response.responseHeader.serviceResult;
48282 if(retval != UA_STATUSCODE_GOOD) {
48283 UA_AddNodesResponse_clear(p: &response);
48284 return retval;
48285 }
48286
48287 if(response.resultsSize != 1) {
48288 UA_AddNodesResponse_clear(p: &response);
48289 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48290 }
48291
48292 /* Move the id of the created node */
48293 retval = response.results[0].statusCode;
48294 if(retval == UA_STATUSCODE_GOOD && outNewNodeId) {
48295 *outNewNodeId = response.results[0].addedNodeId;
48296 UA_NodeId_init(p: &response.results[0].addedNodeId);
48297 }
48298
48299 UA_AddNodesResponse_clear(p: &response);
48300 return retval;
48301}
48302
48303/********/
48304/* Call */
48305/********/
48306
48307#ifdef UA_ENABLE_METHODCALLS
48308
48309UA_StatusCode
48310UA_Client_call(UA_Client *client, const UA_NodeId objectId,
48311 const UA_NodeId methodId, size_t inputSize,
48312 const UA_Variant *input, size_t *outputSize,
48313 UA_Variant **output) {
48314 /* Set up the request */
48315 UA_CallRequest request;
48316 UA_CallRequest_init(p: &request);
48317 UA_CallMethodRequest item;
48318 UA_CallMethodRequest_init(p: &item);
48319 item.methodId = methodId;
48320 item.objectId = objectId;
48321 item.inputArguments = (UA_Variant *)(void*)(uintptr_t)input; // cast const...
48322 item.inputArgumentsSize = inputSize;
48323 request.methodsToCall = &item;
48324 request.methodsToCallSize = 1;
48325
48326 /* Call the service */
48327 UA_CallResponse response = UA_Client_Service_call(client, request);
48328 UA_StatusCode retval = response.responseHeader.serviceResult;
48329 if(retval == UA_STATUSCODE_GOOD) {
48330 if(response.resultsSize == 1)
48331 retval = response.results[0].statusCode;
48332 else
48333 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48334 }
48335 if(retval != UA_STATUSCODE_GOOD) {
48336 UA_CallResponse_clear(p: &response);
48337 return retval;
48338 }
48339
48340 /* Move the output arguments */
48341 if(output != NULL && outputSize != NULL) {
48342 *output = response.results[0].outputArguments;
48343 *outputSize = response.results[0].outputArgumentsSize;
48344 response.results[0].outputArguments = NULL;
48345 response.results[0].outputArgumentsSize = 0;
48346 }
48347 UA_CallResponse_clear(p: &response);
48348 return retval;
48349}
48350
48351#endif
48352
48353/********************/
48354/* Write Attributes */
48355/********************/
48356
48357UA_StatusCode
48358__UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId,
48359 UA_AttributeId attributeId, const void *in,
48360 const UA_DataType *inDataType) {
48361 if(!in)
48362 return UA_STATUSCODE_BADTYPEMISMATCH;
48363
48364 UA_WriteValue wValue;
48365 UA_WriteValue_init(p: &wValue);
48366 wValue.nodeId = *nodeId;
48367 wValue.attributeId = attributeId;
48368 if(attributeId == UA_ATTRIBUTEID_VALUE)
48369 wValue.value.value = *(const UA_Variant*)in;
48370 else
48371 /* hack. is never written into. */
48372 UA_Variant_setScalar(v: &wValue.value.value, p: (void*)(uintptr_t)in, type: inDataType);
48373 wValue.value.hasValue = true;
48374 UA_WriteRequest wReq;
48375 UA_WriteRequest_init(p: &wReq);
48376 wReq.nodesToWrite = &wValue;
48377 wReq.nodesToWriteSize = 1;
48378
48379 UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq);
48380
48381 UA_StatusCode retval = wResp.responseHeader.serviceResult;
48382 if(retval == UA_STATUSCODE_GOOD) {
48383 if(wResp.resultsSize == 1)
48384 retval = wResp.results[0];
48385 else
48386 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48387 }
48388
48389 UA_WriteResponse_clear(p: &wResp);
48390 return retval;
48391}
48392
48393UA_StatusCode
48394UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
48395 size_t newArrayDimensionsSize,
48396 const UA_UInt32 *newArrayDimensions) {
48397 if(!newArrayDimensions)
48398 return UA_STATUSCODE_BADTYPEMISMATCH;
48399
48400 UA_WriteValue wValue;
48401 UA_WriteValue_init(p: &wValue);
48402 wValue.nodeId = nodeId;
48403 wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
48404 UA_Variant_setArray(v: &wValue.value.value, array: (void*)(uintptr_t)newArrayDimensions,
48405 arraySize: newArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
48406 wValue.value.hasValue = true;
48407 UA_WriteRequest wReq;
48408 UA_WriteRequest_init(p: &wReq);
48409 wReq.nodesToWrite = &wValue;
48410 wReq.nodesToWriteSize = 1;
48411
48412 UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq);
48413
48414 UA_StatusCode retval = wResp.responseHeader.serviceResult;
48415 if(retval == UA_STATUSCODE_GOOD) {
48416 if(wResp.resultsSize == 1)
48417 retval = wResp.results[0];
48418 else
48419 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48420 }
48421 UA_WriteResponse_clear(p: &wResp);
48422 return retval;
48423}
48424
48425/*******************/
48426/* Read Attributes */
48427/*******************/
48428
48429UA_StatusCode
48430__UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId,
48431 UA_AttributeId attributeId, void *out,
48432 const UA_DataType *outDataType) {
48433 UA_ReadValueId item;
48434 UA_ReadValueId_init(p: &item);
48435 item.nodeId = *nodeId;
48436 item.attributeId = attributeId;
48437 UA_ReadRequest request;
48438 UA_ReadRequest_init(p: &request);
48439 request.nodesToRead = &item;
48440 request.nodesToReadSize = 1;
48441 UA_ReadResponse response = UA_Client_Service_read(client, request);
48442 UA_StatusCode retval = response.responseHeader.serviceResult;
48443 if(retval == UA_STATUSCODE_GOOD) {
48444 if(response.resultsSize == 1)
48445 retval = response.results[0].status;
48446 else
48447 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48448 }
48449 if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD)) {
48450 UA_ReadResponse_clear(p: &response);
48451 return retval;
48452 }
48453
48454 /* Set the StatusCode */
48455 UA_DataValue *res = response.results;
48456 if(res->hasStatus)
48457 retval = res->status;
48458
48459 /* Return early of no value is given */
48460 if(!res->hasValue) {
48461 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48462 UA_ReadResponse_clear(p: &response);
48463 return retval;
48464 }
48465
48466 /* Copy value into out */
48467 if(attributeId == UA_ATTRIBUTEID_VALUE) {
48468 memcpy(dest: out, src: &res->value, n: sizeof(UA_Variant));
48469 UA_Variant_init(p: &res->value);
48470 } else if(attributeId == UA_ATTRIBUTEID_NODECLASS) {
48471 memcpy(dest: out, src: (UA_NodeClass*)res->value.data, n: sizeof(UA_NodeClass));
48472 } else if(UA_Variant_isScalar(v: &res->value) &&
48473 res->value.type == outDataType) {
48474 memcpy(dest: out, src: res->value.data, n: res->value.type->memSize);
48475 UA_free(ptr: res->value.data);
48476 res->value.data = NULL;
48477 } else {
48478 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48479 }
48480
48481 UA_ReadResponse_clear(p: &response);
48482 return retval;
48483}
48484
48485static UA_StatusCode
48486processReadArrayDimensionsResult(UA_ReadResponse *response,
48487 UA_UInt32 **outArrayDimensions,
48488 size_t *outArrayDimensionsSize) {
48489 UA_StatusCode retval = response->responseHeader.serviceResult;
48490 if(retval != UA_STATUSCODE_GOOD)
48491 return retval;
48492
48493 if(response->resultsSize != 1)
48494 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48495
48496 retval = response->results[0].status;
48497 if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD))
48498 return retval;
48499
48500 UA_DataValue *res = &response->results[0];
48501 if(!res->hasValue ||
48502 UA_Variant_isScalar(v: &res->value) ||
48503 res->value.type != &UA_TYPES[UA_TYPES_UINT32])
48504 return UA_STATUSCODE_BADUNEXPECTEDERROR;
48505
48506 /* Move results */
48507 *outArrayDimensions = (UA_UInt32*)res->value.data;
48508 *outArrayDimensionsSize = res->value.arrayLength;
48509 res->value.data = NULL;
48510 res->value.arrayLength = 0;
48511 return UA_STATUSCODE_GOOD;
48512}
48513
48514UA_StatusCode
48515UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId,
48516 size_t *outArrayDimensionsSize,
48517 UA_UInt32 **outArrayDimensions) {
48518 UA_ReadValueId item;
48519 UA_ReadValueId_init(p: &item);
48520 item.nodeId = nodeId;
48521 item.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS;
48522 UA_ReadRequest request;
48523 UA_ReadRequest_init(p: &request);
48524 request.nodesToRead = &item;
48525 request.nodesToReadSize = 1;
48526
48527 UA_ReadResponse response = UA_Client_Service_read(client, request);
48528 UA_StatusCode retval = processReadArrayDimensionsResult(response: &response, outArrayDimensions,
48529 outArrayDimensionsSize);
48530 UA_ReadResponse_clear(p: &response);
48531 return retval;
48532}
48533
48534/*********************/
48535/* Historical Access */
48536/*********************/
48537#ifdef UA_ENABLE_HISTORIZING
48538static UA_HistoryReadResponse
48539__UA_Client_HistoryRead(UA_Client *client, const UA_NodeId *nodeId,
48540 UA_ExtensionObject* details, UA_String indexRange,
48541 UA_TimestampsToReturn timestampsToReturn,
48542 UA_ByteString continuationPoint, UA_Boolean releaseConti) {
48543
48544 UA_HistoryReadValueId item;
48545 UA_HistoryReadValueId_init(p: &item);
48546
48547 item.nodeId = *nodeId;
48548 item.indexRange = indexRange;
48549 item.continuationPoint = continuationPoint;
48550 item.dataEncoding = UA_QUALIFIEDNAME(nsIndex: 0, chars: "Default Binary");
48551
48552 UA_HistoryReadRequest request;
48553 UA_HistoryReadRequest_init(p: &request);
48554
48555 request.nodesToRead = &item;
48556 request.nodesToReadSize = 1;
48557 request.timestampsToReturn = timestampsToReturn; // Defaults to Source
48558 request.releaseContinuationPoints = releaseConti; // No values are returned, if true
48559
48560 /* Build ReadDetails */
48561 request.historyReadDetails = *details;
48562
48563 return UA_Client_Service_historyRead(client, request);
48564}
48565
48566static UA_StatusCode
48567__UA_Client_HistoryRead_service(UA_Client *client, const UA_NodeId *nodeId,
48568 const UA_HistoricalIteratorCallback callback,
48569 UA_ExtensionObject *details, UA_String indexRange,
48570 UA_TimestampsToReturn timestampsToReturn,
48571 void *callbackContext) {
48572
48573 UA_ByteString continuationPoint = UA_BYTESTRING_NULL;
48574 UA_Boolean continuationAvail = false;
48575 UA_Boolean fetchMore = false;
48576 UA_StatusCode retval = UA_STATUSCODE_GOOD;
48577
48578 do {
48579 /* We release the continuation point, if no more data is requested by the user */
48580 UA_Boolean cleanup = !fetchMore && continuationAvail;
48581 UA_HistoryReadResponse response =
48582 __UA_Client_HistoryRead(client, nodeId, details, indexRange, timestampsToReturn, continuationPoint, releaseConti: cleanup);
48583
48584 if (cleanup) {
48585 retval = response.responseHeader.serviceResult;
48586cleanup: UA_HistoryReadResponse_clear(p: &response);
48587 UA_ByteString_clear(p: &continuationPoint);
48588 return retval;
48589 }
48590
48591 retval = response.responseHeader.serviceResult;
48592 if (retval == UA_STATUSCODE_GOOD) {
48593 if (response.resultsSize == 1)
48594 retval = response.results[0].statusCode;
48595 else
48596 retval = UA_STATUSCODE_BADUNEXPECTEDERROR;
48597 }
48598 if (!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD))
48599 goto cleanup;
48600
48601 UA_HistoryReadResult *res = response.results;
48602
48603 /* Clear old and check / store new continuation point */
48604 UA_ByteString_clear(p: &continuationPoint);
48605 UA_ByteString_copy(src: &res->continuationPoint, dst: &continuationPoint);
48606 continuationAvail = !UA_ByteString_equal(string1: &continuationPoint, string2: &UA_BYTESTRING_NULL);
48607
48608 /* Client callback with possibility to request further values */
48609 fetchMore = callback(client, nodeId, continuationAvail, &res->historyData, callbackContext);
48610
48611 /* Regular cleanup */
48612 UA_HistoryReadResponse_clear(p: &response);
48613 } while (continuationAvail);
48614
48615 return retval;
48616}
48617
48618#ifdef UA_ENABLE_EXPERIMENTAL_HISTORIZING
48619UA_StatusCode
48620UA_Client_HistoryRead_events(UA_Client *client, const UA_NodeId *nodeId,
48621 const UA_HistoricalIteratorCallback callback,
48622 UA_DateTime startTime, UA_DateTime endTime,
48623 UA_String indexRange, const UA_EventFilter filter, UA_UInt32 numValuesPerNode,
48624 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48625
48626 UA_ReadEventDetails details;
48627 UA_ReadEventDetails_init(p: &details);
48628 details.filter = filter;
48629
48630 // At least two of the following parameters must be set
48631 details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
48632 details.startTime = startTime;
48633 details.endTime = endTime;
48634
48635 UA_ExtensionObject detailsExtensionObject;
48636 UA_ExtensionObject_init(p: &detailsExtensionObject);
48637 detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READEVENTDETAILS];
48638 detailsExtensionObject.content.decoded.data = &details;
48639 detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
48640
48641 return __UA_Client_HistoryRead_service(client, nodeId, callback, details: &detailsExtensionObject,
48642 indexRange, timestampsToReturn, callbackContext);
48643}
48644#endif // UA_ENABLE_EXPERIMENTAL_HISTORIZING
48645
48646static UA_StatusCode
48647__UA_Client_HistoryRead_service_rawMod(UA_Client *client, const UA_NodeId *nodeId,
48648 const UA_HistoricalIteratorCallback callback,
48649 UA_DateTime startTime,UA_DateTime endTime,
48650 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
48651 UA_Boolean readModified, UA_TimestampsToReturn timestampsToReturn,
48652 void *callbackContext) {
48653
48654 UA_ReadRawModifiedDetails details;
48655 UA_ReadRawModifiedDetails_init(p: &details);
48656 details.isReadModified = readModified; // Return only modified values
48657 details.returnBounds = returnBounds; // Return values pre / post given range
48658
48659 // At least two of the following parameters must be set
48660 details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of
48661 details.startTime = startTime;
48662 details.endTime = endTime;
48663
48664 UA_ExtensionObject detailsExtensionObject;
48665 UA_ExtensionObject_init(p: &detailsExtensionObject);
48666 detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS];
48667 detailsExtensionObject.content.decoded.data = &details;
48668 detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED;
48669
48670 return __UA_Client_HistoryRead_service(client, nodeId, callback,
48671 details: &detailsExtensionObject, indexRange,
48672 timestampsToReturn, callbackContext);
48673}
48674
48675UA_StatusCode
48676UA_Client_HistoryRead_raw(UA_Client *client, const UA_NodeId *nodeId,
48677 const UA_HistoricalIteratorCallback callback,
48678 UA_DateTime startTime, UA_DateTime endTime,
48679 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode,
48680 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48681
48682 return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds,
48683 numValuesPerNode, false, timestampsToReturn, callbackContext);
48684}
48685
48686#ifdef UA_ENABLE_EXPERIMENTAL_HISTORIZING
48687UA_StatusCode
48688UA_Client_HistoryRead_modified(UA_Client *client, const UA_NodeId *nodeId,
48689 const UA_HistoricalIteratorCallback callback,
48690 UA_DateTime startTime, UA_DateTime endTime,
48691 UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 maxItems,
48692 UA_TimestampsToReturn timestampsToReturn, void *callbackContext) {
48693
48694 return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds,
48695 numValuesPerNode: maxItems, true, timestampsToReturn, callbackContext);
48696}
48697#endif // UA_ENABLE_EXPERIMENTAL_HISTORIZING
48698
48699static UA_HistoryUpdateResponse
48700__UA_Client_HistoryUpdate(UA_Client *client,
48701 void *details,
48702 size_t typeId)
48703{
48704 UA_HistoryUpdateRequest request;
48705 UA_HistoryUpdateRequest_init(p: &request);
48706
48707 UA_ExtensionObject extension;
48708 UA_ExtensionObject_init(p: &extension);
48709 request.historyUpdateDetailsSize = 1;
48710 request.historyUpdateDetails = &extension;
48711
48712 extension.encoding = UA_EXTENSIONOBJECT_DECODED;
48713 extension.content.decoded.type = &UA_TYPES[typeId];
48714 extension.content.decoded.data = details;
48715
48716 UA_HistoryUpdateResponse response;
48717 response = UA_Client_Service_historyUpdate(client, request);
48718 return response;
48719}
48720
48721static UA_StatusCode
48722__UA_Client_HistoryUpdate_updateData(UA_Client *client,
48723 const UA_NodeId *nodeId,
48724 UA_PerformUpdateType type,
48725 UA_DataValue *value)
48726{
48727 UA_StatusCode ret = UA_STATUSCODE_GOOD;
48728 UA_UpdateDataDetails details;
48729 UA_UpdateDataDetails_init(p: &details);
48730
48731 details.performInsertReplace = type;
48732 details.updateValuesSize = 1;
48733 details.updateValues = value;
48734 UA_NodeId_copy(src: nodeId, dst: &details.nodeId);
48735
48736 UA_HistoryUpdateResponse response;
48737 response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_UPDATEDATADETAILS);
48738 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
48739 ret = response.responseHeader.serviceResult;
48740 goto cleanup;
48741 }
48742 if (response.resultsSize != 1 || response.results[0].operationResultsSize != 1) {
48743 ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
48744 goto cleanup;
48745 }
48746 if (response.results[0].statusCode != UA_STATUSCODE_GOOD) {
48747 ret = response.results[0].statusCode;
48748 goto cleanup;
48749 }
48750 ret = response.results[0].operationResults[0];
48751cleanup:
48752 UA_HistoryUpdateResponse_clear(p: &response);
48753 UA_NodeId_clear(p: &details.nodeId);
48754 return ret;
48755}
48756
48757UA_StatusCode
48758UA_Client_HistoryUpdate_insert(UA_Client *client,
48759 const UA_NodeId *nodeId,
48760 UA_DataValue *value)
48761{
48762 return __UA_Client_HistoryUpdate_updateData(client,
48763 nodeId,
48764 type: UA_PERFORMUPDATETYPE_INSERT,
48765 value);
48766}
48767
48768UA_StatusCode
48769UA_Client_HistoryUpdate_replace(UA_Client *client,
48770 const UA_NodeId *nodeId,
48771 UA_DataValue *value)
48772{
48773 return __UA_Client_HistoryUpdate_updateData(client,
48774 nodeId,
48775 type: UA_PERFORMUPDATETYPE_REPLACE,
48776 value);
48777}
48778
48779UA_StatusCode
48780UA_Client_HistoryUpdate_update(UA_Client *client,
48781 const UA_NodeId *nodeId,
48782 UA_DataValue *value)
48783{
48784 return __UA_Client_HistoryUpdate_updateData(client,
48785 nodeId,
48786 type: UA_PERFORMUPDATETYPE_UPDATE,
48787 value);
48788}
48789
48790UA_StatusCode
48791UA_Client_HistoryUpdate_deleteRaw(UA_Client *client,
48792 const UA_NodeId *nodeId,
48793 UA_DateTime startTimestamp,
48794 UA_DateTime endTimestamp)
48795{
48796 UA_StatusCode ret = UA_STATUSCODE_GOOD;
48797
48798 UA_DeleteRawModifiedDetails details;
48799 UA_DeleteRawModifiedDetails_init(p: &details);
48800
48801 details.isDeleteModified = false;
48802 details.startTime = startTimestamp;
48803 details.endTime = endTimestamp;
48804 UA_NodeId_copy(src: nodeId, dst: &details.nodeId);
48805
48806 UA_HistoryUpdateResponse response;
48807 response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_DELETERAWMODIFIEDDETAILS);
48808 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
48809 ret = response.responseHeader.serviceResult;
48810 goto cleanup;
48811 }
48812 if (response.resultsSize != 1) {
48813 ret = UA_STATUSCODE_BADUNEXPECTEDERROR;
48814 goto cleanup;
48815 }
48816
48817 ret = response.results[0].statusCode;
48818
48819cleanup:
48820 UA_HistoryUpdateResponse_clear(p: &response);
48821 UA_NodeId_clear(p: &details.nodeId);
48822 return ret;
48823}
48824#endif // UA_ENABLE_HISTORIZING
48825
48826/*******************/
48827/* Async Functions */
48828/*******************/
48829
48830/*Write Attributes*/
48831UA_StatusCode __UA_Client_writeAttribute_async(UA_Client *client,
48832 const UA_NodeId *nodeId, UA_AttributeId attributeId, const void *in,
48833 const UA_DataType *inDataType, UA_ClientAsyncServiceCallback callback,
48834 void *userdata, UA_UInt32 *reqId) {
48835 if (!in)
48836 return UA_STATUSCODE_BADTYPEMISMATCH;
48837
48838 UA_WriteValue wValue;
48839 UA_WriteValue_init(p: &wValue);
48840 wValue.nodeId = *nodeId;
48841 wValue.attributeId = attributeId;
48842 if (attributeId == UA_ATTRIBUTEID_VALUE)
48843 wValue.value.value = *(const UA_Variant*) in;
48844 else
48845 /* hack. is never written into. */
48846 UA_Variant_setScalar(v: &wValue.value.value, p: (void*) (uintptr_t) in,
48847 type: inDataType);
48848 wValue.value.hasValue = true;
48849 UA_WriteRequest wReq;
48850 UA_WriteRequest_init(p: &wReq);
48851 wReq.nodesToWrite = &wValue;
48852 wReq.nodesToWriteSize = 1;
48853
48854 return __UA_Client_AsyncService(client, request: &wReq,
48855 requestType: &UA_TYPES[UA_TYPES_WRITEREQUEST], callback,
48856 responseType: &UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, requestId: reqId);
48857}
48858
48859/*Node Management*/
48860
48861UA_StatusCode UA_EXPORT
48862__UA_Client_addNode_async(UA_Client *client, const UA_NodeClass nodeClass,
48863 const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId,
48864 const UA_NodeId referenceTypeId, const UA_QualifiedName browseName,
48865 const UA_NodeId typeDefinition, const UA_NodeAttributes *attr,
48866 const UA_DataType *attributeType, UA_NodeId *outNewNodeId,
48867 UA_ClientAsyncServiceCallback callback, void *userdata,
48868 UA_UInt32 *reqId) {
48869 UA_AddNodesRequest request;
48870 UA_AddNodesRequest_init(p: &request);
48871 UA_AddNodesItem item;
48872 UA_AddNodesItem_init(p: &item);
48873 item.parentNodeId.nodeId = parentNodeId;
48874 item.referenceTypeId = referenceTypeId;
48875 item.requestedNewNodeId.nodeId = requestedNewNodeId;
48876 item.browseName = browseName;
48877 item.nodeClass = nodeClass;
48878 item.typeDefinition.nodeId = typeDefinition;
48879 item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE;
48880 item.nodeAttributes.content.decoded.type = attributeType;
48881 item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into.
48882 request.nodesToAdd = &item;
48883 request.nodesToAddSize = 1;
48884
48885 return __UA_Client_AsyncService(client, request: &request,
48886 requestType: &UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback,
48887 responseType: &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, requestId: reqId);
48888
48889}
48890
48891/* Misc Highlevel Functions */
48892#ifdef UA_ENABLE_METHODCALLS
48893UA_StatusCode __UA_Client_call_async(UA_Client *client,
48894 const UA_NodeId objectId, const UA_NodeId methodId, size_t inputSize,
48895 const UA_Variant *input, UA_ClientAsyncServiceCallback callback,
48896 void *userdata, UA_UInt32 *reqId) {
48897
48898 UA_CallRequest request;
48899 UA_CallRequest_init(p: &request);
48900 UA_CallMethodRequest item;
48901 UA_CallMethodRequest_init(p: &item);
48902 item.methodId = methodId;
48903 item.objectId = objectId;
48904 item.inputArguments = (UA_Variant *) (void*) (uintptr_t) input; // cast const...
48905 item.inputArgumentsSize = inputSize;
48906 request.methodsToCall = &item;
48907 request.methodsToCallSize = 1;
48908
48909 return __UA_Client_AsyncService(client, request: &request,
48910 requestType: &UA_TYPES[UA_TYPES_CALLREQUEST], callback,
48911 responseType: &UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, requestId: reqId);
48912}
48913#endif
48914
48915/* UA_StatusCode */
48916/* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */
48917/* UA_UInt32 *ids, size_t pathSize, */
48918/* UA_ClientAsyncTranslateCallback callback, */
48919/* void *userdata, UA_UInt32 *reqId) { */
48920/* return UA_STATUSCODE_BADNOTIMPLEMENTED; */
48921/* } */
48922
48923/*************************/
48924/* Read Single Attribute */
48925/*************************/
48926
48927typedef struct {
48928 UA_ClientAsyncOperationCallback userCallback;
48929 void *userContext;
48930 const UA_DataType *resultType; /* DataValue -> Value attribute,
48931 * Variant -> ArrayDimensions attribute */
48932} UA_AttributeReadContext;
48933
48934static void
48935AttributeReadCallback(UA_Client *client, void *userdata,
48936 UA_UInt32 requestId, UA_ReadResponse *rr) {
48937 UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)userdata;
48938 UA_LOG_DEBUG(logger: &UA_Client_getConfig(client)->logger, category: UA_LOGCATEGORY_CLIENT,
48939 msg: "Async read response for request %" PRIu32, requestId);
48940
48941 /* Check the ServiceResult */
48942 UA_StatusCode res = rr->responseHeader.serviceResult;
48943 if(res != UA_STATUSCODE_GOOD)
48944 goto finish;
48945
48946 /* Check result array size */
48947 if(rr->resultsSize != 1) {
48948 res = UA_STATUSCODE_BADINTERNALERROR;
48949 goto finish;
48950 }
48951
48952 /* A Value attribute */
48953 UA_DataValue *dv = &rr->results[0];
48954 if(ctx->resultType == &UA_TYPES[UA_TYPES_DATAVALUE]) {
48955 ctx->userCallback(client, ctx->userContext, requestId,
48956 UA_STATUSCODE_GOOD, dv);
48957 goto finish;
48958 }
48959
48960 /* An ArrayDimensions attribute. Has to be an array of UInt32. */
48961 if(ctx->resultType == &UA_TYPES[UA_TYPES_VARIANT]) {
48962 if(dv->hasValue &&
48963 UA_Variant_hasArrayType(v: &dv->value, type: &UA_TYPES[UA_TYPES_UINT32])) {
48964 ctx->userCallback(client, ctx->userContext, requestId,
48965 UA_STATUSCODE_GOOD, &dv->value);
48966 } else {
48967 res = UA_STATUSCODE_BADINTERNALERROR;
48968 }
48969 goto finish;
48970 }
48971
48972 /* Check we have a scalar value of the right datatype */
48973 if(!dv->hasValue ||
48974 !UA_Variant_hasScalarType(v: &dv->value, type: ctx->resultType)) {
48975 res = UA_STATUSCODE_BADINTERNALERROR;
48976 goto finish;
48977 }
48978
48979 /* Callback into userland */
48980 ctx->userCallback(client, ctx->userContext, requestId,
48981 UA_STATUSCODE_GOOD, dv->value.data);
48982
48983 finish:
48984 if(res != UA_STATUSCODE_GOOD)
48985 ctx->userCallback(client, ctx->userContext, requestId, res, NULL);
48986 UA_free(ptr: ctx);
48987}
48988
48989static UA_StatusCode
48990readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
48991 UA_TimestampsToReturn timestampsToReturn,
48992 const UA_DataType *resultType, /* For the specialized reads */
48993 UA_ClientAsyncOperationCallback callback,
48994 void *userdata, UA_UInt32 *requestId) {
48995 UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)
48996 UA_malloc(size: sizeof(UA_AttributeReadContext));
48997 if(!ctx)
48998 return UA_STATUSCODE_BADOUTOFMEMORY;
48999
49000 ctx->userCallback = callback;
49001 ctx->userContext = userdata;
49002 ctx->resultType = resultType;
49003
49004 UA_ReadRequest request;
49005 UA_ReadRequest_init(p: &request);
49006 request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi; /* hack, treated as const */
49007 request.nodesToReadSize = 1;
49008 request.timestampsToReturn = timestampsToReturn;
49009
49010 UA_StatusCode res =
49011 __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST],
49012 callback: (UA_ClientAsyncServiceCallback)AttributeReadCallback,
49013 responseType: &UA_TYPES[UA_TYPES_READRESPONSE], userdata: ctx, requestId);
49014 if(res != UA_STATUSCODE_GOOD)
49015 UA_free(ptr: ctx);
49016 return res;
49017}
49018
49019UA_StatusCode
49020UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi,
49021 UA_TimestampsToReturn timestampsToReturn,
49022 UA_ClientAsyncReadAttributeCallback callback,
49023 void *userdata, UA_UInt32 *requestId) {
49024 return readAttribute_async(client, rvi, timestampsToReturn,
49025 resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special handling */
49026 callback: (UA_ClientAsyncOperationCallback)callback,
49027 userdata, requestId);
49028}
49029
49030/* Helper to keep the code short */
49031static UA_StatusCode
49032readAttribute_simpleAsync(UA_Client *client, const UA_NodeId *nodeId,
49033 UA_AttributeId attributeId, const UA_DataType *resultType,
49034 UA_ClientAsyncOperationCallback callback,
49035 void *userdata, UA_UInt32 *requestId) {
49036 UA_ReadValueId rvi;
49037 UA_ReadValueId_init(p: &rvi);
49038 rvi.nodeId = *nodeId;
49039 rvi.attributeId = attributeId;
49040 return readAttribute_async(client, rvi: &rvi, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER,
49041 resultType, callback, userdata, requestId);
49042}
49043
49044UA_StatusCode
49045UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49046 UA_ClientAsyncReadValueAttributeCallback callback,
49047 void *userdata, UA_UInt32 *requestId) {
49048 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUE,
49049 resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special hndling */
49050 callback: (UA_ClientAsyncOperationCallback)callback,
49051 userdata, requestId);
49052}
49053
49054UA_StatusCode
49055UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49056 UA_ClientAsyncReadDataTypeAttributeCallback callback,
49057 void *userdata, UA_UInt32 *requestId) {
49058 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DATATYPE,
49059 resultType: &UA_TYPES[UA_TYPES_NODEID],
49060 callback: (UA_ClientAsyncOperationCallback)callback,
49061 userdata, requestId);
49062}
49063
49064UA_StatusCode
49065UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49066 UA_ClientReadArrayDimensionsAttributeCallback callback,
49067 void *userdata, UA_UInt32 *requestId) {
49068 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS,
49069 resultType: &UA_TYPES[UA_TYPES_VARIANT], /* special handling */
49070 callback: (UA_ClientAsyncOperationCallback)callback,
49071 userdata, requestId);
49072}
49073
49074UA_StatusCode
49075UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49076 UA_ClientAsyncReadNodeClassAttributeCallback callback,
49077 void *userdata, UA_UInt32 *requestId) {
49078 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_NODECLASS,
49079 resultType: &UA_TYPES[UA_TYPES_NODECLASS],
49080 callback: (UA_ClientAsyncOperationCallback)callback,
49081 userdata, requestId);
49082}
49083
49084UA_StatusCode
49085UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49086 UA_ClientAsyncReadBrowseNameAttributeCallback callback,
49087 void *userdata, UA_UInt32 *requestId) {
49088 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_BROWSENAME,
49089 resultType: &UA_TYPES[UA_TYPES_QUALIFIEDNAME],
49090 callback: (UA_ClientAsyncOperationCallback)callback,
49091 userdata, requestId);
49092}
49093
49094UA_StatusCode
49095UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49096 UA_ClientAsyncReadDisplayNameAttributeCallback callback,
49097 void *userdata, UA_UInt32 *requestId) {
49098 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DISPLAYNAME,
49099 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
49100 callback: (UA_ClientAsyncOperationCallback)callback,
49101 userdata, requestId);
49102}
49103
49104UA_StatusCode
49105UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49106 UA_ClientAsyncReadDescriptionAttributeCallback callback,
49107 void *userdata, UA_UInt32 *requestId) {
49108 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DESCRIPTION,
49109 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
49110 callback: (UA_ClientAsyncOperationCallback)callback,
49111 userdata, requestId);
49112}
49113
49114UA_StatusCode
49115UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49116 UA_ClientAsyncReadWriteMaskAttributeCallback callback,
49117 void *userdata, UA_UInt32 *requestId) {
49118 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_WRITEMASK,
49119 resultType: &UA_TYPES[UA_TYPES_UINT32],
49120 callback: (UA_ClientAsyncOperationCallback)callback,
49121 userdata, requestId);
49122}
49123
49124UA_StatusCode UA_EXPORT
49125UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49126 UA_ClientAsyncReadUserWriteMaskAttributeCallback callback,
49127 void *userdata, UA_UInt32 *requestId) {
49128 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERWRITEMASK,
49129 resultType: &UA_TYPES[UA_TYPES_UINT32],
49130 callback: (UA_ClientAsyncOperationCallback)callback,
49131 userdata, requestId);
49132}
49133
49134UA_StatusCode
49135UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49136 UA_ClientAsyncReadIsAbstractAttributeCallback callback,
49137 void *userdata, UA_UInt32 *requestId) {
49138 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ISABSTRACT,
49139 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49140 callback: (UA_ClientAsyncOperationCallback)callback,
49141 userdata, requestId);
49142}
49143
49144UA_StatusCode
49145UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49146 UA_ClientAsyncReadSymmetricAttributeCallback callback,
49147 void *userdata, UA_UInt32 *requestId) {
49148 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_SYMMETRIC,
49149 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49150 callback: (UA_ClientAsyncOperationCallback)callback,
49151 userdata, requestId);
49152}
49153
49154UA_StatusCode
49155UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49156 UA_ClientAsyncReadInverseNameAttributeCallback callback,
49157 void *userdata, UA_UInt32 *requestId) {
49158 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_INVERSENAME,
49159 resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT],
49160 callback: (UA_ClientAsyncOperationCallback)callback,
49161 userdata, requestId);
49162}
49163
49164UA_StatusCode
49165UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49166 UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback,
49167 void *userdata, UA_UInt32 *requestId) {
49168 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_CONTAINSNOLOOPS,
49169 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49170 callback: (UA_ClientAsyncOperationCallback)callback,
49171 userdata, requestId);
49172}
49173
49174UA_StatusCode
49175UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49176 UA_ClientAsyncReadEventNotifierAttributeCallback callback,
49177 void *userdata, UA_UInt32 *requestId) {
49178 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EVENTNOTIFIER,
49179 resultType: &UA_TYPES[UA_TYPES_BYTE],
49180 callback: (UA_ClientAsyncOperationCallback)callback,
49181 userdata, requestId);
49182}
49183
49184UA_StatusCode
49185UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49186 UA_ClientAsyncReadValueRankAttributeCallback callback,
49187 void *userdata, UA_UInt32 *requestId) {
49188 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUERANK,
49189 resultType: &UA_TYPES[UA_TYPES_INT32],
49190 callback: (UA_ClientAsyncOperationCallback)callback,
49191 userdata, requestId);
49192}
49193
49194UA_StatusCode
49195UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49196 UA_ClientAsyncReadAccessLevelAttributeCallback callback,
49197 void *userdata, UA_UInt32 *requestId) {
49198 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ACCESSLEVEL,
49199 resultType: &UA_TYPES[UA_TYPES_BYTE],
49200 callback: (UA_ClientAsyncOperationCallback)callback,
49201 userdata, requestId);
49202}
49203
49204UA_StatusCode
49205UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49206 UA_ClientAsyncReadUserAccessLevelAttributeCallback callback,
49207 void *userdata, UA_UInt32 *requestId) {
49208 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERACCESSLEVEL,
49209 resultType: &UA_TYPES[UA_TYPES_BYTE],
49210 callback: (UA_ClientAsyncOperationCallback)callback,
49211 userdata, requestId);
49212}
49213
49214UA_StatusCode
49215UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49216 UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback,
49217 void *userdata, UA_UInt32 *requestId) {
49218 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL,
49219 resultType: &UA_TYPES[UA_TYPES_DOUBLE],
49220 callback: (UA_ClientAsyncOperationCallback)callback,
49221 userdata, requestId);
49222}
49223
49224UA_StatusCode
49225UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49226 UA_ClientAsyncReadHistorizingAttributeCallback callback,
49227 void *userdata, UA_UInt32 *requestId) {
49228 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_HISTORIZING,
49229 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49230 callback: (UA_ClientAsyncOperationCallback)callback,
49231 userdata, requestId);
49232}
49233
49234UA_StatusCode
49235UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49236 UA_ClientAsyncReadExecutableAttributeCallback callback,
49237 void *userdata, UA_UInt32 *requestId) {
49238 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EXECUTABLE,
49239 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49240 callback: (UA_ClientAsyncOperationCallback)callback,
49241 userdata, requestId);
49242}
49243
49244UA_StatusCode
49245UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId,
49246 UA_ClientAsyncReadUserExecutableAttributeCallback callback,
49247 void *userdata, UA_UInt32 *requestId) {
49248 return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USEREXECUTABLE,
49249 resultType: &UA_TYPES[UA_TYPES_BOOLEAN],
49250 callback: (UA_ClientAsyncOperationCallback)callback,
49251 userdata, requestId);
49252}
49253
49254/**** amalgamated original file "/src/client/ua_client_subscriptions.c" ****/
49255
49256/* This Source Code Form is subject to the terms of the Mozilla Public
49257 * License, v. 2.0. If a copy of the MPL was not distributed with this
49258 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
49259 *
49260 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
49261 * Copyright 2015 (c) Oleksiy Vasylyev
49262 * Copyright 2016 (c) Sten Grüner
49263 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
49264 * Copyright 2016-2017 (c) Florian Palm
49265 * Copyright 2017 (c) Frank Meerkötter
49266 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
49267 */
49268
49269
49270
49271#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
49272
49273/*****************/
49274/* Subscriptions */
49275/*****************/
49276
49277static void
49278MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
49279 UA_Client_MonitoredItem *mon);
49280
49281static void
49282ua_Subscriptions_create(UA_Client *client, UA_Client_Subscription *newSub,
49283 UA_CreateSubscriptionResponse *response) {
49284 newSub->subscriptionId = response->subscriptionId;
49285 newSub->sequenceNumber = 0;
49286 newSub->lastActivity = UA_DateTime_nowMonotonic();
49287 newSub->publishingInterval = response->revisedPublishingInterval;
49288 newSub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
49289 LIST_INIT(&newSub->monitoredItems);
49290 LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry);
49291}
49292
49293static void
49294ua_Subscriptions_create_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49295 void *r) {
49296 UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r;
49297 CustomCallback *cc = (CustomCallback *)data;
49298 UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData;
49299 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
49300 UA_free(ptr: newSub);
49301 goto cleanup;
49302 }
49303
49304 /* Prepare the internal representation */
49305 ua_Subscriptions_create(client, newSub, response);
49306
49307cleanup:
49308 if(cc->userCallback)
49309 cc->userCallback(client, cc->userData, requestId, response);
49310 UA_free(ptr: cc);
49311}
49312
49313UA_CreateSubscriptionResponse
49314UA_Client_Subscriptions_create(UA_Client *client,
49315 const UA_CreateSubscriptionRequest request,
49316 void *subscriptionContext,
49317 UA_Client_StatusChangeNotificationCallback statusChangeCallback,
49318 UA_Client_DeleteSubscriptionCallback deleteCallback) {
49319 UA_CreateSubscriptionResponse response;
49320 UA_Client_Subscription *sub = (UA_Client_Subscription *)
49321 UA_malloc(size: sizeof(UA_Client_Subscription));
49322 if(!sub) {
49323 UA_CreateSubscriptionResponse_init(p: &response);
49324 response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY;
49325 return response;
49326 }
49327 sub->context = subscriptionContext;
49328 sub->statusChangeCallback = statusChangeCallback;
49329 sub->deleteCallback = deleteCallback;
49330
49331 /* Send the request as a synchronous service call */
49332 __UA_Client_Service(client,
49333 request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
49334 response: &response, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]);
49335 if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49336 {
49337 UA_free (ptr: sub);
49338 return response;
49339 }
49340
49341 ua_Subscriptions_create(client, newSub: sub, response: &response);
49342 return response;
49343}
49344
49345UA_StatusCode
49346UA_Client_Subscriptions_create_async(UA_Client *client,
49347 const UA_CreateSubscriptionRequest request,
49348 void *subscriptionContext,
49349 UA_Client_StatusChangeNotificationCallback statusChangeCallback,
49350 UA_Client_DeleteSubscriptionCallback deleteCallback,
49351 UA_ClientAsyncServiceCallback createCallback,
49352 void *userdata,
49353 UA_UInt32 *requestId) {
49354 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
49355 if(!cc)
49356 return UA_STATUSCODE_BADOUTOFMEMORY;
49357
49358 UA_Client_Subscription *sub = (UA_Client_Subscription *)
49359 UA_malloc(size: sizeof(UA_Client_Subscription));
49360 if(!sub) {
49361 UA_free(ptr: cc);
49362 return UA_STATUSCODE_BADOUTOFMEMORY;
49363 }
49364 sub->context = subscriptionContext;
49365 sub->statusChangeCallback = statusChangeCallback;
49366 sub->deleteCallback = deleteCallback;
49367
49368 cc->userCallback = createCallback;
49369 cc->userData = userdata;
49370 cc->clientData = sub;
49371
49372 /* Send the request as asynchronous service call */
49373 return __UA_Client_AsyncService(
49374 client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST],
49375 callback: ua_Subscriptions_create_handler, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE],
49376 userdata: cc, requestId);
49377}
49378
49379static UA_Client_Subscription *
49380findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) {
49381 UA_Client_Subscription *sub = NULL;
49382 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
49383 if(sub->subscriptionId == subscriptionId)
49384 break;
49385 }
49386 return sub;
49387}
49388
49389static void
49390ua_Subscriptions_modify(UA_Client *client, UA_Client_Subscription *sub,
49391 const UA_ModifySubscriptionResponse *response) {
49392 sub->publishingInterval = response->revisedPublishingInterval;
49393 sub->maxKeepAliveCount = response->revisedMaxKeepAliveCount;
49394}
49395
49396static void
49397ua_Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49398 void *r) {
49399 UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r;
49400 CustomCallback *cc = (CustomCallback *)data;
49401 UA_Client_Subscription *sub =
49402 findSubscription(client, subscriptionId: (UA_UInt32)(uintptr_t)cc->clientData);
49403 if(sub) {
49404 ua_Subscriptions_modify(client, sub, response);
49405 } else {
49406 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49407 msg: "No internal representation of subscription %" PRIu32,
49408 (UA_UInt32)(uintptr_t)cc->clientData);
49409 }
49410
49411 if(cc->userCallback)
49412 cc->userCallback(client, cc->userData, requestId, response);
49413 UA_free(ptr: cc);
49414}
49415
49416UA_ModifySubscriptionResponse
49417UA_Client_Subscriptions_modify(UA_Client *client,
49418 const UA_ModifySubscriptionRequest request) {
49419 UA_ModifySubscriptionResponse response;
49420 UA_ModifySubscriptionResponse_init(p: &response);
49421
49422 /* Find the internal representation */
49423 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49424 if(!sub) {
49425 response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49426 return response;
49427 }
49428
49429 /* Call the service */
49430 __UA_Client_Service(client,
49431 request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
49432 response: &response, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]);
49433
49434 /* Adjust the internal representation */
49435 ua_Subscriptions_modify(client, sub, response: &response);
49436 return response;
49437}
49438
49439UA_StatusCode
49440UA_Client_Subscriptions_modify_async(UA_Client *client,
49441 const UA_ModifySubscriptionRequest request,
49442 UA_ClientAsyncServiceCallback callback,
49443 void *userdata, UA_UInt32 *requestId) {
49444 /* Find the internal representation */
49445 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49446 if(!sub)
49447 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49448
49449 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
49450 if(!cc)
49451 return UA_STATUSCODE_BADOUTOFMEMORY;
49452
49453 cc->clientData = (void *)(uintptr_t)request.subscriptionId;
49454 cc->userData = userdata;
49455 cc->userCallback = callback;
49456
49457 return __UA_Client_AsyncService(
49458 client, request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST],
49459 callback: ua_Subscriptions_modify_handler, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE],
49460 userdata: cc, requestId);
49461}
49462
49463static void
49464UA_Client_Subscription_deleteInternal(UA_Client *client,
49465 UA_Client_Subscription *sub) {
49466 /* Remove the MonitoredItems */
49467 UA_Client_MonitoredItem *mon;
49468 UA_Client_MonitoredItem *mon_tmp;
49469 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp)
49470 MonitoredItem_delete(client, sub, mon);
49471
49472 /* Call the delete callback */
49473 if(sub->deleteCallback)
49474 sub->deleteCallback(client, sub->subscriptionId, sub->context);
49475
49476 /* Remove */
49477 LIST_REMOVE(sub, listEntry);
49478 UA_free(ptr: sub);
49479}
49480
49481static void
49482UA_Client_Subscription_processDelete(UA_Client *client,
49483 const UA_DeleteSubscriptionsRequest *request,
49484 const UA_DeleteSubscriptionsResponse *response) {
49485 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49486 return;
49487
49488 /* Check that the request and response size -- use the same index for both */
49489 if(request->subscriptionIdsSize != response->resultsSize)
49490 return;
49491
49492 for(size_t i = 0; i < request->subscriptionIdsSize; i++) {
49493 if(response->results[i] != UA_STATUSCODE_GOOD &&
49494 response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID)
49495 continue;
49496
49497 /* Get the Subscription */
49498 UA_Client_Subscription *sub =
49499 findSubscription(client, subscriptionId: request->subscriptionIds[i]);
49500 if(!sub) {
49501 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49502 msg: "No internal representation of subscription %" PRIu32,
49503 request->subscriptionIds[i]);
49504 continue;
49505 }
49506
49507 /* Delete the Subscription */
49508 UA_Client_Subscription_deleteInternal(client, sub);
49509 }
49510
49511}
49512
49513typedef struct {
49514 UA_DeleteSubscriptionsRequest request;
49515 UA_ClientAsyncServiceCallback userCallback;
49516 void *userData;
49517} DeleteSubscriptionCallback;
49518
49519static void
49520ua_Subscriptions_delete_handler(UA_Client *client, void *data, UA_UInt32 requestId,
49521 void *r) {
49522 UA_DeleteSubscriptionsResponse *response =
49523 (UA_DeleteSubscriptionsResponse *)r;
49524 DeleteSubscriptionCallback *dsc =
49525 (DeleteSubscriptionCallback*)data;
49526
49527 /* Delete */
49528 UA_Client_Subscription_processDelete(client, request: &dsc->request, response);
49529
49530 /* Userland Callback */
49531 dsc->userCallback(client, dsc->userData, requestId, response);
49532
49533 /* Cleanup */
49534 UA_DeleteSubscriptionsRequest_clear(p: &dsc->request);
49535 UA_free(ptr: dsc);
49536}
49537
49538UA_StatusCode
49539UA_Client_Subscriptions_delete_async(UA_Client *client,
49540 const UA_DeleteSubscriptionsRequest request,
49541 UA_ClientAsyncServiceCallback callback,
49542 void *userdata, UA_UInt32 *requestId) {
49543 /* Make a copy of the request that persists into the async callback */
49544 DeleteSubscriptionCallback *dsc =
49545 (DeleteSubscriptionCallback*)UA_malloc(size: sizeof(DeleteSubscriptionCallback));
49546 if(!dsc)
49547 return UA_STATUSCODE_BADOUTOFMEMORY;
49548 dsc->userCallback = callback;
49549 dsc->userData = userdata;
49550 UA_StatusCode res = UA_DeleteSubscriptionsRequest_copy(src: &request, dst: &dsc->request);
49551 if(res != UA_STATUSCODE_GOOD) {
49552 UA_free(ptr: dsc);
49553 return res;
49554 }
49555
49556 /* Make the async call */
49557 return __UA_Client_AsyncService(
49558 client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
49559 callback: ua_Subscriptions_delete_handler, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE],
49560 userdata: dsc, requestId);
49561}
49562
49563UA_DeleteSubscriptionsResponse
49564UA_Client_Subscriptions_delete(UA_Client *client,
49565 const UA_DeleteSubscriptionsRequest request) {
49566 /* Send the request */
49567 UA_DeleteSubscriptionsResponse response;
49568 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST],
49569 response: &response, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]);
49570
49571 /* Process */
49572 UA_Client_Subscription_processDelete(client, request: &request, response: &response);
49573 return response;
49574}
49575
49576UA_StatusCode
49577UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId) {
49578 UA_DeleteSubscriptionsRequest request;
49579 UA_DeleteSubscriptionsRequest_init(p: &request);
49580 request.subscriptionIds = &subscriptionId;
49581 request.subscriptionIdsSize = 1;
49582
49583 UA_DeleteSubscriptionsResponse response =
49584 UA_Client_Subscriptions_delete(client, request);
49585
49586 UA_StatusCode retval = response.responseHeader.serviceResult;
49587 if(retval != UA_STATUSCODE_GOOD) {
49588 UA_DeleteSubscriptionsResponse_clear(p: &response);
49589 return retval;
49590 }
49591
49592 if(response.resultsSize != 1) {
49593 UA_DeleteSubscriptionsResponse_clear(p: &response);
49594 return UA_STATUSCODE_BADINTERNALERROR;
49595 }
49596
49597 retval = response.results[0];
49598 UA_DeleteSubscriptionsResponse_clear(p: &response);
49599 return retval;
49600}
49601
49602/******************/
49603/* MonitoredItems */
49604/******************/
49605
49606static void
49607MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub,
49608 UA_Client_MonitoredItem *mon) {
49609 LIST_REMOVE(mon, listEntry);
49610 if(mon->deleteCallback)
49611 mon->deleteCallback(client, sub->subscriptionId, sub->context,
49612 mon->monitoredItemId, mon->context);
49613 UA_free(ptr: mon);
49614}
49615
49616typedef struct {
49617 void **contexts;
49618 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks;
49619 void **handlingCallbacks;
49620 UA_CreateMonitoredItemsRequest request;
49621
49622 /* Notify the user that the async callback was processed */
49623 UA_ClientAsyncServiceCallback userCallback;
49624 void *userData;
49625} MonitoredItems_CreateData;
49626
49627static void
49628MonitoredItems_CreateData_clear(UA_Client *client, MonitoredItems_CreateData *data) {
49629 UA_free(ptr: data->contexts);
49630 UA_free(ptr: data->deleteCallbacks);
49631 UA_free(ptr: data->handlingCallbacks);
49632 UA_CreateMonitoredItemsRequest_clear(p: &data->request);
49633}
49634
49635static void
49636ua_MonitoredItems_create(UA_Client *client, MonitoredItems_CreateData *data,
49637 UA_CreateMonitoredItemsResponse *response) {
49638 UA_CreateMonitoredItemsRequest *request = &data->request;
49639 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks = data->deleteCallbacks;
49640
49641 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: data->request.subscriptionId);
49642 if(!sub)
49643 goto cleanup;
49644
49645 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49646 goto cleanup;
49647
49648 if(response->resultsSize != request->itemsToCreateSize) {
49649 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
49650 goto cleanup;
49651 }
49652
49653 /* Add internally */
49654 for(size_t i = 0; i < request->itemsToCreateSize; i++) {
49655 if(response->results[i].statusCode != UA_STATUSCODE_GOOD) {
49656 if(deleteCallbacks[i])
49657 deleteCallbacks[i](client, sub->subscriptionId, sub->context,
49658 0, data->contexts[i]);
49659 continue;
49660 }
49661
49662 UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *)
49663 UA_malloc(size: sizeof(UA_Client_MonitoredItem));
49664 if(!newMon) {
49665 if(deleteCallbacks[i])
49666 deleteCallbacks[i](client, sub->subscriptionId, sub->context, 0,
49667 data->contexts[i]);
49668 continue;
49669 }
49670
49671 newMon->monitoredItemId = response->results[i].monitoredItemId;
49672 newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle;
49673 newMon->context = data->contexts[i];
49674 newMon->deleteCallback = deleteCallbacks[i];
49675 newMon->handler.dataChangeCallback =
49676 (UA_Client_DataChangeNotificationCallback)(uintptr_t)
49677 data->handlingCallbacks[i];
49678 newMon->isEventMonitoredItem =
49679 (request->itemsToCreate[i].itemToMonitor.attributeId ==
49680 UA_ATTRIBUTEID_EVENTNOTIFIER);
49681 LIST_INSERT_HEAD(&sub->monitoredItems, newMon, listEntry);
49682
49683 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49684 msg: "Subscription %" PRIu32
49685 " | Added a MonitoredItem with handle %" PRIu32,
49686 sub->subscriptionId, newMon->clientHandle);
49687 }
49688 return;
49689
49690 /* Adding failed */
49691 cleanup:
49692 for(size_t i = 0; i < request->itemsToCreateSize; i++) {
49693 if(deleteCallbacks[i])
49694 deleteCallbacks[i](client, data->request.subscriptionId,
49695 sub ? sub->context : NULL, 0, data->contexts[i]);
49696 }
49697}
49698
49699static void
49700ua_MonitoredItems_create_async_handler(UA_Client *client, void *d, UA_UInt32 requestId,
49701 void *r) {
49702 UA_CreateMonitoredItemsResponse *response = (UA_CreateMonitoredItemsResponse *)r;
49703 MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)d;
49704
49705 ua_MonitoredItems_create(client, data, response);
49706
49707 if(data->userCallback)
49708 data->userCallback(client, data->userData, requestId, response);
49709
49710 MonitoredItems_CreateData_clear(client, data);
49711 UA_free(ptr: data);
49712}
49713
49714static UA_StatusCode
49715MonitoredItems_CreateData_prepare(UA_Client *client,
49716 const UA_CreateMonitoredItemsRequest *request,
49717 void **contexts, void **handlingCallbacks,
49718 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49719 MonitoredItems_CreateData *data) {
49720 /* Align arrays and copy over */
49721 UA_StatusCode retval = UA_STATUSCODE_BADOUTOFMEMORY;
49722 data->contexts = (void **)UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *));
49723 if(!data->contexts)
49724 goto cleanup;
49725 if(contexts)
49726 memcpy(dest: data->contexts, src: contexts, n: request->itemsToCreateSize * sizeof(void *));
49727
49728 data->deleteCallbacks = (UA_Client_DeleteMonitoredItemCallback *)
49729 UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(UA_Client_DeleteMonitoredItemCallback));
49730 if(!data->deleteCallbacks)
49731 goto cleanup;
49732 if(deleteCallbacks)
49733 memcpy(dest: data->deleteCallbacks, src: deleteCallbacks,
49734 n: request->itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback));
49735
49736 data->handlingCallbacks = (void **)
49737 UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *));
49738 if(!data->handlingCallbacks)
49739 goto cleanup;
49740 if(handlingCallbacks)
49741 memcpy(dest: data->handlingCallbacks, src: handlingCallbacks,
49742 n: request->itemsToCreateSize * sizeof(void *));
49743
49744 retval = UA_CreateMonitoredItemsRequest_copy(src: request, dst: &data->request);
49745 if(retval != UA_STATUSCODE_GOOD)
49746 goto cleanup;
49747
49748 /* Set the clientHandle */
49749 for(size_t i = 0; i < data->request.itemsToCreateSize; i++)
49750 data->request.itemsToCreate[i].requestedParameters.clientHandle =
49751 ++client->monitoredItemHandles;
49752
49753 return UA_STATUSCODE_GOOD;
49754
49755cleanup:
49756 MonitoredItems_CreateData_clear(client, data);
49757 return retval;
49758}
49759
49760static void
49761ua_Client_MonitoredItems_create(UA_Client *client,
49762 const UA_CreateMonitoredItemsRequest *request,
49763 void **contexts, void **handlingCallbacks,
49764 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49765 UA_CreateMonitoredItemsResponse *response) {
49766 UA_CreateMonitoredItemsResponse_init(p: response);
49767
49768 if(!request->itemsToCreateSize) {
49769 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
49770 return;
49771 }
49772
49773 /* Test if the subscription is valid */
49774 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request->subscriptionId);
49775 if(!sub) {
49776 response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49777 return;
49778 }
49779
49780 MonitoredItems_CreateData data;
49781 memset(s: &data, c: 0, n: sizeof(MonitoredItems_CreateData));
49782
49783 UA_StatusCode res =
49784 MonitoredItems_CreateData_prepare(client, request, contexts, handlingCallbacks,
49785 deleteCallbacks, data: &data);
49786 if(res != UA_STATUSCODE_GOOD) {
49787 response->responseHeader.serviceResult = res;
49788 return;
49789 }
49790
49791 /* Call the service. Use data->request as it contains the client handle
49792 * information. */
49793 __UA_Client_Service(client, request: &data.request,
49794 requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
49795 response, responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]);
49796
49797 /* Add internal representation */
49798 ua_MonitoredItems_create(client, data: &data, response);
49799
49800 MonitoredItems_CreateData_clear(client, data: &data);
49801}
49802
49803static UA_StatusCode
49804ua_Client_MonitoredItems_createDataChanges_async(
49805 UA_Client *client, const UA_CreateMonitoredItemsRequest request, void **contexts,
49806 void **callbacks, UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49807 UA_ClientAsyncServiceCallback createCallback, void *userdata, UA_UInt32 *requestId) {
49808 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
49809 if(!sub)
49810 return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
49811
49812 MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)
49813 UA_calloc(nmemb: 1, size: sizeof(MonitoredItems_CreateData));
49814 if(!data)
49815 return UA_STATUSCODE_BADOUTOFMEMORY;
49816 data->userCallback = createCallback;
49817 data->userData = userdata;
49818
49819 UA_StatusCode res = MonitoredItems_CreateData_prepare(
49820 client, request: &request, contexts, handlingCallbacks: callbacks, deleteCallbacks, data);
49821 if(res != UA_STATUSCODE_GOOD) {
49822 UA_free(ptr: data);
49823 return res;
49824 }
49825
49826 return __UA_Client_AsyncService(
49827 client, request: &data->request, requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST],
49828 callback: ua_MonitoredItems_create_async_handler,
49829 responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], userdata: data, requestId);
49830}
49831
49832UA_CreateMonitoredItemsResponse
49833UA_Client_MonitoredItems_createDataChanges(UA_Client *client,
49834 const UA_CreateMonitoredItemsRequest request,
49835 void **contexts,
49836 UA_Client_DataChangeNotificationCallback *callbacks,
49837 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) {
49838 UA_CreateMonitoredItemsResponse response;
49839 ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callbacks,
49840 deleteCallbacks, response: &response);
49841 return response;
49842}
49843
49844UA_StatusCode
49845UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client,
49846 const UA_CreateMonitoredItemsRequest request,
49847 void **contexts,
49848 UA_Client_DataChangeNotificationCallback *callbacks,
49849 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49850 UA_ClientAsyncServiceCallback createCallback,
49851 void *userdata, UA_UInt32 *requestId) {
49852 return ua_Client_MonitoredItems_createDataChanges_async(
49853 client, request, contexts, callbacks: (void **)callbacks, deleteCallbacks, createCallback,
49854 userdata, requestId);
49855}
49856
49857UA_MonitoredItemCreateResult
49858UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId,
49859 UA_TimestampsToReturn timestampsToReturn,
49860 const UA_MonitoredItemCreateRequest item,
49861 void *context,
49862 UA_Client_DataChangeNotificationCallback callback,
49863 UA_Client_DeleteMonitoredItemCallback deleteCallback) {
49864 UA_CreateMonitoredItemsRequest request;
49865 UA_CreateMonitoredItemsRequest_init(p: &request);
49866 request.subscriptionId = subscriptionId;
49867 request.timestampsToReturn = timestampsToReturn;
49868 request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
49869 request.itemsToCreateSize = 1;
49870 UA_CreateMonitoredItemsResponse response =
49871 UA_Client_MonitoredItems_createDataChanges(client, request, contexts: &context,
49872 callbacks: &callback, deleteCallbacks: &deleteCallback);
49873 UA_MonitoredItemCreateResult result;
49874 UA_MonitoredItemCreateResult_init(p: &result);
49875 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49876 result.statusCode = response.responseHeader.serviceResult;
49877
49878 if(result.statusCode == UA_STATUSCODE_GOOD &&
49879 response.resultsSize != 1)
49880 result.statusCode = UA_STATUSCODE_BADINTERNALERROR;
49881
49882 if(result.statusCode == UA_STATUSCODE_GOOD)
49883 UA_MonitoredItemCreateResult_copy(src: &response.results[0] , dst: &result);
49884 UA_CreateMonitoredItemsResponse_clear(p: &response);
49885 return result;
49886}
49887
49888UA_CreateMonitoredItemsResponse
49889UA_Client_MonitoredItems_createEvents(UA_Client *client,
49890 const UA_CreateMonitoredItemsRequest request,
49891 void **contexts,
49892 UA_Client_EventNotificationCallback *callback,
49893 UA_Client_DeleteMonitoredItemCallback *deleteCallback) {
49894 UA_CreateMonitoredItemsResponse response;
49895 ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callback,
49896 deleteCallbacks: deleteCallback, response: &response);
49897 return response;
49898}
49899
49900/* Monitor the EventNotifier attribute only */
49901UA_StatusCode
49902UA_Client_MonitoredItems_createEvents_async(UA_Client *client,
49903 const UA_CreateMonitoredItemsRequest request,
49904 void **contexts,
49905 UA_Client_EventNotificationCallback *callbacks,
49906 UA_Client_DeleteMonitoredItemCallback *deleteCallbacks,
49907 UA_ClientAsyncServiceCallback createCallback,
49908 void *userdata, UA_UInt32 *requestId) {
49909 return ua_Client_MonitoredItems_createDataChanges_async(
49910 client, request, contexts, callbacks: (void **)callbacks, deleteCallbacks, createCallback,
49911 userdata, requestId);
49912}
49913
49914UA_MonitoredItemCreateResult
49915UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId,
49916 UA_TimestampsToReturn timestampsToReturn,
49917 const UA_MonitoredItemCreateRequest item, void *context,
49918 UA_Client_EventNotificationCallback callback,
49919 UA_Client_DeleteMonitoredItemCallback deleteCallback) {
49920 UA_CreateMonitoredItemsRequest request;
49921 UA_CreateMonitoredItemsRequest_init(p: &request);
49922 request.subscriptionId = subscriptionId;
49923 request.timestampsToReturn = timestampsToReturn;
49924 request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item;
49925 request.itemsToCreateSize = 1;
49926 UA_CreateMonitoredItemsResponse response =
49927 UA_Client_MonitoredItems_createEvents(client, request, contexts: &context,
49928 callback: &callback, deleteCallback: &deleteCallback);
49929 UA_StatusCode retval = response.responseHeader.serviceResult;
49930 UA_MonitoredItemCreateResult result;
49931 UA_MonitoredItemCreateResult_init(p: &result);
49932 if(retval != UA_STATUSCODE_GOOD) {
49933 UA_CreateMonitoredItemsResponse_clear(p: &response);
49934 result.statusCode = retval;
49935 return result;
49936 }
49937 UA_MonitoredItemCreateResult_copy(src: response.results , dst: &result);
49938 UA_CreateMonitoredItemsResponse_clear(p: &response);
49939 return result;
49940}
49941
49942static void
49943ua_MonitoredItems_delete(UA_Client *client, UA_Client_Subscription *sub,
49944 const UA_DeleteMonitoredItemsRequest *request,
49945 const UA_DeleteMonitoredItemsResponse *response) {
49946#ifdef __clang_analyzer__
49947 return;
49948#endif
49949
49950 /* Loop over deleted MonitoredItems */
49951 for(size_t i = 0; i < response->resultsSize; i++) {
49952 if(response->results[i] != UA_STATUSCODE_GOOD &&
49953 response->results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) {
49954 continue;
49955 }
49956
49957 /* Delete the internal representation */
49958 UA_Client_MonitoredItem *mon;
49959 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
49960 if(mon->monitoredItemId == request->monitoredItemIds[i]) {
49961 MonitoredItem_delete(client, sub, mon);
49962 break;
49963 }
49964 }
49965 }
49966}
49967
49968static void
49969ua_MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId,
49970 void *r) {
49971 CustomCallback *cc = (CustomCallback *)d;
49972 UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r;
49973 UA_DeleteMonitoredItemsRequest *request =
49974 (UA_DeleteMonitoredItemsRequest *)cc->clientData;
49975 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
49976 goto cleanup;
49977
49978 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request->subscriptionId);
49979 if(!sub) {
49980 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
49981 msg: "No internal representation of subscription %" PRIu32,
49982 request->subscriptionId);
49983 goto cleanup;
49984 }
49985
49986 /* Delete MonitoredItems from the internal representation */
49987 ua_MonitoredItems_delete(client, sub, request, response);
49988
49989cleanup:
49990 if(cc->userCallback)
49991 cc->userCallback(client, cc->userData, requestId, response);
49992 UA_DeleteMonitoredItemsRequest_delete(p: request);
49993 UA_free(ptr: cc);
49994}
49995
49996UA_DeleteMonitoredItemsResponse
49997UA_Client_MonitoredItems_delete(UA_Client *client,
49998 const UA_DeleteMonitoredItemsRequest request) {
49999 /* Send the request */
50000 UA_DeleteMonitoredItemsResponse response;
50001 __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
50002 response: &response, responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]);
50003
50004 /* A problem occured remote? */
50005 if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
50006 return response;
50007
50008 /* Find the internal subscription representation */
50009 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId);
50010 if(!sub) {
50011 UA_LOG_INFO(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50012 msg: "No internal representation of subscription %" PRIu32,
50013 request.subscriptionId);
50014 return response;
50015 }
50016
50017 /* Remove MonitoredItems in the internal representation */
50018 ua_MonitoredItems_delete(client, sub, request: &request, response: &response);
50019 return response;
50020}
50021
50022UA_StatusCode
50023UA_Client_MonitoredItems_delete_async(UA_Client *client,
50024 const UA_DeleteMonitoredItemsRequest request,
50025 UA_ClientAsyncServiceCallback callback,
50026 void *userdata, UA_UInt32 *requestId) {
50027 /* Send the request */
50028 CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback));
50029 if(!cc)
50030 return UA_STATUSCODE_BADOUTOFMEMORY;
50031
50032 UA_DeleteMonitoredItemsRequest *req_copy = UA_DeleteMonitoredItemsRequest_new();
50033 if(!req_copy) {
50034 UA_free(ptr: cc);
50035 return UA_STATUSCODE_BADOUTOFMEMORY;
50036 }
50037
50038 UA_DeleteMonitoredItemsRequest_copy(src: &request, dst: req_copy);
50039 cc->clientData = req_copy;
50040 cc->userCallback = callback;
50041 cc->userData = userdata;
50042
50043 return __UA_Client_AsyncService(
50044 client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST],
50045 callback: ua_MonitoredItems_delete_handler,
50046 responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], userdata: cc, requestId);
50047}
50048
50049UA_StatusCode
50050UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId,
50051 UA_UInt32 monitoredItemId) {
50052 UA_DeleteMonitoredItemsRequest request;
50053 UA_DeleteMonitoredItemsRequest_init(p: &request);
50054 request.subscriptionId = subscriptionId;
50055 request.monitoredItemIds = &monitoredItemId;
50056 request.monitoredItemIdsSize = 1;
50057
50058 UA_DeleteMonitoredItemsResponse response =
50059 UA_Client_MonitoredItems_delete(client, request);
50060
50061 UA_StatusCode retval = response.responseHeader.serviceResult;
50062 if(retval != UA_STATUSCODE_GOOD) {
50063 UA_DeleteMonitoredItemsResponse_clear(p: &response);
50064 return retval;
50065 }
50066
50067 if(response.resultsSize != 1) {
50068 UA_DeleteMonitoredItemsResponse_clear(p: &response);
50069 return UA_STATUSCODE_BADINTERNALERROR;
50070 }
50071
50072 retval = response.results[0];
50073 UA_DeleteMonitoredItemsResponse_clear(p: &response);
50074 return retval;
50075}
50076
50077UA_ModifyMonitoredItemsResponse
50078UA_Client_MonitoredItems_modify(UA_Client *client,
50079 const UA_ModifyMonitoredItemsRequest request) {
50080 UA_ModifyMonitoredItemsResponse response;
50081
50082 UA_Client_Subscription *sub;
50083 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
50084 if (sub->subscriptionId == request.subscriptionId)
50085 break;
50086 }
50087
50088 if (!sub) {
50089 UA_ModifyMonitoredItemsResponse_init(p: &response);
50090 response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID;
50091 return response;
50092 }
50093
50094 UA_ModifyMonitoredItemsRequest modifiedRequest;
50095 UA_ModifyMonitoredItemsRequest_copy(src: &request, dst: &modifiedRequest);
50096
50097 for (size_t i = 0; i < modifiedRequest.itemsToModifySize; ++i) {
50098 UA_Client_MonitoredItem *mon;
50099 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
50100 if(mon->monitoredItemId == modifiedRequest.itemsToModify[i].monitoredItemId) {
50101 modifiedRequest.itemsToModify[i].requestedParameters.clientHandle = mon->clientHandle;
50102 break;
50103 }
50104 }
50105 }
50106
50107 __UA_Client_Service(client,
50108 request: &modifiedRequest, requestType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST],
50109 response: &response, responseType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]);
50110
50111 UA_ModifyMonitoredItemsRequest_clear(p: &modifiedRequest);
50112 return response;
50113}
50114
50115/*************************************/
50116/* Async Processing of Notifications */
50117/*************************************/
50118
50119/* Assume the request is already initialized */
50120UA_StatusCode
50121UA_Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request) {
50122 /* Count acks */
50123 UA_Client_NotificationsAckNumber *ack;
50124 LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry)
50125 ++request->subscriptionAcknowledgementsSize;
50126
50127 /* Create the array. Returns a sentinel pointer if the length is zero. */
50128 request->subscriptionAcknowledgements = (UA_SubscriptionAcknowledgement*)
50129 UA_Array_new(size: request->subscriptionAcknowledgementsSize,
50130 type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]);
50131 if(!request->subscriptionAcknowledgements) {
50132 request->subscriptionAcknowledgementsSize = 0;
50133 return UA_STATUSCODE_BADOUTOFMEMORY;
50134 }
50135
50136 size_t i = 0;
50137 UA_Client_NotificationsAckNumber *ack_tmp;
50138 LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, ack_tmp) {
50139 request->subscriptionAcknowledgements[i].sequenceNumber = ack->subAck.sequenceNumber;
50140 request->subscriptionAcknowledgements[i].subscriptionId = ack->subAck.subscriptionId;
50141 ++i;
50142 LIST_REMOVE(ack, listEntry);
50143 UA_free(ptr: ack);
50144 }
50145 return UA_STATUSCODE_GOOD;
50146}
50147
50148/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) */
50149/* The value 0 is never used for the sequence number */
50150static UA_UInt32
50151UA_Client_Subscriptions_nextSequenceNumber(UA_UInt32 sequenceNumber) {
50152 UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
50153 if(nextSequenceNumber == 0)
50154 nextSequenceNumber = 1;
50155 return nextSequenceNumber;
50156}
50157
50158static void
50159processDataChangeNotification(UA_Client *client, UA_Client_Subscription *sub,
50160 UA_DataChangeNotification *dataChangeNotification) {
50161 for(size_t j = 0; j < dataChangeNotification->monitoredItemsSize; ++j) {
50162 UA_MonitoredItemNotification *min = &dataChangeNotification->monitoredItems[j];
50163
50164 /* Find the MonitoredItem */
50165 UA_Client_MonitoredItem *mon;
50166 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
50167 if(mon->clientHandle == min->clientHandle)
50168 break;
50169 }
50170
50171 if(!mon) {
50172 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50173 msg: "Could not process a notification with clienthandle %" PRIu32
50174 " on subscription %" PRIu32, min->clientHandle, sub->subscriptionId);
50175 continue;
50176 }
50177
50178 if(mon->isEventMonitoredItem) {
50179 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50180 msg: "MonitoredItem is configured for Events. But received a "
50181 "DataChangeNotification.");
50182 continue;
50183 }
50184
50185 if(mon->handler.dataChangeCallback) {
50186 mon->handler.dataChangeCallback(client, sub->subscriptionId, sub->context,
50187 mon->monitoredItemId, mon->context,
50188 &min->value);
50189 }
50190 }
50191}
50192
50193static void
50194processEventNotification(UA_Client *client, UA_Client_Subscription *sub,
50195 UA_EventNotificationList *eventNotificationList) {
50196 for(size_t j = 0; j < eventNotificationList->eventsSize; ++j) {
50197 UA_EventFieldList *eventFieldList = &eventNotificationList->events[j];
50198
50199 /* Find the MonitoredItem */
50200 UA_Client_MonitoredItem *mon;
50201 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
50202 if(mon->clientHandle == eventFieldList->clientHandle)
50203 break;
50204 }
50205
50206 if(!mon) {
50207 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50208 msg: "Could not process a notification with clienthandle %" PRIu32
50209 " on subscription %" PRIu32, eventFieldList->clientHandle,
50210 sub->subscriptionId);
50211 continue;
50212 }
50213
50214 if(!mon->isEventMonitoredItem) {
50215 UA_LOG_DEBUG(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50216 msg: "MonitoredItem is configured for DataChanges. But received a "
50217 "EventNotification.");
50218 continue;
50219 }
50220
50221 mon->handler.eventCallback(client, sub->subscriptionId, sub->context,
50222 mon->monitoredItemId, mon->context,
50223 eventFieldList->eventFieldsSize,
50224 eventFieldList->eventFields);
50225 }
50226}
50227
50228static void
50229processNotificationMessage(UA_Client *client, UA_Client_Subscription *sub,
50230 UA_ExtensionObject *msg) {
50231 if(msg->encoding != UA_EXTENSIONOBJECT_DECODED)
50232 return;
50233
50234 /* Handle DataChangeNotification */
50235 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]) {
50236 UA_DataChangeNotification *dataChangeNotification =
50237 (UA_DataChangeNotification *)msg->content.decoded.data;
50238 processDataChangeNotification(client, sub, dataChangeNotification);
50239 return;
50240 }
50241
50242 /* Handle EventNotification */
50243 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]) {
50244 UA_EventNotificationList *eventNotificationList =
50245 (UA_EventNotificationList *)msg->content.decoded.data;
50246 processEventNotification(client, sub, eventNotificationList);
50247 return;
50248 }
50249
50250 /* Handle StatusChangeNotification */
50251 if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]) {
50252 if(sub->statusChangeCallback) {
50253 sub->statusChangeCallback(client, sub->subscriptionId, sub->context,
50254 (UA_StatusChangeNotification*)msg->content.decoded.data);
50255 } else {
50256 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50257 msg: "Dropped a StatusChangeNotification since no "
50258 "callback is registered");
50259 }
50260 return;
50261 }
50262
50263 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50264 msg: "Unknown notification message type");
50265}
50266
50267static void
50268UA_Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequest *request,
50269 UA_PublishResponse *response) {
50270 UA_NotificationMessage *msg = &response->notificationMessage;
50271
50272 client->currentlyOutStandingPublishRequests--;
50273
50274 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS) {
50275 if(client->config.outStandingPublishRequests > 1) {
50276 client->config.outStandingPublishRequests--;
50277 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50278 msg: "Too many publishrequest, reduce outStandingPublishRequests "
50279 "to %" PRId16, client->config.outStandingPublishRequests);
50280 } else {
50281 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50282 msg: "Too many publishrequest when outStandingPublishRequests = 1");
50283 UA_Client_Subscriptions_deleteSingle(client, subscriptionId: response->subscriptionId);
50284 }
50285 return;
50286 }
50287
50288 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSHUTDOWN)
50289 return;
50290
50291 if(!LIST_FIRST(&client->subscriptions)) {
50292 response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION;
50293 return;
50294 }
50295
50296 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) {
50297 if(client->sessionState != UA_SESSIONSTATE_ACTIVATED) {
50298 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50299 msg: "Received Publish Response with code %s",
50300 UA_StatusCode_name(code: response->responseHeader.serviceResult));
50301 UA_Client_Subscription* sub = findSubscription(client, subscriptionId: response->subscriptionId);
50302 if (sub != NULL)
50303 UA_Client_Subscription_deleteInternal(client, sub);
50304 }
50305 return;
50306 }
50307
50308 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID) {
50309 UA_Client_disconnect(client); /* TODO: This should be handled before the process callback */
50310 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50311 msg: "Received BadSessionIdInvalid");
50312 return;
50313 }
50314
50315 if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) {
50316 if (client->config.subscriptionInactivityCallback) {
50317 UA_Client_Subscription* sub = findSubscription(client, subscriptionId: response->subscriptionId);
50318 if (sub != NULL)
50319 client->config.subscriptionInactivityCallback(client, sub->subscriptionId,
50320 sub->context);
50321 }
50322 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50323 msg: "Received Timeout for Publish Response");
50324 return;
50325 }
50326
50327 if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
50328 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50329 msg: "Received Publish Response with code %s",
50330 UA_StatusCode_name(code: response->responseHeader.serviceResult));
50331 return;
50332 }
50333
50334 UA_Client_Subscription *sub = findSubscription(client, subscriptionId: response->subscriptionId);
50335 if(!sub) {
50336 response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
50337 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50338 msg: "Received Publish Response for a non-existant subscription");
50339 return;
50340 }
50341
50342 sub->lastActivity = UA_DateTime_nowMonotonic();
50343
50344 /* Detect missing message - OPC Unified Architecture, Part 4 5.13.1.1 e) */
50345 if(UA_Client_Subscriptions_nextSequenceNumber(sequenceNumber: sub->sequenceNumber) != msg->sequenceNumber) {
50346 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50347 msg: "Invalid subscription sequence number: expected %" PRIu32
50348 " but got %" PRIu32,
50349 UA_Client_Subscriptions_nextSequenceNumber(sequenceNumber: sub->sequenceNumber),
50350 msg->sequenceNumber);
50351 /* This is an error. But we do not abort the connection. Some server
50352 * SDKs misbehave from time to time and send out-of-order sequence
50353 * numbers. (Probably some multi-threading synchronization issue.) */
50354 /* UA_Client_disconnect(client);
50355 return; */
50356 }
50357 /* According to f), a keep-alive message contains no notifications and has
50358 * the sequence number of the next NotificationMessage that is to be sent =>
50359 * More than one consecutive keep-alive message or a NotificationMessage
50360 * following a keep-alive message will share the same sequence number. */
50361 if (msg->notificationDataSize)
50362 sub->sequenceNumber = msg->sequenceNumber;
50363
50364 /* Process the notification messages */
50365 for(size_t k = 0; k < msg->notificationDataSize; ++k)
50366 processNotificationMessage(client, sub, msg: &msg->notificationData[k]);
50367
50368 /* Add to the list of pending acks */
50369 for(size_t i = 0; i < response->availableSequenceNumbersSize; i++) {
50370 if(response->availableSequenceNumbers[i] != msg->sequenceNumber)
50371 continue;
50372 UA_Client_NotificationsAckNumber *tmpAck = (UA_Client_NotificationsAckNumber*)
50373 UA_malloc(size: sizeof(UA_Client_NotificationsAckNumber));
50374 if(!tmpAck) {
50375 UA_LOG_WARNING(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50376 msg: "Not enough memory to store the acknowledgement for a publish "
50377 "message on subscription %" PRIu32, sub->subscriptionId);
50378 break;
50379 }
50380 tmpAck->subAck.sequenceNumber = msg->sequenceNumber;
50381 tmpAck->subAck.subscriptionId = sub->subscriptionId;
50382 LIST_INSERT_HEAD(&client->pendingNotificationsAcks, tmpAck, listEntry);
50383 break;
50384 }
50385}
50386
50387static void
50388processPublishResponseAsync(UA_Client *client, void *userdata,
50389 UA_UInt32 requestId, void *response) {
50390 UA_PublishRequest *req = (UA_PublishRequest*)userdata;
50391 UA_PublishResponse *res = (UA_PublishResponse*)response;
50392
50393 /* Process the response */
50394 UA_Client_Subscriptions_processPublishResponse(client, request: req, response: res);
50395
50396 /* Delete the cached request */
50397 UA_PublishRequest_delete(p: req);
50398
50399 /* Fill up the outstanding publish requests */
50400 UA_Client_Subscriptions_backgroundPublish(client);
50401}
50402
50403void
50404UA_Client_Subscriptions_clean(UA_Client *client) {
50405 UA_Client_NotificationsAckNumber *n;
50406 UA_Client_NotificationsAckNumber *tmp;
50407 LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) {
50408 LIST_REMOVE(n, listEntry);
50409 UA_free(ptr: n);
50410 }
50411
50412 UA_Client_Subscription *sub;
50413 UA_Client_Subscription *tmps;
50414 LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps)
50415 UA_Client_Subscription_deleteInternal(client, sub); /* force local removal */
50416
50417 client->monitoredItemHandles = 0;
50418}
50419
50420void
50421UA_Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client) {
50422 if(client->sessionState < UA_SESSIONSTATE_ACTIVATED)
50423 return;
50424
50425 /* Is the lack of responses the client's fault? */
50426 if(client->currentlyOutStandingPublishRequests == 0)
50427 return;
50428
50429 UA_Client_Subscription *sub;
50430 LIST_FOREACH(sub, &client->subscriptions, listEntry) {
50431 UA_DateTime maxSilence = (UA_DateTime)
50432 ((sub->publishingInterval * sub->maxKeepAliveCount) +
50433 client->config.timeout) * UA_DATETIME_MSEC;
50434 if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic()) {
50435 /* Reset activity */
50436 sub->lastActivity = UA_DateTime_nowMonotonic();
50437
50438 if(client->config.subscriptionInactivityCallback)
50439 client->config.subscriptionInactivityCallback(client, sub->subscriptionId,
50440 sub->context);
50441 UA_LOG_ERROR(logger: &client->config.logger, category: UA_LOGCATEGORY_CLIENT,
50442 msg: "Inactivity for Subscription %" PRIu32 ".", sub->subscriptionId);
50443 }
50444 }
50445}
50446
50447void
50448UA_Client_Subscriptions_backgroundPublish(UA_Client *client) {
50449 if(client->sessionState != UA_SESSIONSTATE_ACTIVATED)
50450 return;
50451
50452 /* The session must have at least one subscription */
50453 if(!LIST_FIRST(&client->subscriptions))
50454 return;
50455
50456 while(client->currentlyOutStandingPublishRequests < client->config.outStandingPublishRequests) {
50457 UA_PublishRequest *request = UA_PublishRequest_new();
50458 if(!request)
50459 return;
50460
50461 request->requestHeader.timeoutHint=60000;
50462 UA_StatusCode retval = UA_Client_preparePublishRequest(client, request);
50463 if(retval != UA_STATUSCODE_GOOD) {
50464 UA_PublishRequest_delete(p: request);
50465 return;
50466 }
50467
50468 UA_UInt32 requestId;
50469 client->currentlyOutStandingPublishRequests++;
50470
50471 /* Disable the timeout, it is treat in
50472 * UA_Client_Subscriptions_backgroundPublishInactivityCheck */
50473 retval = __UA_Client_AsyncServiceEx(client, request,
50474 requestType: &UA_TYPES[UA_TYPES_PUBLISHREQUEST],
50475 callback: processPublishResponseAsync,
50476 responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE],
50477 userdata: (void*)request, requestId: &requestId, timeout: 0);
50478 if(retval != UA_STATUSCODE_GOOD) {
50479 UA_PublishRequest_delete(p: request);
50480 return;
50481 }
50482 }
50483}
50484
50485#endif /* UA_ENABLE_SUBSCRIPTIONS */
50486
50487/**** amalgamated original file "/deps/libc_time.c" ****/
50488
50489/* Originally released by the musl project (http://www.musl-libc.org/) under the
50490 * MIT license. Taken from the file /src/time/__secs_to_tm.c */
50491
50492#include <limits.h>
50493
50494/* 2000-03-01 (mod 400 year, immediately after feb29 */
50495#define LEAPOCH (946684800LL + 86400*(31+29))
50496
50497#define DAYS_PER_400Y (365*400 + 97)
50498#define DAYS_PER_100Y (365*100 + 24)
50499#define DAYS_PER_4Y (365*4 + 1)
50500
50501int __secs_to_tm(long long t, struct mytm *tm) {
50502 long long days, secs, years;
50503 int remdays, remsecs, remyears;
50504 int qc_cycles, c_cycles, q_cycles;
50505 int months;
50506 static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29};
50507
50508 /* Reject time_t values whose year would overflow int */
50509 if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
50510 return -1;
50511
50512 secs = t - LEAPOCH;
50513 days = secs / 86400LL;
50514 remsecs = (int)(secs % 86400);
50515 if (remsecs < 0) {
50516 remsecs += 86400;
50517 --days;
50518 }
50519
50520 qc_cycles = (int)(days / DAYS_PER_400Y);
50521 remdays = (int)(days % DAYS_PER_400Y);
50522 if (remdays < 0) {
50523 remdays += DAYS_PER_400Y;
50524 --qc_cycles;
50525 }
50526
50527 c_cycles = remdays / DAYS_PER_100Y;
50528 if (c_cycles == 4) --c_cycles;
50529 remdays -= c_cycles * DAYS_PER_100Y;
50530
50531 q_cycles = remdays / DAYS_PER_4Y;
50532 if (q_cycles == 25) --q_cycles;
50533 remdays -= q_cycles * DAYS_PER_4Y;
50534
50535 remyears = remdays / 365;
50536 if (remyears == 4) --remyears;
50537 remdays -= remyears * 365;
50538
50539 years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
50540
50541 for (months=0; days_in_month[months] <= remdays; ++months)
50542 remdays -= days_in_month[months];
50543
50544 if (years+100 > INT_MAX || years+100 < INT_MIN)
50545 return -1;
50546
50547 tm->tm_year = (int)(years + 100);
50548 tm->tm_mon = months + 2;
50549 if (tm->tm_mon >= 12) {
50550 tm->tm_mon -=12;
50551 ++tm->tm_year;
50552 }
50553 tm->tm_mday = remdays + 1;
50554 tm->tm_hour = remsecs / 3600;
50555 tm->tm_min = remsecs / 60 % 60;
50556 tm->tm_sec = remsecs % 60;
50557
50558 return 0;
50559}
50560
50561static const int secs_through_month[] =
50562 {0, 31*86400, 59*86400, 90*86400,
50563 120*86400, 151*86400, 181*86400, 212*86400,
50564 243*86400, 273*86400, 304*86400, 334*86400 };
50565
50566static int
50567__month_to_secs(int month, int is_leap) {
50568 int t = secs_through_month[month];
50569 if (is_leap && month >= 2)
50570 t+=86400;
50571 return t;
50572}
50573
50574static long long
50575__year_to_secs(const long long year, int *is_leap) {
50576 int cycles, centuries, leaps, rem;
50577 int is_leap_val = 0;
50578 if (!is_leap) {
50579 is_leap = &is_leap_val;
50580 }
50581 cycles = (int)((year-100) / 400);
50582 rem = (int)((year-100) % 400);
50583 if (rem < 0) {
50584 cycles--;
50585 rem += 400;
50586 }
50587 if (!rem) {
50588 *is_leap = 1;
50589 centuries = 0;
50590 leaps = 0;
50591 } else {
50592 if (rem >= 200) {
50593 if (rem >= 300) centuries = 3, rem -= 300;
50594 else centuries = 2, rem -= 200;
50595 } else {
50596 if (rem >= 100) centuries = 1, rem -= 100;
50597 else centuries = 0;
50598 }
50599 if (!rem) {
50600 *is_leap = 0;
50601 leaps = 0;
50602 } else {
50603 leaps = (rem / (int)4U);
50604 rem %= (int)4U;
50605 *is_leap = !rem;
50606 }
50607 }
50608
50609 leaps += 97*cycles + 24*centuries - *is_leap;
50610
50611 return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
50612}
50613
50614long long __tm_to_secs(const struct mytm *tm) {
50615 int is_leap;
50616 long long year = tm->tm_year;
50617 int month = tm->tm_mon;
50618 if (month >= 12 || month < 0) {
50619 int adj = month / 12;
50620 month %= 12;
50621 if (month < 0) {
50622 adj--;
50623 month += 12;
50624 }
50625 year += adj;
50626 }
50627 long long t = __year_to_secs(year, is_leap: &is_leap);
50628 t += __month_to_secs(month, is_leap);
50629 t += 86400LL * (tm->tm_mday-1);
50630 t += 3600LL * tm->tm_hour;
50631 t += 60LL * tm->tm_min;
50632 t += tm->tm_sec;
50633 return t;
50634}
50635
50636/**** amalgamated original file "/deps/pcg_basic.c" ****/
50637
50638/*
50639 * PCG Random Number Generation for C.
50640 *
50641 * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
50642 *
50643 * Licensed under the Apache License, Version 2.0 (the "License");
50644 * you may not use this file except in compliance with the License.
50645 * You may obtain a copy of the License at
50646 *
50647 * http://www.apache.org/licenses/LICENSE-2.0
50648 *
50649 * Unless required by applicable law or agreed to in writing, software
50650 * distributed under the License is distributed on an "AS IS" BASIS,
50651 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50652 * See the License for the specific language governing permissions and
50653 * limitations under the License.
50654 *
50655 * For additional information about the PCG random number generation scheme,
50656 * including its license and other licensing options, visit
50657 *
50658 * http://www.pcg-random.org
50659 */
50660
50661
50662void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq) {
50663 rng->state = 0U;
50664 rng->inc = (initseq << 1u) | 1u;
50665 pcg32_random_r(rng);
50666 rng->state += initial_state;
50667 pcg32_random_r(rng);
50668}
50669
50670uint32_t pcg32_random_r(pcg32_random_t* rng) {
50671 uint64_t oldstate = rng->state;
50672 rng->state = oldstate * 6364136223846793005ULL + rng->inc;
50673 uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);
50674 uint32_t rot = (uint32_t)(oldstate >> 59u);
50675 return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); /* was (xorshifted >> rot) | (xorshifted << ((-rot) & 31)) */
50676}
50677
50678/**** amalgamated original file "/deps/base64.c" ****/
50679
50680/*
50681 * Base64 encoding: Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi>
50682 * This software may be distributed under the terms of the BSD license.
50683 *
50684 * Base64 decoding: Copyright (c) 2016, polfosol
50685 * Posted at https://stackoverflow.com/a/37109258 under the CC-BY-SA Creative
50686 * Commons license.
50687 */
50688
50689
50690static const unsigned char base64_table[65] =
50691 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
50692
50693unsigned char *
50694UA_base64(const unsigned char *src, size_t len, size_t *out_len) {
50695 if(len == 0) {
50696 *out_len = 0;
50697 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50698 }
50699
50700 size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */
50701 if(olen < len)
50702 return NULL; /* integer overflow */
50703
50704 unsigned char *out = (unsigned char*)UA_malloc(size: olen);
50705 if(!out)
50706 return NULL;
50707
50708 const unsigned char *end = src + len;
50709 const unsigned char *in = src;
50710 unsigned char *pos = out;
50711 while(end - in >= 3) {
50712 *pos++ = base64_table[in[0] >> 2];
50713 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
50714 *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
50715 *pos++ = base64_table[in[2] & 0x3f];
50716 in += 3;
50717 }
50718
50719 if(end - in) {
50720 *pos++ = base64_table[in[0] >> 2];
50721 if(end - in == 1) {
50722 *pos++ = base64_table[(in[0] & 0x03) << 4];
50723 *pos++ = '=';
50724 } else {
50725 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
50726 *pos++ = base64_table[(in[1] & 0x0f) << 2];
50727 }
50728 *pos++ = '=';
50729 }
50730
50731 *out_len = (size_t)(pos - out);
50732 return out;
50733}
50734
50735static const uint32_t from_b64[256] = {
50736 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50737 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
50738 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 63, 62, 62, 63,
50739 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0,
50740 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
50741 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63,
50742 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
50743 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
50744
50745unsigned char *
50746UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) {
50747 // we need a minimum length
50748 if(len <= 2) {
50749 *out_len = 0;
50750 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50751 }
50752
50753 const unsigned char *p = src;
50754 size_t pad1 = len % 4 || p[len - 1] == '=';
50755 size_t pad2 = pad1 && (len % 4 > 2 || p[len - 2] != '=');
50756 const size_t last = (len - pad1) / 4 << 2;
50757
50758 unsigned char *str = (unsigned char*)UA_malloc(size: last / 4 * 3 + pad1 + pad2);
50759 if(!str)
50760 return NULL;
50761
50762 unsigned char *pos = str;
50763 for(size_t i = 0; i < last; i += 4) {
50764 uint32_t n = from_b64[p[i]] << 18 | from_b64[p[i + 1]] << 12 |
50765 from_b64[p[i + 2]] << 6 | from_b64[p[i + 3]];
50766 *pos++ = (unsigned char)(n >> 16);
50767 *pos++ = (unsigned char)(n >> 8 & 0xFF);
50768 *pos++ = (unsigned char)(n & 0xFF);
50769 }
50770
50771 if(pad1) {
50772 if (last + 1 >= len) {
50773 UA_free(ptr: str);
50774 *out_len = 0;
50775 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50776 }
50777 uint32_t n = from_b64[p[last]] << 18 | from_b64[p[last + 1]] << 12;
50778 *pos++ = (unsigned char)(n >> 16);
50779 if(pad2) {
50780 if (last + 2 >= len) {
50781 UA_free(ptr: str);
50782 *out_len = 0;
50783 return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL;
50784 }
50785 n |= from_b64[p[last + 2]] << 6;
50786 *pos++ = (unsigned char)(n >> 8 & 0xFF);
50787 }
50788 }
50789
50790 *out_len = (uintptr_t)(pos - str);
50791 return str;
50792}
50793
50794/**** amalgamated original file "/deps/aa_tree.c" ****/
50795
50796/* This Source Code Form is subject to the terms of the Mozilla Public
50797 * License, v. 2.0. If a copy of the MPL was not distributed with this
50798 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
50799 *
50800 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
50801 */
50802
50803#include <stddef.h>
50804
50805#ifdef UNDER_CE
50806 /* Windows CE: uintptr_t has already been defined by windows.h */
50807#elif !defined(_MSC_VER) || _MSC_VER >= 1800
50808# include <inttypes.h>
50809#elif !defined(uintptr_t)
50810 /* Workaround missing standard includes in older Visual Studio */
50811# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
50812typedef _W64 unsigned int uintptr_t;
50813# else
50814typedef unsigned __int64 uintptr_t;
50815# endif
50816#endif
50817
50818#define aa_entry_container(head, entry) \
50819 ((void*)((uintptr_t)entry - head->entry_offset))
50820#define aa_entry_key(head, entry) \
50821 ((const void*)((uintptr_t)entry + head->key_offset - head->entry_offset))
50822#define aa_container_entry(head, container) \
50823 ((struct aa_entry*)((uintptr_t)container + head->entry_offset))
50824#define aa_container_key(head, container) \
50825 ((const void*)((uintptr_t)container + head->key_offset))
50826
50827void
50828aa_init(struct aa_head *head,
50829 enum aa_cmp (*cmp)(const void*, const void*),
50830 unsigned int entry_offset, unsigned int key_offset) {
50831 head->root = NULL;
50832 head->cmp = cmp;
50833 head->entry_offset = entry_offset;
50834 head->key_offset = key_offset;
50835}
50836
50837static struct aa_entry *
50838_aa_skew(struct aa_entry *n) {
50839 if(!n)
50840 return NULL;
50841 if(n->left && n->level == n->left->level) {
50842 struct aa_entry *l = n->left;
50843 n->left = l->right;
50844 l->right = n;
50845 return l;
50846 }
50847 return n;
50848}
50849
50850static struct aa_entry *
50851_aa_split(struct aa_entry *n) {
50852 if(!n)
50853 return NULL;
50854 if(n->right && n->right->right &&
50855 n->right->right->level == n->level) {
50856 struct aa_entry *r = n->right;
50857 n->right = r->left;
50858 r->left = n;
50859 r->level++;
50860 return r;
50861 }
50862 return n;
50863}
50864
50865static struct aa_entry *
50866_aa_fixup(struct aa_entry *n) {
50867 unsigned int should_be = 0;
50868 if(n->left)
50869 should_be = n->left->level;
50870 if(n->right && n->right->level < should_be)
50871 should_be = n->right->level;
50872 should_be++;
50873 if(should_be < n->level)
50874 n->level = should_be;
50875 if(n->right && n->right->level > should_be)
50876 n->right->level = should_be;
50877 n = _aa_skew(n);
50878 n->right = _aa_skew(n: n->right);
50879 if(n->right)
50880 n->right->right = _aa_skew(n: n->right->right);
50881 n = _aa_split(n);
50882 n->right = _aa_split(n: n->right);
50883 return n;
50884}
50885
50886static struct aa_entry *
50887_aa_insert(struct aa_head *h, struct aa_entry *n, void *elem) {
50888 if(!n) {
50889 struct aa_entry *e = aa_container_entry(h, elem);
50890 e->left = NULL;
50891 e->right = NULL;
50892 e->level = 1;
50893 return e;
50894 }
50895 const void *n_key = aa_entry_key(h, n);
50896 const void *key = aa_container_key(h, elem);
50897 enum aa_cmp eq = h->cmp(key, n_key);
50898 if(eq == AA_CMP_EQ)
50899 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50900 if(eq == AA_CMP_LESS)
50901 n->left = _aa_insert(h, n: n->left, elem);
50902 else
50903 n->right = _aa_insert(h, n: n->right, elem);
50904 return _aa_split(n: _aa_skew(n));
50905}
50906
50907void
50908aa_insert(struct aa_head *h, void *elem) {
50909 h->root = _aa_insert(h, n: h->root, elem);
50910}
50911
50912void *
50913aa_find(const struct aa_head *h, const void *key) {
50914 struct aa_entry *n = h->root;
50915 while(n) {
50916 enum aa_cmp eq = h->cmp(key, aa_entry_key(h, n));
50917 if(eq == AA_CMP_EQ)
50918 return aa_entry_container(h, n);
50919 n = (eq == AA_CMP_LESS) ? n->left : n->right;
50920 }
50921 return NULL;
50922}
50923
50924static struct aa_entry *
50925unlink_succ(struct aa_entry *n, struct aa_entry **succ) {
50926 if(!n->left) {
50927 *succ = n;
50928 return n->right;
50929 }
50930 n->left = unlink_succ(n: n->left, succ);
50931 return _aa_fixup(n);
50932}
50933
50934static struct aa_entry *
50935unlink_pred(struct aa_entry *n, struct aa_entry **pred) {
50936 if(!n->right) {
50937 *pred = n;
50938 return n->left;
50939 }
50940 n->right = unlink_pred(n: n->right, pred);
50941 return _aa_fixup(n);
50942}
50943
50944static struct aa_entry *
50945_aa_remove(struct aa_head *h, void *elem, struct aa_entry *n) {
50946 if(!n)
50947 return NULL;
50948
50949 const void *elem_key = aa_container_key(h, elem);
50950 const void *n_key = aa_entry_key(h, n);
50951 if(n_key == elem_key) {
50952 if(!n->left && !n->right)
50953 return NULL;
50954 struct aa_entry *replace = NULL;
50955 if(!n->left)
50956 n->right = unlink_succ(n: n->right, succ: &replace);
50957 else
50958 n->left = unlink_pred(n: n->left, pred: &replace);
50959 replace->left = n->left;
50960 replace->right = n->right;
50961 replace->level = n->level;
50962 return _aa_fixup(n: replace);
50963 }
50964
50965 enum aa_cmp eq = h->cmp(elem_key, n_key);
50966 if(eq == AA_CMP_EQ)
50967 eq = (elem_key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
50968 if(eq == AA_CMP_LESS)
50969 n->left = _aa_remove(h, elem, n: n->left);
50970 else
50971 n->right = _aa_remove(h, elem, n: n->right);
50972 return _aa_fixup(n);
50973}
50974
50975void
50976aa_remove(struct aa_head *head, void *elem) {
50977 head->root = _aa_remove(h: head, elem, n: head->root);
50978}
50979
50980void *
50981aa_min(const struct aa_head *head) {
50982 struct aa_entry *e = head->root;
50983 if(!e)
50984 return NULL;
50985 while(e->left)
50986 e = e->left;
50987 return aa_entry_container(head, e);
50988}
50989
50990void *
50991aa_max(const struct aa_head *head) {
50992 struct aa_entry *e = head->root;
50993 if(!e)
50994 return NULL;
50995 while(e->right)
50996 e = e->right;
50997 return aa_entry_container(head, e);
50998}
50999
51000void *
51001aa_next(const struct aa_head *head, const void *elem) {
51002 struct aa_entry *e = aa_container_entry(head, elem);
51003 if(e->right) {
51004 e = e->right;
51005 while(e->left)
51006 e = e->left;
51007 return aa_entry_container(head, e);
51008 }
51009 struct aa_entry *next = NULL;
51010 struct aa_entry *n = head->root;
51011 const void *key = aa_container_key(head, elem);
51012 while(n && n != e) {
51013 const void *n_key = aa_entry_key(head, n);
51014 enum aa_cmp eq = head->cmp(key, n_key);
51015 if(eq == AA_CMP_EQ)
51016 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
51017 if(eq == AA_CMP_MORE) {
51018 n = n->right;
51019 } else {
51020 next = n;
51021 n = n->left;
51022 }
51023 }
51024 return (next) ? aa_entry_container(head, next) : NULL;
51025}
51026
51027void *
51028aa_prev(const struct aa_head *head, const void *elem) {
51029 struct aa_entry *e = aa_container_entry(head, elem);
51030 if(e->left) {
51031 e = e->left;
51032 while(e->right)
51033 e = e->right;
51034 return aa_entry_container(head, e);
51035 }
51036 struct aa_entry *prev = NULL;
51037 struct aa_entry *n = head->root;
51038 const void *key = aa_container_key(head, elem);
51039 while(n && n != e) {
51040 const void *n_key = aa_entry_key(head, n);
51041 enum aa_cmp eq = head->cmp(key, n_key);
51042 if(eq == AA_CMP_EQ)
51043 eq = (key > n_key) ? AA_CMP_MORE : AA_CMP_LESS;
51044 if(eq == AA_CMP_MORE) {
51045 prev = n;
51046 n = n->right;
51047 } else {
51048 n = n->left;
51049 }
51050 }
51051 return (prev) ? aa_entry_container(head, prev) : NULL;
51052}
51053
51054/**** amalgamated original file "/deps/ziptree.c" ****/
51055
51056/* This Source Code Form is subject to the terms of the Mozilla Public
51057 * License, v. 2.0. If a copy of the MPL was not distributed with this
51058 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
51059 *
51060 * Copyright 2021 (c) Julius Pfrommer
51061 */
51062
51063
51064#if defined(_MSC_VER)
51065#include <intrin.h>
51066#endif
51067
51068unsigned char
51069__ZIP_FFS32(unsigned int v) {
51070#if defined(__GNUC__) || defined(__clang__)
51071 return (unsigned char)((unsigned char)__builtin_ffs((int)v) - 1u);
51072#elif defined(_MSC_VER)
51073 unsigned long index = 255;
51074 _BitScanForward(&index, v);
51075 return (unsigned char)index;
51076#else
51077 if(v == 0)
51078 return 255;
51079 unsigned int t = 1;
51080 unsigned char r = 0;
51081 while((v & t) == 0) {
51082 t = t << 1;
51083 r++;
51084 }
51085 return r;
51086#endif
51087}
51088
51089/* Generic analog to ZIP_ENTRY(type) */
51090struct zip_entry {
51091 void *left;
51092 void *right;
51093 unsigned char rank;
51094};
51095
51096#define ZIP_ENTRY_PTR(x) (struct zip_entry*)((char*)x + fieldoffset)
51097#define ZIP_KEY_PTR(x) (void*)((char*)x + keyoffset)
51098
51099void *
51100__ZIP_INSERT(zip_cmp_cb cmp, unsigned short fieldoffset,
51101 unsigned short keyoffset, void *root, void *elm) {
51102 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
51103 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51104 if(!root) {
51105 elm_entry->left = NULL;
51106 elm_entry->right = NULL;
51107 return elm;
51108 }
51109 enum ZIP_CMP order = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
51110 if(order == ZIP_CMP_LESS) {
51111 if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root: root_entry->left, elm) == elm) {
51112 if(elm_entry->rank < root_entry->rank) {
51113 root_entry->left = elm;
51114 } else {
51115 root_entry->left = elm_entry->right;
51116 elm_entry->right = root;
51117 return elm;
51118 }
51119 }
51120 } else {
51121 if(__ZIP_INSERT(cmp, fieldoffset, keyoffset, root: root_entry->right, elm) == elm) {
51122 if(elm_entry->rank <= root_entry->rank) {
51123 root_entry->right = elm;
51124 } else {
51125 root_entry->right = elm_entry->left;
51126 elm_entry->left = root;
51127 return elm;
51128 }
51129 }
51130 }
51131 return root;
51132}
51133
51134static void *
51135__ZIP(unsigned short fieldoffset, void *x, void *y) {
51136 if(!x) return y;
51137 if(!y) return x;
51138 struct zip_entry *x_entry = ZIP_ENTRY_PTR(x);
51139 struct zip_entry *y_entry = ZIP_ENTRY_PTR(y);
51140 if(x_entry->rank < y_entry->rank) {
51141 y_entry->left = __ZIP(fieldoffset, x, y: y_entry->left);
51142 return y;
51143 } else {
51144 x_entry->right = __ZIP(fieldoffset, x: x_entry->right, y);
51145 return x;
51146 }
51147}
51148
51149/* Modified from the original algorithm. Allow multiple elements with the same
51150 * key. */
51151void *
51152__ZIP_REMOVE(zip_cmp_cb cmp, unsigned short fieldoffset,
51153 unsigned short keyoffset, void *root, void *elm) {
51154 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
51155 if(root == elm)
51156 return __ZIP(fieldoffset, x: root_entry->left, y: root_entry->right);
51157 void *left = root_entry->left;
51158 void *right = root_entry->right;
51159 enum ZIP_CMP eq = cmp(ZIP_KEY_PTR(elm), ZIP_KEY_PTR(root));
51160 if(eq == ZIP_CMP_LESS) {
51161 struct zip_entry *left_entry = ZIP_ENTRY_PTR(left);
51162 if(elm == left)
51163 root_entry->left = __ZIP(fieldoffset, x: left_entry->left, y: left_entry->right);
51164 else if(left)
51165 __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: left, elm);
51166 } else if(eq == ZIP_CMP_MORE) {
51167 struct zip_entry *right_entry = ZIP_ENTRY_PTR(right);
51168 if(elm == right)
51169 root_entry->right = __ZIP(fieldoffset, x: right_entry->left, y: right_entry->right);
51170 else if(right)
51171 __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: right, elm);
51172 } else { /* ZIP_CMP_EQ, but root != elm */
51173 if(right)
51174 root_entry->right = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: right, elm);
51175 if(left)
51176 root_entry->left = __ZIP_REMOVE(cmp, fieldoffset, keyoffset, root: left, elm);
51177 }
51178 return root;
51179}
51180
51181void *
51182__ZIP_FIND(zip_cmp_cb cmp, unsigned short fieldoffset,
51183 unsigned short keyoffset, void *root, const void *key) {
51184 if(!root)
51185 return NULL;
51186 enum ZIP_CMP eq = cmp(key, ZIP_KEY_PTR(root));
51187 if(eq == ZIP_CMP_EQ)
51188 return root;
51189 struct zip_entry *root_entry = ZIP_ENTRY_PTR(root);
51190 if(eq == ZIP_CMP_LESS)
51191 return __ZIP_FIND(cmp, fieldoffset, keyoffset, root: root_entry->left, key);
51192 else
51193 return __ZIP_FIND(cmp, fieldoffset, keyoffset, root: root_entry->right, key);
51194}
51195
51196void *
51197__ZIP_MIN(unsigned short fieldoffset, void *elm) {
51198 if(!elm)
51199 return NULL;
51200 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51201 while(elm_entry->left) {
51202 elm = elm_entry->left;
51203 elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
51204 }
51205 return elm;
51206}
51207
51208void *
51209__ZIP_MAX(unsigned short fieldoffset, void *elm) {
51210 if(!elm)
51211 return NULL;
51212 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51213 while(elm_entry->right) {
51214 elm = elm_entry->right;
51215 elm_entry = (struct zip_entry*)((char*)elm + fieldoffset);
51216 }
51217 return elm;
51218}
51219
51220void
51221__ZIP_ITER(unsigned short fieldoffset, __zip_iter_cb cb,
51222 void *context, void *elm) {
51223 if(!elm)
51224 return;
51225 struct zip_entry *elm_entry = ZIP_ENTRY_PTR(elm);
51226 __ZIP_ITER(fieldoffset, cb, context, elm: elm_entry->left);
51227 __ZIP_ITER(fieldoffset, cb, context, elm: elm_entry->right);
51228 cb(elm, context);
51229}
51230
51231/**** amalgamated original file "/src/pubsub/ua_pubsub_config.c" ****/
51232
51233/* This Source Code Form is subject to the terms of the Mozilla Public
51234 * License, v. 2.0. If a copy of the MPL was not distributed with this
51235 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
51236 *
51237 * Copyright (c) 2020 Yannick Wallerer, Siemens AG
51238 * Copyright (c) 2020 Thomas Fischer, Siemens AG
51239 */
51240
51241
51242#ifdef UA_ENABLE_PUBSUB
51243#ifdef UA_ENABLE_PUBSUB_ETH_UADP
51244#endif
51245#endif
51246
51247
51248#ifdef UA_ENABLE_PUBSUB_FILE_CONFIG
51249
51250static UA_StatusCode
51251createPubSubConnection(UA_Server *server,
51252 const UA_PubSubConnectionDataType *connection,
51253 UA_UInt32 pdsCount, UA_NodeId *pdsIdent);
51254
51255static UA_StatusCode
51256createWriterGroup(UA_Server *server,
51257 const UA_WriterGroupDataType *writerGroupParameters,
51258 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51259 const UA_NodeId *pdsIdent);
51260
51261static UA_StatusCode
51262createDataSetWriter(UA_Server *server,
51263 const UA_DataSetWriterDataType *dataSetWriterParameters,
51264 UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
51265 const UA_NodeId *pdsIdent);
51266
51267static UA_StatusCode
51268createReaderGroup(UA_Server *server,
51269 const UA_ReaderGroupDataType *readerGroupParameters,
51270 UA_NodeId connectionIdent);
51271
51272static UA_StatusCode
51273createDataSetReader(UA_Server *server,
51274 const UA_DataSetReaderDataType *dataSetReaderParameters,
51275 UA_NodeId readerGroupIdent);
51276
51277static UA_StatusCode
51278createPublishedDataSet(UA_Server *server,
51279 const UA_PublishedDataSetDataType *publishedDataSetParameters,
51280 UA_NodeId *publishedDataSetIdent);
51281
51282static UA_StatusCode
51283createDataSetFields(UA_Server *server,
51284 const UA_NodeId *publishedDataSetIdent,
51285 const UA_PublishedDataSetDataType *publishedDataSetParameters);
51286
51287static UA_StatusCode
51288generatePubSubConfigurationDataType(const UA_Server *server,
51289 UA_PubSubConfigurationDataType *pubSubConfiguration);
51290
51291/* Gets PubSub Configuration from an ExtensionObject */
51292static UA_StatusCode
51293extractPubSubConfigFromExtensionObject(const UA_ExtensionObject *src,
51294 UA_PubSubConfigurationDataType **dst) {
51295 if(src->encoding != UA_EXTENSIONOBJECT_DECODED ||
51296 src->content.decoded.type != &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]) {
51297 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51298 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51299 "Reading extensionObject failed");
51300 return UA_STATUSCODE_BADINVALIDARGUMENT;
51301 }
51302
51303 UA_UABinaryFileDataType *binFile = (UA_UABinaryFileDataType*)src->content.decoded.data;
51304
51305 if(binFile->body.arrayLength != 0 || binFile->body.arrayDimensionsSize != 0) {
51306 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51307 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51308 "Loading multiple configurations is not supported");
51309 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51310 }
51311
51312 if(binFile->body.type != &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]) {
51313 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51314 "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] "
51315 "Invalid datatype encoded in the binary file");
51316 return UA_STATUSCODE_BADTYPEMISMATCH;
51317 }
51318
51319 *dst = (UA_PubSubConfigurationDataType*)binFile->body.data;
51320 return UA_STATUSCODE_GOOD;
51321}
51322
51323/* Configures a PubSub Server with given PubSubConfigurationDataType object */
51324static UA_StatusCode
51325updatePubSubConfig(UA_Server *server,
51326 const UA_PubSubConfigurationDataType *configurationParameters) {
51327 if(server == NULL || configurationParameters == NULL) {
51328 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51329 "[UA_PubSubManager_updatePubSubConfig] Invalid argument");
51330 return UA_STATUSCODE_BADINVALIDARGUMENT;
51331 }
51332
51333 UA_PubSubManager_delete(server, &server->pubSubManager);
51334
51335 /* Configuration of Published DataSets: */
51336 UA_UInt32 pdsCount = (UA_UInt32)configurationParameters->publishedDataSetsSize;
51337 UA_NodeId *publishedDataSetIdent = (UA_NodeId*)UA_calloc(pdsCount, sizeof(UA_NodeId));
51338 if(!publishedDataSetIdent)
51339 return UA_STATUSCODE_BADOUTOFMEMORY;
51340
51341 UA_StatusCode res = UA_STATUSCODE_GOOD;
51342 for(UA_UInt32 i = 0; i < pdsCount; i++) {
51343 res = createPublishedDataSet(server,
51344 &configurationParameters->publishedDataSets[i],
51345 &publishedDataSetIdent[i]);
51346 if(res != UA_STATUSCODE_GOOD) {
51347 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51348 "[UA_PubSubManager_updatePubSubConfig] PDS creation failed");
51349 UA_free(publishedDataSetIdent);
51350 return res;
51351 }
51352 }
51353
51354 /* Configuration of PubSub Connections: */
51355 if(configurationParameters->connectionsSize < 1) {
51356 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51357 "[UA_PubSubManager_updatePubSubConfig] no connection in "
51358 "UA_PubSubConfigurationDataType");
51359 UA_free(publishedDataSetIdent);
51360 return UA_STATUSCODE_GOOD;
51361 }
51362
51363 for(size_t i = 0; i < configurationParameters->connectionsSize; i++) {
51364 res = createPubSubConnection(server,
51365 &configurationParameters->connections[i],
51366 pdsCount, publishedDataSetIdent);
51367 if(res != UA_STATUSCODE_GOOD)
51368 break;
51369 }
51370
51371 UA_free(publishedDataSetIdent);
51372 return res;
51373}
51374
51375/* Function called by UA_PubSubManager_createPubSubConnection to set the
51376 * PublisherId of a certain connection. */
51377static UA_StatusCode
51378setConnectionPublisherId(const UA_PubSubConnectionDataType *src,
51379 UA_PubSubConnectionConfig *dst) {
51380 if(src->publisherId.type == &UA_TYPES[UA_TYPES_STRING]) {
51381 dst->publisherIdType = UA_PUBSUB_PUBLISHERID_STRING;
51382 dst->publisherId.string = *(UA_String*)src->publisherId.data;
51383 } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_BYTE] ||
51384 src->publisherId.type == &UA_TYPES[UA_TYPES_UINT16] ||
51385 src->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]) {
51386 dst->publisherIdType = UA_PUBSUB_PUBLISHERID_NUMERIC;
51387 dst->publisherId.numeric = *(UA_UInt32*)src->publisherId.data;
51388 } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT64]) {
51389 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51390 "[UA_PubSubManager_setConnectionPublisherId] PublisherId is UInt64 "
51391 "(not implemented); Recommended dataType for PublisherId: UInt32");
51392 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51393 } else {
51394 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51395 "[UA_PubSubManager_setConnectionPublisherId] PublisherId is not valid.");
51396 return UA_STATUSCODE_BADINTERNALERROR;
51397 }
51398 return UA_STATUSCODE_GOOD;
51399}
51400
51401/* Function called by UA_PubSubManager_createPubSubConnection to create all WriterGroups
51402 * and ReaderGroups that belong to a certain connection. */
51403static UA_StatusCode
51404createComponentsForConnection(UA_Server *server,
51405 const UA_PubSubConnectionDataType *connParams,
51406 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51407 const UA_NodeId *pdsIdent) {
51408 /* WriterGroups configuration */
51409 UA_StatusCode res = UA_STATUSCODE_GOOD;
51410 for(size_t i = 0; i < connParams->writerGroupsSize; i++) {
51411 res = createWriterGroup(server, &connParams->writerGroups[i],
51412 connectionIdent, pdsCount, pdsIdent);
51413 if(res != UA_STATUSCODE_GOOD) {
51414 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51415 "[UA_PubSubManager_createComponentsForConnection] "
51416 "Error occured during %d. WriterGroup Creation", (UA_UInt32)i+1);
51417 return res;
51418 }
51419 }
51420
51421 /* ReaderGroups configuration */
51422 for(size_t j = 0; j < connParams->readerGroupsSize; j++) {
51423 res = createReaderGroup(server, &connParams->readerGroups[j], connectionIdent);
51424 if(res == UA_STATUSCODE_GOOD)
51425 res |= UA_PubSubConnection_regist(server, &connectionIdent);
51426 if(res != UA_STATUSCODE_GOOD) {
51427 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51428 "[UA_PubSubManager_createComponentsForConnection] "
51429 "Error occured during %d. ReaderGroup Creation", (UA_UInt32)j+1);
51430 return res;
51431 }
51432 }
51433
51434 return res;
51435}
51436
51437/* Checks if transportLayer for the specified transportProfileUri exists.
51438 *
51439 * @param server Server object that shall be configured
51440 * @param transportProfileUri String that specifies the transport protocol */
51441static UA_Boolean
51442transportLayerExists(UA_Server *server, UA_String transportProfileUri) {
51443 for(size_t i = 0; i < server->config.pubSubConfig.transportLayersSize; i++) {
51444 if(UA_String_equal(&server->config.pubSubConfig.transportLayers[i].transportProfileUri,
51445 &transportProfileUri)) {
51446 return true;
51447 }
51448 }
51449 return false;
51450}
51451
51452/* Creates transportlayer for specified transport protocol if this layer doesn't exist yet */
51453static UA_StatusCode
51454createTransportLayer(UA_Server *server, const UA_String transportProfileUri) {
51455 if(transportLayerExists(server, transportProfileUri))
51456 return UA_STATUSCODE_GOOD;
51457
51458 UA_ServerConfig *config = UA_Server_getConfig(server);
51459 UA_PubSubTransportLayer tl;
51460
51461 do {
51462 UA_String strUDP =
51463 UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp");
51464 if(UA_String_equal(&transportProfileUri, &strUDP)) {
51465 tl = UA_PubSubTransportLayerUDPMP();
51466 break;
51467 }
51468
51469#ifdef UA_ENABLE_PUBSUB_ETH_UADP
51470 UA_String strETH =
51471 UA_STRING("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp");
51472 if(UA_String_equal(&transportProfileUri, &strETH)) {
51473 tl = UA_PubSubTransportLayerEthernet();
51474 break;
51475 }
51476#endif
51477
51478 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51479 "[UA_PubSubManager_createTransportLayer] "
51480 "invalid transportProfileUri");
51481 return UA_STATUSCODE_BADINVALIDARGUMENT;
51482 } while(0);
51483
51484 if(config->pubSubConfig.transportLayersSize > 0) {
51485 config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
51486 UA_realloc(config->pubSubConfig.transportLayers,
51487 (config->pubSubConfig.transportLayersSize + 1) *
51488 sizeof(UA_PubSubTransportLayer));
51489 } else {
51490 config->pubSubConfig.transportLayers = (UA_PubSubTransportLayer *)
51491 UA_calloc(1, sizeof(UA_PubSubTransportLayer));
51492 }
51493
51494 if(config->pubSubConfig.transportLayers == NULL) {
51495 UA_Server_delete(server);
51496 return UA_STATUSCODE_BADOUTOFMEMORY;
51497 }
51498 config->pubSubConfig.transportLayers[config->pubSubConfig.transportLayersSize] = tl;
51499 config->pubSubConfig.transportLayersSize++;
51500 return UA_STATUSCODE_GOOD;
51501}
51502
51503/* Creates PubSubConnection configuration from PubSubConnectionDataType object
51504 *
51505 * @param server Server object that shall be configured
51506 * @param connParams PubSub connection configuration
51507 * @param pdsCount Number of published DataSets
51508 * @param pdsIdent Array of NodeIds of the published DataSets */
51509static UA_StatusCode
51510createPubSubConnection(UA_Server *server, const UA_PubSubConnectionDataType *connParams,
51511 UA_UInt32 pdsCount, UA_NodeId *pdsIdent) {
51512 UA_PubSubConnectionConfig config;
51513 memset(&config, 0, sizeof(UA_PubSubConnectionConfig));
51514
51515 config.name = connParams->name;
51516 config.enabled = connParams->enabled;
51517 config.transportProfileUri = connParams->transportProfileUri;
51518 config.connectionPropertiesSize = connParams->connectionPropertiesSize;
51519 if(config.connectionPropertiesSize > 0) {
51520 config.connectionProperties = connParams->connectionProperties;
51521 }
51522
51523 UA_StatusCode res = setConnectionPublisherId(connParams, &config);
51524 if(res != UA_STATUSCODE_GOOD) {
51525 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51526 "[UA_PubSubManager_createPubSubConnection] "
51527 "Setting PublisherId failed");
51528 return res;
51529 }
51530
51531 if(connParams->address.encoding == UA_EXTENSIONOBJECT_DECODED) {
51532 UA_Variant_setScalar(&(config.address),
51533 connParams->address.content.decoded.data,
51534 connParams->address.content.decoded.type);
51535 } else {
51536 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51537 "[UA_PubSubManager_createPubSubConnection] "
51538 "Reading connection address failed");
51539 return UA_STATUSCODE_BADINTERNALERROR;
51540 }
51541
51542 if(connParams->transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED) {
51543 UA_Variant_setScalar(&(config.connectionTransportSettings),
51544 connParams->transportSettings.content.decoded.data,
51545 connParams->transportSettings.content.decoded.type);
51546 } else {
51547 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51548 "[UA_PubSubManager_createPubSubConnection] "
51549 "TransportSettings can not be read");
51550 }
51551
51552 res = createTransportLayer(server, connParams->transportProfileUri);
51553 if(res != UA_STATUSCODE_GOOD) {
51554 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51555 "[UA_PubSubManager_createPubSubConnection] "
51556 "Creating transportLayer failed");
51557 return res;
51558 }
51559
51560 /* Load connection config into server: */
51561 UA_NodeId connectionIdent;
51562 res = UA_Server_addPubSubConnection(server, &config, &connectionIdent);
51563 if(res == UA_STATUSCODE_GOOD) {
51564 /* Configuration of all Components that belong to this connection: */
51565 res = createComponentsForConnection(server, connParams, connectionIdent,
51566 pdsCount, pdsIdent);
51567 } else {
51568 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51569 "[UA_PubSubManager_createPubSubConnection] "
51570 "Connection creation failed");
51571 }
51572
51573 return res;
51574}
51575
51576/* Function called by UA_PubSubManager_createWriterGroup to configure the messageSettings
51577 * of a writerGroup */
51578static UA_StatusCode
51579setWriterGroupEncodingType(const UA_WriterGroupDataType *writerGroupParameters,
51580 UA_WriterGroupConfig *config) {
51581 if(writerGroupParameters->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED) {
51582 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51583 "[UA_PubSubManager_setWriterGroupEncodingType] "
51584 "getting message type information failed");
51585 return UA_STATUSCODE_BADINVALIDARGUMENT;
51586 }
51587
51588 if(writerGroupParameters->messageSettings.content.decoded.type ==
51589 &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) {
51590 config->encodingMimeType = UA_PUBSUB_ENCODING_UADP;
51591 } else if(writerGroupParameters->messageSettings.content.decoded.type ==
51592 &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]) {
51593 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51594 "[UA_PubSubManager_setWriterGroupEncodingType] "
51595 "encoding type: JSON (not implemented!)");
51596 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51597 } else {
51598 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51599 "[UA_PubSubManager_setWriterGroupEncodingType] "
51600 "invalid message encoding type");
51601 return UA_STATUSCODE_BADINVALIDARGUMENT;
51602 }
51603
51604 return UA_STATUSCODE_GOOD;
51605}
51606
51607/* WriterGroup configuration from WriterGroup object
51608 *
51609 * @param server Server object that shall be configured
51610 * @param writerGroupParameters WriterGroup configuration
51611 * @param connectionIdent NodeId of the PubSub connection, the WriterGroup belongs to
51612 * @param pdsCount Number of published DataSets
51613 * @param pdsIdent Array of NodeIds of the published DataSets */
51614static UA_StatusCode
51615createWriterGroup(UA_Server *server,
51616 const UA_WriterGroupDataType *writerGroupParameters,
51617 UA_NodeId connectionIdent, UA_UInt32 pdsCount,
51618 const UA_NodeId *pdsIdent) {
51619 UA_WriterGroupConfig config;
51620 memset(&config, 0, sizeof(UA_WriterGroupConfig));
51621 config.name = writerGroupParameters->name;
51622 config.enabled = writerGroupParameters->enabled;
51623 config.writerGroupId = writerGroupParameters->writerGroupId;
51624 config.publishingInterval = writerGroupParameters->publishingInterval;
51625 config.keepAliveTime = writerGroupParameters->keepAliveTime;
51626 config.priority = writerGroupParameters->priority;
51627 config.securityMode = writerGroupParameters->securityMode;
51628 config.transportSettings = writerGroupParameters->transportSettings;
51629 config.messageSettings = writerGroupParameters->messageSettings;
51630 config.groupPropertiesSize = writerGroupParameters->groupPropertiesSize;
51631 if(config.groupPropertiesSize > 0)
51632 config.groupProperties = writerGroupParameters->groupProperties;
51633
51634 config.maxEncapsulatedDataSetMessageCount = 255; /* non std parameter */
51635
51636 UA_StatusCode res = setWriterGroupEncodingType(writerGroupParameters, &config);
51637 if(res != UA_STATUSCODE_GOOD) {
51638 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51639 "[UA_PubSubManager_createWriterGroup] "
51640 "Setting message settings failed");
51641 return res;
51642 }
51643
51644 /* Load config into server: */
51645 UA_NodeId writerGroupIdent;
51646 res = UA_Server_addWriterGroup(server, connectionIdent, &config, &writerGroupIdent);
51647 UA_Server_setWriterGroupOperational(server, writerGroupIdent);
51648 if(res != UA_STATUSCODE_GOOD) {
51649 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51650 "[UA_PubSubManager_createWriterGroup] "
51651 "Adding WriterGroup to server failed: 0x%x", res);
51652 return res;
51653 }
51654
51655 /* Configuration of all DataSetWriters that belong to this WriterGroup */
51656 for(size_t dsw = 0; dsw < writerGroupParameters->dataSetWritersSize; dsw++) {
51657 res = createDataSetWriter(server, &writerGroupParameters->dataSetWriters[dsw],
51658 writerGroupIdent, pdsCount, pdsIdent);
51659 if(res != UA_STATUSCODE_GOOD) {
51660 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51661 "[UA_PubSubManager_createWriterGroup] "
51662 "DataSetWriter Creation failed.");
51663 break;
51664 }
51665 }
51666 return res;
51667}
51668
51669/* Function called by UA_PubSubManager_createDataSetWriter. It searches for a
51670 * PublishedDataSet that is referenced by the DataSetWriter. If a related PDS is found,
51671 * the DSWriter will be added to the server, otherwise, no DSWriter will be added.
51672 *
51673 * @param server UA_Server object that shall be configured
51674 * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
51675 * @param dsWriterConfig WriterGroup configuration
51676 * @param pdsCount Number of published DataSets
51677 * @param pdsIdent Array of NodeIds of the published DataSets */
51678static UA_StatusCode
51679addDataSetWriterWithPdsReference(UA_Server *server, UA_NodeId writerGroupIdent,
51680 const UA_DataSetWriterConfig *dsWriterConfig,
51681 UA_UInt32 pdsCount, const UA_NodeId *pdsIdent) {
51682 UA_NodeId dataSetWriterIdent;
51683 UA_PublishedDataSetConfig pdsConfig;
51684 UA_Boolean pdsFound = false;
51685
51686 UA_StatusCode res = UA_STATUSCODE_GOOD;
51687 for(size_t pds = 0; pds < pdsCount && res == UA_STATUSCODE_GOOD; pds++) {
51688 res = UA_Server_getPublishedDataSetConfig(server, pdsIdent[pds], &pdsConfig);
51689 /* members of pdsConfig must be deleted manually */
51690 if(res != UA_STATUSCODE_GOOD) {
51691 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51692 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51693 "Getting pdsConfig from NodeId failed.");
51694 return res;
51695 }
51696
51697 if(dsWriterConfig->dataSetName.length == pdsConfig.name.length &&
51698 0 == strncmp((const char *)dsWriterConfig->dataSetName.data,
51699 (const char *)pdsConfig.name.data,
51700 dsWriterConfig->dataSetName.length)) {
51701 /* DSWriter will only be created, if a matching PDS is found: */
51702 res = UA_Server_addDataSetWriter(server, writerGroupIdent, pdsIdent[pds],
51703 dsWriterConfig, &dataSetWriterIdent);
51704 if(res != UA_STATUSCODE_GOOD) {
51705 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51706 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51707 "Adding DataSetWriter failed");
51708 } else {
51709 pdsFound = true;
51710 }
51711
51712 UA_PublishedDataSetConfig_clear(&pdsConfig);
51713 if(pdsFound)
51714 break; /* break loop if corresponding publishedDataSet was found */
51715 }
51716 }
51717
51718 if(!pdsFound) {
51719 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51720 "[UA_PubSubManager_addDataSetWriterWithPdsReference] "
51721 "No matching DataSet found; no DataSetWriter created");
51722 }
51723
51724 return res;
51725}
51726
51727/* Creates DataSetWriter configuration from DataSetWriter object
51728 *
51729 * @param server UA_Server object that shall be configured
51730 * @param dataSetWriterParameters DataSetWriter Configuration
51731 * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to
51732 * @param pdsCount Number of published DataSets
51733 * @param pdsIdent Array of NodeIds of the published DataSets */
51734static UA_StatusCode
51735createDataSetWriter(UA_Server *server,
51736 const UA_DataSetWriterDataType *dataSetWriterParameters,
51737 UA_NodeId writerGroupIdent, UA_UInt32 pdsCount,
51738 const UA_NodeId *pdsIdent) {
51739 UA_DataSetWriterConfig config;
51740 memset(&config, 0, sizeof(UA_DataSetWriterConfig));
51741 config.name = dataSetWriterParameters->name;
51742 config.dataSetWriterId = dataSetWriterParameters->dataSetWriterId;
51743 config.keyFrameCount = dataSetWriterParameters->keyFrameCount;
51744 config.dataSetFieldContentMask = dataSetWriterParameters->dataSetFieldContentMask;
51745 config.messageSettings = dataSetWriterParameters->messageSettings;
51746 config.dataSetName = dataSetWriterParameters->dataSetName;
51747 config.dataSetWriterPropertiesSize = dataSetWriterParameters->dataSetWriterPropertiesSize;
51748 if(config.dataSetWriterPropertiesSize > 0)
51749 config.dataSetWriterProperties = dataSetWriterParameters->dataSetWriterProperties;
51750
51751 UA_StatusCode res = addDataSetWriterWithPdsReference(server, writerGroupIdent,
51752 &config, pdsCount, pdsIdent);
51753 if(res != UA_STATUSCODE_GOOD) {
51754 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51755 "[UA_PubSubManager_createDataSetWriter] "
51756 "Referencing related PDS failed");
51757 }
51758
51759 return res;
51760}
51761
51762/* Creates ReaderGroup configuration from ReaderGroup object
51763 *
51764 * @param server UA_Server object that shall be configured
51765 * @param readerGroupParameters ReaderGroup configuration
51766 * @param connectionIdent NodeId of the PubSub connection, the ReaderGroup belongs to */
51767static UA_StatusCode
51768createReaderGroup(UA_Server *server,
51769 const UA_ReaderGroupDataType *readerGroupParameters,
51770 UA_NodeId connectionIdent) {
51771 UA_ReaderGroupConfig config;
51772 memset(&config, 0, sizeof(UA_ReaderGroupConfig));
51773
51774 config.name = readerGroupParameters->name;
51775 config.securityParameters.securityMode = readerGroupParameters->securityMode;
51776
51777 UA_NodeId readerGroupIdent;
51778 UA_StatusCode res =
51779 UA_Server_addReaderGroup(server, connectionIdent, &config, &readerGroupIdent);
51780 if(res != UA_STATUSCODE_GOOD) {
51781 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51782 "[UA_PubSubManager_createReaderGroup] Adding ReaderGroup "
51783 "to server failed: 0x%x", res);
51784 return res;
51785 }
51786
51787 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51788 "[UA_PubSubManager_createReaderGroup] ReaderGroup successfully added.");
51789 for(UA_UInt32 i = 0; i < readerGroupParameters->dataSetReadersSize; i++) {
51790 res = createDataSetReader(server, &readerGroupParameters->dataSetReaders[i],
51791 readerGroupIdent);
51792 if(res != UA_STATUSCODE_GOOD) {
51793 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51794 "[UA_PubSubManager_createReaderGroup] Creating DataSetReader failed");
51795 break;
51796 }
51797 }
51798
51799 if(res == UA_STATUSCODE_GOOD)
51800 UA_Server_setReaderGroupOperational(server, readerGroupIdent);
51801
51802 return res;
51803}
51804
51805/* Creates TargetVariables or SubscribedDataSetMirror for a given DataSetReader
51806 *
51807 * @param server UA_Server object that shall be configured
51808 * @param dsReaderIdent NodeId of the DataSetReader the SubscribedDataSet belongs to
51809 * @param dataSetReaderParameters Configuration Parameters of the DataSetReader */
51810static UA_StatusCode
51811addSubscribedDataSet(UA_Server *server, const UA_NodeId dsReaderIdent,
51812 const UA_ExtensionObject *subscribedDataSet) {
51813 if(subscribedDataSet->content.decoded.type ==
51814 &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]) {
51815 UA_TargetVariablesDataType *tmpTargetVars = (UA_TargetVariablesDataType*)
51816 subscribedDataSet->content.decoded.data;
51817 UA_FieldTargetVariable *targetVars = (UA_FieldTargetVariable *)
51818 UA_calloc(tmpTargetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable));
51819
51820 for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
51821 UA_FieldTargetDataType_copy(&tmpTargetVars->targetVariables[index],
51822 &targetVars[index].targetVariable);
51823 }
51824
51825 UA_StatusCode res =
51826 UA_Server_DataSetReader_createTargetVariables(server, dsReaderIdent,
51827 tmpTargetVars->targetVariablesSize,
51828 targetVars);
51829 if(res != UA_STATUSCODE_GOOD) {
51830 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51831 "[UA_PubSubManager_addSubscribedDataSet] "
51832 "create TargetVariables failed");
51833 }
51834
51835 for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) {
51836 UA_FieldTargetDataType_clear(&targetVars[index].targetVariable);
51837 }
51838
51839 UA_free(targetVars);
51840 return res;
51841 }
51842
51843 if(subscribedDataSet->content.decoded.type ==
51844 &UA_TYPES[UA_TYPES_SUBSCRIBEDDATASETMIRRORDATATYPE]) {
51845 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51846 "[UA_PubSubManager_addSubscribedDataSet] "
51847 "DataSetMirror is currently not supported");
51848 return UA_STATUSCODE_BADINVALIDARGUMENT;
51849 }
51850
51851 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51852 "[UA_PubSubManager_addSubscribedDataSet] "
51853 "Invalid Type of SubscribedDataSet");
51854 return UA_STATUSCODE_BADINTERNALERROR;
51855}
51856
51857/* Creates DataSetReader configuration from DataSetReader object
51858 *
51859 * @param server UA_Server object that shall be configured
51860 * @param dataSetReaderParameters DataSetReader configuration
51861 * @param writerGroupIdent NodeId of readerGroupParameters, the DataSetReader belongs to */
51862static UA_StatusCode
51863createDataSetReader(UA_Server *server, const UA_DataSetReaderDataType *dsrParams,
51864 UA_NodeId readerGroupIdent) {
51865 UA_DataSetReaderConfig config;
51866 memset(&config, 0, sizeof(UA_DataSetReaderConfig));
51867
51868 config.name = dsrParams->name;
51869 config.publisherId = dsrParams->publisherId;
51870 config.writerGroupId = dsrParams->writerGroupId;
51871 config.dataSetWriterId = dsrParams->dataSetWriterId;
51872 config.dataSetMetaData = dsrParams->dataSetMetaData;
51873 config.dataSetFieldContentMask = dsrParams->dataSetFieldContentMask;
51874 config.messageReceiveTimeout = dsrParams->messageReceiveTimeout;
51875 config.messageSettings = dsrParams->messageSettings;
51876
51877 UA_NodeId dsReaderIdent;
51878 UA_StatusCode res = UA_Server_addDataSetReader(server, readerGroupIdent,
51879 &config, &dsReaderIdent);
51880 if(res == UA_STATUSCODE_GOOD)
51881 res = addSubscribedDataSet(server, dsReaderIdent,
51882 &dsrParams->subscribedDataSet);
51883 if(res != UA_STATUSCODE_GOOD) {
51884 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51885 "[UA_PubSubManager_createDataSetReader] "
51886 "create subscribedDataSet failed");
51887 }
51888
51889 return res;
51890}
51891
51892/* Determines whether PublishedDataSet is of type PublishedItems or PublishedEvents.
51893 * (PublishedEvents are currently not supported!)
51894 *
51895 * @param publishedDataSetParameters PublishedDataSet parameters
51896 * @param config PublishedDataSet configuration object */
51897static UA_StatusCode
51898setPublishedDataSetType(const UA_PublishedDataSetDataType *pdsParams,
51899 UA_PublishedDataSetConfig *config) {
51900 if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
51901 return UA_STATUSCODE_BADINTERNALERROR;
51902
51903 const UA_DataType *sourceType = pdsParams->dataSetSource.content.decoded.type;
51904 if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]) {
51905 config->publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS;
51906 return UA_STATUSCODE_GOOD;
51907 } else if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
51908 /* config.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDEVENTS; */
51909 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51910 "[UA_PubSubManager_setPublishedDataSetType] Published events not supported.");
51911 return UA_STATUSCODE_BADNOTIMPLEMENTED;
51912 }
51913
51914 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51915 "[UA_PubSubManager_setPublishedDataSetType] Invalid DataSetSourceDataType.");
51916 return UA_STATUSCODE_BADINTERNALERROR;
51917}
51918
51919/* Creates PublishedDataSetConfig object from PublishedDataSet object
51920 *
51921 * @param server UA_Server object that shall be configured
51922 * @param pdsParams publishedDataSet configuration
51923 * @param pdsIdent NodeId of the publishedDataSet */
51924static UA_StatusCode
51925createPublishedDataSet(UA_Server *server,
51926 const UA_PublishedDataSetDataType *pdsParams,
51927 UA_NodeId *pdsIdent) {
51928 UA_PublishedDataSetConfig config;
51929 memset(&config, 0, sizeof(UA_PublishedDataSetConfig));
51930
51931 config.name = pdsParams->name;
51932 UA_StatusCode res = setPublishedDataSetType(pdsParams, &config);
51933 if(res != UA_STATUSCODE_GOOD)
51934 return res;
51935
51936 res = UA_Server_addPublishedDataSet(server, &config, pdsIdent).addResult;
51937 if(res != UA_STATUSCODE_GOOD) {
51938 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51939 "[UA_PubSubManager_createPublishedDataSet] "
51940 "Adding PublishedDataSet failed.");
51941 return res;
51942 }
51943
51944 /* DataSetField configuration for this publishedDataSet: */
51945 res = createDataSetFields(server, pdsIdent, pdsParams);
51946 if(res != UA_STATUSCODE_GOOD) {
51947 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51948 "[UA_PubSubManager_createPublishedDataSet] "
51949 "Creating DataSetFieldConfig failed.");
51950 }
51951
51952 return res;
51953}
51954
51955/* Adds DataSetField Variables bound to a certain PublishedDataSet. This method does NOT
51956 * check, whether the PublishedDataSet actually contains Variables instead of Events!
51957 *
51958 * @param server UA_Server object that shall be configured
51959 * @param pdsIdent NodeId of the publishedDataSet, the DataSetField belongs to
51960 * @param publishedDataSetParameters publishedDataSet configuration */
51961static UA_StatusCode
51962addDataSetFieldVariables(UA_Server *server, const UA_NodeId *pdsIdent,
51963 const UA_PublishedDataSetDataType *pdsParams) {
51964 UA_PublishedDataItemsDataType *pdItems = (UA_PublishedDataItemsDataType *)
51965 pdsParams->dataSetSource.content.decoded.data;
51966 if(pdItems->publishedDataSize != pdsParams->dataSetMetaData.fieldsSize)
51967 return UA_STATUSCODE_BADINTERNALERROR;
51968
51969 for(size_t i = 0; i < pdItems->publishedDataSize; i++) {
51970 UA_DataSetFieldConfig fc;
51971 memset(&fc, 0, sizeof(UA_DataSetFieldConfig));
51972 fc.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE;
51973 fc.field.variable.configurationVersion = pdsParams->dataSetMetaData.configurationVersion;
51974 fc.field.variable.fieldNameAlias = pdsParams->dataSetMetaData.fields[i].name;
51975 fc.field.variable.promotedField = pdsParams->dataSetMetaData.
51976 fields[i].fieldFlags & 0x0001;
51977 fc.field.variable.publishParameters = pdItems->publishedData[i];
51978
51979 UA_NodeId fieldIdent;
51980 UA_StatusCode res = UA_Server_addDataSetField(server, *pdsIdent, &fc, &fieldIdent).result;
51981 if(res != UA_STATUSCODE_GOOD) {
51982 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
51983 "[UA_PubSubManager_addDataSetFieldVariables] "
51984 "Adding DataSetField Variable failed.");
51985 return res;
51986 }
51987 }
51988
51989 return UA_STATUSCODE_GOOD;
51990}
51991
51992/* Checks if PublishedDataSet contains event or variable fields and calls the
51993 * corresponding method to add these fields to the server.
51994 *
51995 * @param server UA_Server object that shall be configured
51996 * @param pdsIdent NodeId of the publishedDataSet, the DataSetFields belongs to
51997 * @param pdsParams publishedDataSet configuration */
51998static UA_StatusCode
51999createDataSetFields(UA_Server *server, const UA_NodeId *pdsIdent,
52000 const UA_PublishedDataSetDataType *pdsParams) {
52001 if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED)
52002 return UA_STATUSCODE_BADINTERNALERROR;
52003
52004 if(pdsParams->dataSetSource.content.decoded.type ==
52005 &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE])
52006 return addDataSetFieldVariables(server, pdsIdent, pdsParams);
52007
52008 /* TODO: Implement Routine for adding Event DataSetFields */
52009 if(pdsParams->dataSetSource.content.decoded.type ==
52010 &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) {
52011 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52012 "[UA_PubSubManager_createDataSetFields] "
52013 "Published events not supported.");
52014 return UA_STATUSCODE_BADNOTIMPLEMENTED;
52015 }
52016
52017 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52018 "[UA_PubSubManager_createDataSetFields] "
52019 "Invalid DataSetSourceDataType.");
52020 return UA_STATUSCODE_BADINTERNALERROR;
52021}
52022
52023UA_StatusCode
52024UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server,
52025 const UA_ByteString buffer) {
52026 size_t offset = 0;
52027 UA_ExtensionObject decodedFile;
52028 UA_StatusCode res = UA_ExtensionObject_decodeBinary(&buffer, &offset, &decodedFile);
52029 if(res != UA_STATUSCODE_GOOD) {
52030 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52031 "[UA_decodeBinFile] decoding UA_Binary failed");
52032 goto cleanup;
52033 }
52034
52035 UA_PubSubConfigurationDataType *pubSubConfig = NULL;
52036 res = extractPubSubConfigFromExtensionObject(&decodedFile, &pubSubConfig);
52037 if(res != UA_STATUSCODE_GOOD) {
52038 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52039 "[UA_PubSubManager_loadPubSubConfigFromByteString] "
52040 "Extracting PubSub Configuration failed");
52041 goto cleanup;
52042 }
52043
52044 res = updatePubSubConfig(server, pubSubConfig);
52045 if(res != UA_STATUSCODE_GOOD) {
52046 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52047 "[UA_PubSubManager_loadPubSubConfigFromByteString] "
52048 "Loading PubSub configuration into server failed");
52049 goto cleanup;
52050 }
52051
52052 cleanup:
52053 UA_ExtensionObject_clear(&decodedFile);
52054 return res;
52055}
52056
52057/* Encodes a PubSubConfigurationDataType object as ByteString using the UA Binary Data
52058 * Encoding */
52059static UA_StatusCode
52060encodePubSubConfiguration(UA_PubSubConfigurationDataType *configurationParameters,
52061 UA_ByteString *buffer) {
52062 UA_UABinaryFileDataType binFile;
52063 memset(&binFile, 0, sizeof(UA_UABinaryFileDataType));
52064 /*Perhaps, additional initializations of binFile are necessary here.*/
52065
52066 UA_Variant_setScalar(&binFile.body, configurationParameters,
52067 &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]);
52068
52069 UA_ExtensionObject container;
52070 memset(&container, 0, sizeof(UA_ExtensionObject));
52071 container.encoding = UA_EXTENSIONOBJECT_DECODED;
52072 container.content.decoded.type = &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE];
52073 container.content.decoded.data = &binFile;
52074
52075 size_t fileSize = UA_ExtensionObject_calcSizeBinary(&container);
52076 buffer->data = (UA_Byte*)UA_calloc(fileSize, sizeof(UA_Byte));
52077 if(buffer->data == NULL) {
52078 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52079 "[UA_PubSubManager_encodePubSubConfiguration] Allocating buffer failed");
52080 return UA_STATUSCODE_BADOUTOFMEMORY;
52081 }
52082
52083 buffer->length = fileSize;
52084
52085 UA_Byte *bufferPos = buffer->data;
52086 UA_StatusCode res =
52087 UA_ExtensionObject_encodeBinary(&container, &bufferPos, bufferPos + fileSize);
52088 if(res != UA_STATUSCODE_GOOD) {
52089 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52090 "[UA_PubSubManager_encodePubSubConfiguration] Encoding failed");
52091 }
52092 return res;
52093}
52094
52095static UA_StatusCode
52096generatePublishedDataSetDataType(const UA_PublishedDataSet *src,
52097 UA_PublishedDataSetDataType *dst) {
52098 if(src->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS)
52099 return UA_STATUSCODE_BADNOTIMPLEMENTED;
52100
52101 memset(dst, 0, sizeof(UA_PublishedDataSetDataType));
52102
52103 UA_PublishedDataItemsDataType *tmp = UA_PublishedDataItemsDataType_new();
52104 UA_String_copy(&src->config.name, &dst->name);
52105 dst->dataSetMetaData.fieldsSize = src->fieldSize;
52106
52107 size_t index = 0;
52108 tmp->publishedDataSize = src->fieldSize;
52109 tmp->publishedData = (UA_PublishedVariableDataType*)
52110 UA_Array_new(tmp->publishedDataSize, &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]);
52111 if(tmp->publishedData == NULL) {
52112 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
52113 return UA_STATUSCODE_BADOUTOFMEMORY;
52114 }
52115
52116 dst->dataSetMetaData.fields = (UA_FieldMetaData*)
52117 UA_Array_new(dst->dataSetMetaData.fieldsSize, &UA_TYPES[UA_TYPES_FIELDMETADATA]);
52118 if(dst->dataSetMetaData.fields == NULL) {
52119 UA_free(tmp->publishedData);
52120 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Allocation memory failed");
52121 return UA_STATUSCODE_BADOUTOFMEMORY;
52122 }
52123
52124 UA_DataSetField *dsf, *dsf_tmp = NULL;
52125 TAILQ_FOREACH_SAFE(dsf ,&src->fields, listEntry, dsf_tmp) {
52126 UA_String_copy(&dsf->config.field.variable.fieldNameAlias,
52127 &dst->dataSetMetaData.fields[index].name);
52128 UA_PublishedVariableDataType_copy(&dsf->config.field.variable.publishParameters,
52129 &tmp->publishedData[index]);
52130 UA_ConfigurationVersionDataType_copy(&dsf->config.field.variable.configurationVersion,
52131 &dst->dataSetMetaData.configurationVersion);
52132 dst->dataSetMetaData.fields[index].fieldFlags =
52133 dsf->config.field.variable.promotedField;
52134 index++;
52135 }
52136 UA_ExtensionObject_setValue(&dst->dataSetSource, tmp,
52137 &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]);
52138
52139 return UA_STATUSCODE_GOOD;
52140}
52141
52142static UA_StatusCode
52143generateDataSetWriterDataType(const UA_DataSetWriter *src,
52144 UA_DataSetWriterDataType *dst) {
52145 memset(dst, 0, sizeof(UA_DataSetWriterDataType));
52146
52147 UA_String_copy(&src->config.name, &dst->name);
52148 dst->dataSetWriterId = src->config.dataSetWriterId;
52149 dst->keyFrameCount = src->config.keyFrameCount;
52150 dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
52151 UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
52152 UA_String_copy(&src->config.dataSetName, &dst->dataSetName);
52153
52154 dst->dataSetWriterPropertiesSize = src->config.dataSetWriterPropertiesSize;
52155 for(size_t i = 0; i < src->config.dataSetWriterPropertiesSize; i++) {
52156 UA_KeyValuePair_copy(&src->config.dataSetWriterProperties[i],
52157 &dst->dataSetWriterProperties[i]);
52158 }
52159
52160 return UA_STATUSCODE_GOOD;
52161}
52162
52163static UA_StatusCode
52164generateWriterGroupDataType(const UA_WriterGroup *src,
52165 UA_WriterGroupDataType *dst) {
52166 memset(dst, 0, sizeof(UA_WriterGroupDataType));
52167
52168 UA_String_copy(&src->config.name, &dst->name);
52169 dst->enabled = src->config.enabled;
52170 dst->writerGroupId = src->config.writerGroupId;
52171 dst->publishingInterval = src->config.publishingInterval;
52172 dst->keepAliveTime = src->config.keepAliveTime;
52173 dst->priority = src->config.priority;
52174 dst->securityMode = src->config.securityMode;
52175
52176 UA_ExtensionObject_copy(&src->config.transportSettings, &dst->transportSettings);
52177 UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
52178
52179 dst->groupPropertiesSize = src->config.groupPropertiesSize;
52180 dst->groupProperties = (UA_KeyValuePair*)
52181 UA_Array_new(dst->groupPropertiesSize, &UA_TYPES[UA_TYPES_KEYVALUEPAIR]);
52182 for(size_t index = 0; index < dst->groupPropertiesSize; index++) {
52183 UA_KeyValuePair_copy(&src->config.groupProperties[index],
52184 &dst->groupProperties[index]);
52185 }
52186
52187 dst->dataSetWriters = (UA_DataSetWriterDataType*)
52188 UA_calloc(src->writersCount, sizeof(UA_DataSetWriterDataType));
52189 if(!dst->dataSetWriters)
52190 return UA_STATUSCODE_BADOUTOFMEMORY;
52191
52192 dst->dataSetWritersSize = src->writersCount;
52193
52194 UA_DataSetWriter *dsw;
52195 size_t dsWriterIndex = 0;
52196 LIST_FOREACH(dsw, &src->writers, listEntry) {
52197 UA_StatusCode res =
52198 generateDataSetWriterDataType(dsw, &dst->dataSetWriters[dsWriterIndex]);
52199 if(res != UA_STATUSCODE_GOOD)
52200 return res;
52201 dsWriterIndex++;
52202 }
52203
52204 return UA_STATUSCODE_GOOD;
52205}
52206
52207static UA_StatusCode
52208generateDataSetReaderDataType(const UA_DataSetReader *src,
52209 UA_DataSetReaderDataType *dst) {
52210 UA_StatusCode res = UA_STATUSCODE_GOOD;
52211 memset(dst, 0, sizeof(UA_DataSetReaderDataType));
52212 dst->writerGroupId = src->config.writerGroupId;
52213 dst->dataSetWriterId = src->config.dataSetWriterId;
52214 dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask;
52215 dst->messageReceiveTimeout = src->config.messageReceiveTimeout;
52216 res |= UA_String_copy(&src->config.name, &dst->name);
52217 res |= UA_Variant_copy(&src->config.publisherId, &dst->publisherId);
52218 res |= UA_DataSetMetaDataType_copy(&src->config.dataSetMetaData,
52219 &dst->dataSetMetaData);
52220 res |= UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings);
52221
52222 UA_TargetVariablesDataType *tmpTarget = UA_TargetVariablesDataType_new();
52223 if(!tmpTarget)
52224 return UA_STATUSCODE_BADOUTOFMEMORY;
52225 UA_ExtensionObject_setValue(&dst->subscribedDataSet, tmpTarget,
52226 &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]);
52227
52228 const UA_TargetVariables *targets =
52229 &src->config.subscribedDataSet.subscribedDataSetTarget;
52230 tmpTarget->targetVariables = (UA_FieldTargetDataType *)
52231 UA_calloc(targets->targetVariablesSize, sizeof(UA_FieldTargetDataType));
52232 if(!tmpTarget->targetVariables)
52233 return UA_STATUSCODE_BADOUTOFMEMORY;
52234 tmpTarget->targetVariablesSize = targets->targetVariablesSize;
52235
52236 for(size_t i = 0; i < tmpTarget->targetVariablesSize; i++) {
52237 res |= UA_FieldTargetDataType_copy(&targets->targetVariables[i].targetVariable,
52238 &tmpTarget->targetVariables[i]);
52239 }
52240
52241 return res;
52242}
52243
52244static UA_StatusCode
52245generateReaderGroupDataType(const UA_ReaderGroup *src,
52246 UA_ReaderGroupDataType *dst) {
52247 memset(dst, 0, sizeof(UA_ReaderGroupDataType));
52248
52249 UA_String_copy(&src->config.name, &dst->name);
52250 dst->dataSetReaders = (UA_DataSetReaderDataType*)
52251 UA_calloc(src->readersCount, sizeof(UA_DataSetReaderDataType));
52252 if(dst->dataSetReaders == NULL)
52253 return UA_STATUSCODE_BADOUTOFMEMORY;
52254 dst->dataSetReadersSize = src->readersCount;
52255
52256 size_t i = 0;
52257 UA_DataSetReader *dsr, *dsr_tmp = NULL;
52258 LIST_FOREACH_SAFE(dsr, &src->readers, listEntry, dsr_tmp) {
52259 UA_StatusCode res =
52260 generateDataSetReaderDataType(dsr, &dst->dataSetReaders[i]);
52261 if(res != UA_STATUSCODE_GOOD)
52262 return res;
52263 i++;
52264 }
52265
52266 return UA_STATUSCODE_GOOD;
52267}
52268
52269/* Generates a PubSubConnectionDataType object from a PubSubConnection. */
52270static UA_StatusCode
52271generatePubSubConnectionDataType(const UA_PubSubConnection *src,
52272 UA_PubSubConnectionDataType *dst) {
52273 memset(dst, 0, sizeof(UA_PubSubConnectionDataType));
52274
52275 UA_String_copy(&src->config->name, &dst->name);
52276 UA_String_copy(&src->config->transportProfileUri, &dst->transportProfileUri);
52277 dst->enabled = src->config->enabled;
52278
52279 dst->connectionPropertiesSize = src->config->connectionPropertiesSize;
52280 for(size_t i = 0; i < src->config->connectionPropertiesSize; i++) {
52281 UA_KeyValuePair_copy(&src->config->connectionProperties[i],
52282 &dst->connectionProperties[i]);
52283 }
52284
52285 if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_NUMERIC) {
52286 UA_Variant_setScalarCopy(&dst->publisherId,
52287 &src->config->publisherId.numeric,
52288 &UA_TYPES[UA_TYPES_UINT32]);
52289 } else if(src->config->publisherIdType == UA_PUBSUB_PUBLISHERID_STRING) {
52290 UA_Variant_setScalarCopy(&dst->publisherId,
52291 &src->config->publisherId.string,
52292 &UA_TYPES[UA_TYPES_STRING]);
52293 }
52294
52295 /* Possibly, array size and dimensions of src->config->address and
52296 * src->config->connectionTransportSettings should be checked beforehand. */
52297 dst->address.encoding = UA_EXTENSIONOBJECT_DECODED;
52298 dst->address.content.decoded.type = src->config->address.type;
52299 UA_StatusCode res =
52300 UA_Array_copy(src->config->address.data, 1,
52301 &dst->address.content.decoded.data, src->config->address.type);
52302 if(res != UA_STATUSCODE_GOOD)
52303 return res;
52304
52305 if(src->config->connectionTransportSettings.data) {
52306 dst->transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
52307 dst->transportSettings.content.decoded.type =
52308 src->config->connectionTransportSettings.type;
52309 res = UA_Array_copy(src->config->connectionTransportSettings.data, 1,
52310 &dst->transportSettings.content.decoded.data,
52311 src->config->connectionTransportSettings.type);
52312
52313 if(res != UA_STATUSCODE_GOOD)
52314 return res;
52315 }
52316
52317 dst->writerGroups = (UA_WriterGroupDataType*)
52318 UA_calloc(src->writerGroupsSize, sizeof(UA_WriterGroupDataType));
52319 if(dst->writerGroups == NULL) {
52320 return UA_STATUSCODE_BADOUTOFMEMORY;
52321 }
52322
52323 dst->writerGroupsSize = src->writerGroupsSize;
52324 UA_WriterGroup *wg, *wg_tmp = NULL;
52325 size_t wgIndex = 0;
52326 LIST_FOREACH_SAFE(wg ,&src->writerGroups, listEntry, wg_tmp) {
52327 res = generateWriterGroupDataType(wg, &dst->writerGroups[wgIndex]);
52328 if(res != UA_STATUSCODE_GOOD)
52329 return res;
52330 wgIndex++;
52331 }
52332
52333 dst->readerGroups = (UA_ReaderGroupDataType*)
52334 UA_calloc(src->readerGroupsSize, sizeof(UA_ReaderGroupDataType));
52335 if(dst->readerGroups == NULL) {
52336 return UA_STATUSCODE_BADOUTOFMEMORY;
52337 }
52338
52339 dst->readerGroupsSize = src->readerGroupsSize;
52340 UA_ReaderGroup *rg = NULL;
52341 size_t rgIndex = 0;
52342 LIST_FOREACH(rg, &src->readerGroups, listEntry) {
52343 res = generateReaderGroupDataType(rg, &dst->readerGroups[rgIndex]);
52344 if(res != UA_STATUSCODE_GOOD)
52345 return res;
52346 rgIndex++;
52347 }
52348
52349 return UA_STATUSCODE_GOOD;
52350}
52351
52352UA_StatusCode
52353generatePubSubConfigurationDataType(const UA_Server* server,
52354 UA_PubSubConfigurationDataType *configDT) {
52355 UA_StatusCode res = UA_STATUSCODE_GOOD;
52356 const UA_PubSubManager *manager = &server->pubSubManager;
52357 memset(configDT, 0, sizeof(UA_PubSubConfigurationDataType));
52358
52359 configDT->publishedDataSets = (UA_PublishedDataSetDataType*)
52360 UA_calloc(manager->publishedDataSetsSize,
52361 sizeof(UA_PublishedDataSetDataType));
52362 if(configDT->publishedDataSets == NULL)
52363 return UA_STATUSCODE_BADOUTOFMEMORY;
52364 configDT->publishedDataSetsSize = manager->publishedDataSetsSize;
52365
52366 UA_PublishedDataSet *pds;
52367 UA_UInt32 pdsIndex = 0;
52368 TAILQ_FOREACH(pds, &manager->publishedDataSets, listEntry) {
52369 UA_PublishedDataSetDataType *dst = &configDT->publishedDataSets[pdsIndex];
52370 res = generatePublishedDataSetDataType(pds, dst);
52371 if(res != UA_STATUSCODE_GOOD) {
52372 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52373 "[UA_PubSubManager_generatePubSubConfigurationDataType] "
52374 "retrieving PublishedDataSet configuration failed");
52375 return res;
52376 }
52377 pdsIndex++;
52378 }
52379
52380 configDT->connections = (UA_PubSubConnectionDataType*)
52381 UA_calloc(manager->connectionsSize, sizeof(UA_PubSubConnectionDataType));
52382 if(configDT->connections == NULL)
52383 return UA_STATUSCODE_BADOUTOFMEMORY;
52384 configDT->connectionsSize = manager->connectionsSize;
52385
52386 UA_UInt32 connectionIndex = 0;
52387 UA_PubSubConnection *connection;
52388 TAILQ_FOREACH(connection, &manager->connections, listEntry) {
52389 UA_PubSubConnectionDataType *cdt = &configDT->connections[connectionIndex];
52390 res = generatePubSubConnectionDataType(connection, cdt);
52391 if(res != UA_STATUSCODE_GOOD) {
52392 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52393 "[UA_PubSubManager_generatePubSubConfigurationDataType] "
52394 "retrieving PubSubConnection configuration failed");
52395 return res;
52396 }
52397 connectionIndex++;
52398 }
52399
52400 return UA_STATUSCODE_GOOD;
52401}
52402
52403UA_StatusCode
52404UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server,
52405 UA_ByteString *buffer) {
52406 UA_PubSubConfigurationDataType config;
52407 memset(&config, 0, sizeof(UA_PubSubConfigurationDataType));
52408
52409 UA_StatusCode res = generatePubSubConfigurationDataType(server, &config);
52410 if(res != UA_STATUSCODE_GOOD) {
52411 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52412 "retrieving PubSub configuration from server failed");
52413 goto cleanup;
52414 }
52415
52416 res = encodePubSubConfiguration(&config, buffer);
52417 if(res != UA_STATUSCODE_GOOD) {
52418 UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52419 "encoding PubSub configuration failed");
52420 goto cleanup;
52421 }
52422
52423 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
52424 "Saving PubSub config was successful");
52425
52426 cleanup:
52427 UA_PubSubConfigurationDataType_clear(&config);
52428 return res;
52429}
52430
52431#endif /* UA_ENABLE_PUBSUB_FILE_CONFIG */
52432
52433/**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.c" ****/
52434
52435/* WARNING: This is a generated file.
52436 * Any manual changes will be overwritten. */
52437
52438
52439
52440/* HasAddIn - ns=0;i=17604 */
52441
52442static UA_StatusCode function_namespace0_generated_0_begin(UA_Server *server, UA_UInt16* ns) {
52443UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52444UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52445attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AddInOf");
52446attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasAddIn");
52447retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52448requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU),
52449parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52450referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52451browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasAddIn"),
52452 typeDefinition: UA_NODEID_NULL,
52453attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52454return retVal;
52455}
52456
52457static UA_StatusCode function_namespace0_generated_0_finish(UA_Server *server, UA_UInt16* ns) {
52458return UA_Server_addNode_finish(server,
52459nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU)
52460);
52461}
52462
52463/* HasHistoricalConfiguration - ns=0;i=56 */
52464
52465static UA_StatusCode function_namespace0_generated_1_begin(UA_Server *server, UA_UInt16* ns) {
52466UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52467UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52468attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "HistoricalConfigurationOf");
52469attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasHistoricalConfiguration");
52470retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52471requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU),
52472parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 44LU),
52473referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52474browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasHistoricalConfiguration"),
52475 typeDefinition: UA_NODEID_NULL,
52476attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52477return retVal;
52478}
52479
52480static UA_StatusCode function_namespace0_generated_1_finish(UA_Server *server, UA_UInt16* ns) {
52481return UA_Server_addNode_finish(server,
52482nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU)
52483);
52484}
52485
52486/* HasEffect - ns=0;i=54 */
52487
52488static UA_StatusCode function_namespace0_generated_2_begin(UA_Server *server, UA_UInt16* ns) {
52489UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52490UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52491attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeEffectedBy");
52492attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasEffect");
52493retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52494requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU),
52495parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52496referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52497browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasEffect"),
52498 typeDefinition: UA_NODEID_NULL,
52499attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52500return retVal;
52501}
52502
52503static UA_StatusCode function_namespace0_generated_2_finish(UA_Server *server, UA_UInt16* ns) {
52504return UA_Server_addNode_finish(server,
52505nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU)
52506);
52507}
52508
52509/* HasCause - ns=0;i=53 */
52510
52511static UA_StatusCode function_namespace0_generated_3_begin(UA_Server *server, UA_UInt16* ns) {
52512UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52513UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52514attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeCausedBy");
52515attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasCause");
52516retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52517requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU),
52518parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52519referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52520browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasCause"),
52521 typeDefinition: UA_NODEID_NULL,
52522attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52523return retVal;
52524}
52525
52526static UA_StatusCode function_namespace0_generated_3_finish(UA_Server *server, UA_UInt16* ns) {
52527return UA_Server_addNode_finish(server,
52528nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU)
52529);
52530}
52531
52532/* ToState - ns=0;i=52 */
52533
52534static UA_StatusCode function_namespace0_generated_4_begin(UA_Server *server, UA_UInt16* ns) {
52535UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52536UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52537attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "FromTransition");
52538attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ToState");
52539retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52540requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU),
52541parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52542referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52543browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ToState"),
52544 typeDefinition: UA_NODEID_NULL,
52545attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52546return retVal;
52547}
52548
52549static UA_StatusCode function_namespace0_generated_4_finish(UA_Server *server, UA_UInt16* ns) {
52550return UA_Server_addNode_finish(server,
52551nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU)
52552);
52553}
52554
52555/* FromState - ns=0;i=51 */
52556
52557static UA_StatusCode function_namespace0_generated_5_begin(UA_Server *server, UA_UInt16* ns) {
52558UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52559UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default;
52560attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "ToTransition");
52561attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FromState");
52562retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE,
52563requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU),
52564parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU),
52565referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52566browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FromState"),
52567 typeDefinition: UA_NODEID_NULL,
52568attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL);
52569return retVal;
52570}
52571
52572static UA_StatusCode function_namespace0_generated_5_finish(UA_Server *server, UA_UInt16* ns) {
52573return UA_Server_addNode_finish(server,
52574nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU)
52575);
52576}
52577
52578/* DiagnosticInfo - ns=0;i=25 */
52579
52580static UA_StatusCode function_namespace0_generated_6_begin(UA_Server *server, UA_UInt16* ns) {
52581UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52582UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52583attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiagnosticInfo");
52584retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52585requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU),
52586parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52587referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52588browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiagnosticInfo"),
52589 typeDefinition: UA_NODEID_NULL,
52590attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52591return retVal;
52592}
52593
52594static UA_StatusCode function_namespace0_generated_6_finish(UA_Server *server, UA_UInt16* ns) {
52595return UA_Server_addNode_finish(server,
52596nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU)
52597);
52598}
52599
52600/* DataValue - ns=0;i=23 */
52601
52602static UA_StatusCode function_namespace0_generated_7_begin(UA_Server *server, UA_UInt16* ns) {
52603UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52604UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52605attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataValue");
52606retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52607requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU),
52608parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52609referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52610browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataValue"),
52611 typeDefinition: UA_NODEID_NULL,
52612attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52613return retVal;
52614}
52615
52616static UA_StatusCode function_namespace0_generated_7_finish(UA_Server *server, UA_UInt16* ns) {
52617return UA_Server_addNode_finish(server,
52618nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU)
52619);
52620}
52621
52622/* Structure - ns=0;i=22 */
52623
52624static UA_StatusCode function_namespace0_generated_8_begin(UA_Server *server, UA_UInt16* ns) {
52625UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52626UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52627attr.isAbstract = true;
52628attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Structure");
52629retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52630requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52631parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52632referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52633browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Structure"),
52634 typeDefinition: UA_NODEID_NULL,
52635attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52636return retVal;
52637}
52638
52639static UA_StatusCode function_namespace0_generated_8_finish(UA_Server *server, UA_UInt16* ns) {
52640return UA_Server_addNode_finish(server,
52641nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU)
52642);
52643}
52644
52645/* TimeZoneDataType - ns=0;i=8912 */
52646
52647static UA_StatusCode function_namespace0_generated_9_begin(UA_Server *server, UA_UInt16* ns) {
52648UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52649UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52650attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TimeZoneDataType");
52651retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52652requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU),
52653parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52654referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52655browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TimeZoneDataType"),
52656 typeDefinition: UA_NODEID_NULL,
52657attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52658return retVal;
52659}
52660
52661static UA_StatusCode function_namespace0_generated_9_finish(UA_Server *server, UA_UInt16* ns) {
52662return UA_Server_addNode_finish(server,
52663nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU)
52664);
52665}
52666
52667/* EUInformation - ns=0;i=887 */
52668
52669static UA_StatusCode function_namespace0_generated_10_begin(UA_Server *server, UA_UInt16* ns) {
52670UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52671UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52672attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EUInformation");
52673retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52674requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU),
52675parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52676referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52677browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EUInformation"),
52678 typeDefinition: UA_NODEID_NULL,
52679attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52680return retVal;
52681}
52682
52683static UA_StatusCode function_namespace0_generated_10_finish(UA_Server *server, UA_UInt16* ns) {
52684return UA_Server_addNode_finish(server,
52685nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU)
52686);
52687}
52688
52689/* Range - ns=0;i=884 */
52690
52691static UA_StatusCode function_namespace0_generated_11_begin(UA_Server *server, UA_UInt16* ns) {
52692UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52693UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52694attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Range");
52695retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52696requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU),
52697parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52698referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52699browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Range"),
52700 typeDefinition: UA_NODEID_NULL,
52701attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52702return retVal;
52703}
52704
52705static UA_StatusCode function_namespace0_generated_11_finish(UA_Server *server, UA_UInt16* ns) {
52706return UA_Server_addNode_finish(server,
52707nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU)
52708);
52709}
52710
52711/* ServerStatusDataType - ns=0;i=862 */
52712
52713static UA_StatusCode function_namespace0_generated_12_begin(UA_Server *server, UA_UInt16* ns) {
52714UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52715UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52716attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusDataType");
52717retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52718requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU),
52719parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52720referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52721browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusDataType"),
52722 typeDefinition: UA_NODEID_NULL,
52723attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52724return retVal;
52725}
52726
52727static UA_StatusCode function_namespace0_generated_12_finish(UA_Server *server, UA_UInt16* ns) {
52728return UA_Server_addNode_finish(server,
52729nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU)
52730);
52731}
52732
52733/* EnumValueType - ns=0;i=7594 */
52734
52735static UA_StatusCode function_namespace0_generated_13_begin(UA_Server *server, UA_UInt16* ns) {
52736UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52737UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52738attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType");
52739retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52740requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU),
52741parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52742referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52743browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"),
52744 typeDefinition: UA_NODEID_NULL,
52745attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52746return retVal;
52747}
52748
52749static UA_StatusCode function_namespace0_generated_13_finish(UA_Server *server, UA_UInt16* ns) {
52750return UA_Server_addNode_finish(server,
52751nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU)
52752);
52753}
52754
52755/* SignedSoftwareCertificate - ns=0;i=344 */
52756
52757static UA_StatusCode function_namespace0_generated_14_begin(UA_Server *server, UA_UInt16* ns) {
52758UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52759UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52760attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SignedSoftwareCertificate");
52761retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52762requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU),
52763parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52764referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52765browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SignedSoftwareCertificate"),
52766 typeDefinition: UA_NODEID_NULL,
52767attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52768return retVal;
52769}
52770
52771static UA_StatusCode function_namespace0_generated_14_finish(UA_Server *server, UA_UInt16* ns) {
52772return UA_Server_addNode_finish(server,
52773nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU)
52774);
52775}
52776
52777/* BuildInfo - ns=0;i=338 */
52778
52779static UA_StatusCode function_namespace0_generated_15_begin(UA_Server *server, UA_UInt16* ns) {
52780UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52781UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52782attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo");
52783retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52784requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU),
52785parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52786referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52787browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"),
52788 typeDefinition: UA_NODEID_NULL,
52789attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52790return retVal;
52791}
52792
52793static UA_StatusCode function_namespace0_generated_15_finish(UA_Server *server, UA_UInt16* ns) {
52794return UA_Server_addNode_finish(server,
52795nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU)
52796);
52797}
52798
52799/* Argument - ns=0;i=296 */
52800
52801static UA_StatusCode function_namespace0_generated_16_begin(UA_Server *server, UA_UInt16* ns) {
52802UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52803UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52804attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument");
52805retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52806requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU),
52807parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52808referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52809browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"),
52810 typeDefinition: UA_NODEID_NULL,
52811attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52812return retVal;
52813}
52814
52815static UA_StatusCode function_namespace0_generated_16_finish(UA_Server *server, UA_UInt16* ns) {
52816return UA_Server_addNode_finish(server,
52817nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU)
52818);
52819}
52820
52821/* Union - ns=0;i=12756 */
52822
52823static UA_StatusCode function_namespace0_generated_17_begin(UA_Server *server, UA_UInt16* ns) {
52824UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52825UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52826attr.isAbstract = true;
52827attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Union");
52828retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52829requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU),
52830parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU),
52831referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52832browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Union"),
52833 typeDefinition: UA_NODEID_NULL,
52834attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52835return retVal;
52836}
52837
52838static UA_StatusCode function_namespace0_generated_17_finish(UA_Server *server, UA_UInt16* ns) {
52839return UA_Server_addNode_finish(server,
52840nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU)
52841);
52842}
52843
52844/* LocalizedText - ns=0;i=21 */
52845
52846static UA_StatusCode function_namespace0_generated_18_begin(UA_Server *server, UA_UInt16* ns) {
52847UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52848UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52849attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalizedText");
52850retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52851requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU),
52852parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52853referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52854browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalizedText"),
52855 typeDefinition: UA_NODEID_NULL,
52856attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52857return retVal;
52858}
52859
52860static UA_StatusCode function_namespace0_generated_18_finish(UA_Server *server, UA_UInt16* ns) {
52861return UA_Server_addNode_finish(server,
52862nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU)
52863);
52864}
52865
52866/* QualifiedName - ns=0;i=20 */
52867
52868static UA_StatusCode function_namespace0_generated_19_begin(UA_Server *server, UA_UInt16* ns) {
52869UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52870UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52871attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QualifiedName");
52872retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52873requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU),
52874parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52875referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52876browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QualifiedName"),
52877 typeDefinition: UA_NODEID_NULL,
52878attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52879return retVal;
52880}
52881
52882static UA_StatusCode function_namespace0_generated_19_finish(UA_Server *server, UA_UInt16* ns) {
52883return UA_Server_addNode_finish(server,
52884nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU)
52885);
52886}
52887
52888/* StatusCode - ns=0;i=19 */
52889
52890static UA_StatusCode function_namespace0_generated_20_begin(UA_Server *server, UA_UInt16* ns) {
52891UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52892UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52893attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StatusCode");
52894retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52895requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU),
52896parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52897referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52898browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StatusCode"),
52899 typeDefinition: UA_NODEID_NULL,
52900attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52901return retVal;
52902}
52903
52904static UA_StatusCode function_namespace0_generated_20_finish(UA_Server *server, UA_UInt16* ns) {
52905return UA_Server_addNode_finish(server,
52906nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU)
52907);
52908}
52909
52910/* ExpandedNodeId - ns=0;i=18 */
52911
52912static UA_StatusCode function_namespace0_generated_21_begin(UA_Server *server, UA_UInt16* ns) {
52913UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52914UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52915attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExpandedNodeId");
52916retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52917requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU),
52918parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52919referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52920browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExpandedNodeId"),
52921 typeDefinition: UA_NODEID_NULL,
52922attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52923return retVal;
52924}
52925
52926static UA_StatusCode function_namespace0_generated_21_finish(UA_Server *server, UA_UInt16* ns) {
52927return UA_Server_addNode_finish(server,
52928nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU)
52929);
52930}
52931
52932/* NodeId - ns=0;i=17 */
52933
52934static UA_StatusCode function_namespace0_generated_22_begin(UA_Server *server, UA_UInt16* ns) {
52935UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52936UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52937attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NodeId");
52938retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52939requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU),
52940parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52941referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52942browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NodeId"),
52943 typeDefinition: UA_NODEID_NULL,
52944attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52945return retVal;
52946}
52947
52948static UA_StatusCode function_namespace0_generated_22_finish(UA_Server *server, UA_UInt16* ns) {
52949return UA_Server_addNode_finish(server,
52950nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU)
52951);
52952}
52953
52954/* XmlElement - ns=0;i=16 */
52955
52956static UA_StatusCode function_namespace0_generated_23_begin(UA_Server *server, UA_UInt16* ns) {
52957UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52958UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52959attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XmlElement");
52960retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52961requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU),
52962parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52963referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52964browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XmlElement"),
52965 typeDefinition: UA_NODEID_NULL,
52966attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52967return retVal;
52968}
52969
52970static UA_StatusCode function_namespace0_generated_23_finish(UA_Server *server, UA_UInt16* ns) {
52971return UA_Server_addNode_finish(server,
52972nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU)
52973);
52974}
52975
52976/* ByteString - ns=0;i=15 */
52977
52978static UA_StatusCode function_namespace0_generated_24_begin(UA_Server *server, UA_UInt16* ns) {
52979UA_StatusCode retVal = UA_STATUSCODE_GOOD;
52980UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
52981attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ByteString");
52982retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
52983requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU),
52984parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
52985referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
52986browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ByteString"),
52987 typeDefinition: UA_NODEID_NULL,
52988attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
52989return retVal;
52990}
52991
52992static UA_StatusCode function_namespace0_generated_24_finish(UA_Server *server, UA_UInt16* ns) {
52993return UA_Server_addNode_finish(server,
52994nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU)
52995);
52996}
52997
52998/* Image - ns=0;i=30 */
52999
53000static UA_StatusCode function_namespace0_generated_25_begin(UA_Server *server, UA_UInt16* ns) {
53001UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53002UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53003attr.isAbstract = true;
53004attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Image");
53005retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53006requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU),
53007parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU),
53008referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53009browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Image"),
53010 typeDefinition: UA_NODEID_NULL,
53011attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53012return retVal;
53013}
53014
53015static UA_StatusCode function_namespace0_generated_25_finish(UA_Server *server, UA_UInt16* ns) {
53016return UA_Server_addNode_finish(server,
53017nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU)
53018);
53019}
53020
53021/* Guid - ns=0;i=14 */
53022
53023static UA_StatusCode function_namespace0_generated_26_begin(UA_Server *server, UA_UInt16* ns) {
53024UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53025UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53026attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Guid");
53027retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53028requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU),
53029parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53030referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53031browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Guid"),
53032 typeDefinition: UA_NODEID_NULL,
53033attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53034return retVal;
53035}
53036
53037static UA_StatusCode function_namespace0_generated_26_finish(UA_Server *server, UA_UInt16* ns) {
53038return UA_Server_addNode_finish(server,
53039nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU)
53040);
53041}
53042
53043/* DateTime - ns=0;i=13 */
53044
53045static UA_StatusCode function_namespace0_generated_27_begin(UA_Server *server, UA_UInt16* ns) {
53046UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53047UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53048attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DateTime");
53049retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53050requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU),
53051parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53052referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53053browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DateTime"),
53054 typeDefinition: UA_NODEID_NULL,
53055attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53056return retVal;
53057}
53058
53059static UA_StatusCode function_namespace0_generated_27_finish(UA_Server *server, UA_UInt16* ns) {
53060return UA_Server_addNode_finish(server,
53061nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU)
53062);
53063}
53064
53065/* UtcTime - ns=0;i=294 */
53066
53067static UA_StatusCode function_namespace0_generated_28_begin(UA_Server *server, UA_UInt16* ns) {
53068UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53069UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53070attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UtcTime");
53071retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53072requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU),
53073parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU),
53074referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53075browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UtcTime"),
53076 typeDefinition: UA_NODEID_NULL,
53077attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53078return retVal;
53079}
53080
53081static UA_StatusCode function_namespace0_generated_28_finish(UA_Server *server, UA_UInt16* ns) {
53082return UA_Server_addNode_finish(server,
53083nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU)
53084);
53085}
53086
53087/* String - ns=0;i=12 */
53088
53089static UA_StatusCode function_namespace0_generated_29_begin(UA_Server *server, UA_UInt16* ns) {
53090UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53091UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53092attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "String");
53093retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53094requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU),
53095parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53096referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53097browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "String"),
53098 typeDefinition: UA_NODEID_NULL,
53099attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53100return retVal;
53101}
53102
53103static UA_StatusCode function_namespace0_generated_29_finish(UA_Server *server, UA_UInt16* ns) {
53104return UA_Server_addNode_finish(server,
53105nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU)
53106);
53107}
53108
53109/* LocaleId - ns=0;i=295 */
53110
53111static UA_StatusCode function_namespace0_generated_30_begin(UA_Server *server, UA_UInt16* ns) {
53112UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53113UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53114attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleId");
53115retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53116requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU),
53117parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU),
53118referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53119browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleId"),
53120 typeDefinition: UA_NODEID_NULL,
53121attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53122return retVal;
53123}
53124
53125static UA_StatusCode function_namespace0_generated_30_finish(UA_Server *server, UA_UInt16* ns) {
53126return UA_Server_addNode_finish(server,
53127nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU)
53128);
53129}
53130
53131/* Boolean - ns=0;i=1 */
53132
53133static UA_StatusCode function_namespace0_generated_31_begin(UA_Server *server, UA_UInt16* ns) {
53134UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53135UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53136attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Boolean");
53137retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53138requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU),
53139parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53140referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53141browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Boolean"),
53142 typeDefinition: UA_NODEID_NULL,
53143attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53144return retVal;
53145}
53146
53147static UA_StatusCode function_namespace0_generated_31_finish(UA_Server *server, UA_UInt16* ns) {
53148return UA_Server_addNode_finish(server,
53149nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU)
53150);
53151}
53152
53153/* Enumeration - ns=0;i=29 */
53154
53155static UA_StatusCode function_namespace0_generated_32_begin(UA_Server *server, UA_UInt16* ns) {
53156UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53157UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53158attr.isAbstract = true;
53159attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Enumeration");
53160retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53161requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53162parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53163referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53164browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Enumeration"),
53165 typeDefinition: UA_NODEID_NULL,
53166attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53167return retVal;
53168}
53169
53170static UA_StatusCode function_namespace0_generated_32_finish(UA_Server *server, UA_UInt16* ns) {
53171return UA_Server_addNode_finish(server,
53172nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU)
53173);
53174}
53175
53176/* ServerState - ns=0;i=852 */
53177
53178static UA_StatusCode function_namespace0_generated_33_begin(UA_Server *server, UA_UInt16* ns) {
53179UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53180UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53181attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerState");
53182retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53183requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU),
53184parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53185referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53186browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerState"),
53187 typeDefinition: UA_NODEID_NULL,
53188attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53189return retVal;
53190}
53191
53192static UA_StatusCode function_namespace0_generated_33_finish(UA_Server *server, UA_UInt16* ns) {
53193return UA_Server_addNode_finish(server,
53194nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU)
53195);
53196}
53197
53198/* RedundancySupport - ns=0;i=851 */
53199
53200static UA_StatusCode function_namespace0_generated_34_begin(UA_Server *server, UA_UInt16* ns) {
53201UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53202UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53203attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
53204retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53205requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU),
53206parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53207referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53208browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
53209 typeDefinition: UA_NODEID_NULL,
53210attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53211return retVal;
53212}
53213
53214static UA_StatusCode function_namespace0_generated_34_finish(UA_Server *server, UA_UInt16* ns) {
53215return UA_Server_addNode_finish(server,
53216nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU)
53217);
53218}
53219
53220/* EnumStrings - ns=0;i=7611 */
53221
53222static UA_StatusCode function_namespace0_generated_35_begin(UA_Server *server, UA_UInt16* ns) {
53223UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53224UA_VariableAttributes attr = UA_VariableAttributes_default;
53225attr.minimumSamplingInterval = 0.000000;
53226attr.userAccessLevel = 1;
53227attr.accessLevel = 1;
53228attr.valueRank = 1;
53229attr.arrayDimensionsSize = 1;
53230UA_UInt32 arrayDimensions[1];
53231arrayDimensions[0] = 0;
53232attr.arrayDimensions = &arrayDimensions[0];
53233attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53234UA_LocalizedText variablenode_ns_0_i_7611_variant_DataContents[6];
53235variablenode_ns_0_i_7611_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: "None");
53236variablenode_ns_0_i_7611_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: "Cold");
53237variablenode_ns_0_i_7611_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: "Warm");
53238variablenode_ns_0_i_7611_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: "Hot");
53239variablenode_ns_0_i_7611_variant_DataContents[4] = UA_LOCALIZEDTEXT(locale: "", text: "Transparent");
53240variablenode_ns_0_i_7611_variant_DataContents[5] = UA_LOCALIZEDTEXT(locale: "", text: "HotAndMirrored");
53241UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_7611_variant_DataContents, arraySize: (UA_Int32) 6, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
53242attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53243retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53244requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU),
53245parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU),
53246referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53247browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53248typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53249attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53250return retVal;
53251}
53252
53253static UA_StatusCode function_namespace0_generated_35_finish(UA_Server *server, UA_UInt16* ns) {
53254return UA_Server_addNode_finish(server,
53255nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU)
53256);
53257}
53258
53259/* AxisScaleEnumeration - ns=0;i=12077 */
53260
53261static UA_StatusCode function_namespace0_generated_36_begin(UA_Server *server, UA_UInt16* ns) {
53262UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53263UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53264attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AxisScaleEnumeration");
53265retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53266requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU),
53267parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53268referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53269browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AxisScaleEnumeration"),
53270 typeDefinition: UA_NODEID_NULL,
53271attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53272return retVal;
53273}
53274
53275static UA_StatusCode function_namespace0_generated_36_finish(UA_Server *server, UA_UInt16* ns) {
53276return UA_Server_addNode_finish(server,
53277nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU)
53278);
53279}
53280
53281/* EnumStrings - ns=0;i=12078 */
53282
53283static UA_StatusCode function_namespace0_generated_37_begin(UA_Server *server, UA_UInt16* ns) {
53284UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53285UA_VariableAttributes attr = UA_VariableAttributes_default;
53286attr.minimumSamplingInterval = 0.000000;
53287attr.userAccessLevel = 1;
53288attr.accessLevel = 1;
53289attr.valueRank = 1;
53290attr.arrayDimensionsSize = 1;
53291UA_UInt32 arrayDimensions[1];
53292arrayDimensions[0] = 0;
53293attr.arrayDimensions = &arrayDimensions[0];
53294attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53295UA_LocalizedText variablenode_ns_0_i_12078_variant_DataContents[3];
53296variablenode_ns_0_i_12078_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: "Linear");
53297variablenode_ns_0_i_12078_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: "Log");
53298variablenode_ns_0_i_12078_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: "Ln");
53299UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12078_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
53300attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53301retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53302requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU),
53303parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU),
53304referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53305browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53306typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53307attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53308return retVal;
53309}
53310
53311static UA_StatusCode function_namespace0_generated_37_finish(UA_Server *server, UA_UInt16* ns) {
53312return UA_Server_addNode_finish(server,
53313nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU)
53314);
53315}
53316
53317/* NamingRuleType - ns=0;i=120 */
53318
53319static UA_StatusCode function_namespace0_generated_38_begin(UA_Server *server, UA_UInt16* ns) {
53320UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53321UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53322attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRuleType");
53323retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53324requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU),
53325parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU),
53326referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53327browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRuleType"),
53328 typeDefinition: UA_NODEID_NULL,
53329attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53330return retVal;
53331}
53332
53333static UA_StatusCode function_namespace0_generated_38_finish(UA_Server *server, UA_UInt16* ns) {
53334return UA_Server_addNode_finish(server,
53335nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU)
53336);
53337}
53338
53339/* EnumValues - ns=0;i=12169 */
53340
53341static UA_StatusCode function_namespace0_generated_39_begin(UA_Server *server, UA_UInt16* ns) {
53342UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53343UA_VariableAttributes attr = UA_VariableAttributes_default;
53344attr.minimumSamplingInterval = 0.000000;
53345attr.userAccessLevel = 1;
53346attr.accessLevel = 1;
53347attr.valueRank = 1;
53348attr.arrayDimensionsSize = 1;
53349UA_UInt32 arrayDimensions[1];
53350arrayDimensions[0] = 0;
53351attr.arrayDimensions = &arrayDimensions[0];
53352attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU);
53353UA_EnumValueType variablenode_ns_0_i_12169_variant_DataContents[3];
53354
53355UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53356variablenode_ns_0_i_12169_variant_DataContents[0].value = (UA_Int64) 1;
53357variablenode_ns_0_i_12169_variant_DataContents[0].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Mandatory");
53358variablenode_ns_0_i_12169_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: "The BrowseName must appear in all instances of the type.");
53359
53360UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53361variablenode_ns_0_i_12169_variant_DataContents[1].value = (UA_Int64) 2;
53362variablenode_ns_0_i_12169_variant_DataContents[1].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Optional");
53363variablenode_ns_0_i_12169_variant_DataContents[1].description = UA_LOCALIZEDTEXT(locale: "", text: "The BrowseName may appear in an instance of the type.");
53364
53365UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53366variablenode_ns_0_i_12169_variant_DataContents[2].value = (UA_Int64) 3;
53367variablenode_ns_0_i_12169_variant_DataContents[2].displayName = UA_LOCALIZEDTEXT(locale: "", text: "Constraint");
53368variablenode_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.");
53369UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12169_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]);
53370attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues");
53371retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53372requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU),
53373parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU),
53374referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53375browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"),
53376typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53377attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53378
53379
53380
53381return retVal;
53382}
53383
53384static UA_StatusCode function_namespace0_generated_39_finish(UA_Server *server, UA_UInt16* ns) {
53385return UA_Server_addNode_finish(server,
53386nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU)
53387);
53388}
53389
53390/* Number - ns=0;i=26 */
53391
53392static UA_StatusCode function_namespace0_generated_40_begin(UA_Server *server, UA_UInt16* ns) {
53393UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53394UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53395attr.isAbstract = true;
53396attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Number");
53397retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53398requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53399parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU),
53400referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53401browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Number"),
53402 typeDefinition: UA_NODEID_NULL,
53403attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53404return retVal;
53405}
53406
53407static UA_StatusCode function_namespace0_generated_40_finish(UA_Server *server, UA_UInt16* ns) {
53408return UA_Server_addNode_finish(server,
53409nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU)
53410);
53411}
53412
53413/* Decimal - ns=0;i=50 */
53414
53415static UA_StatusCode function_namespace0_generated_41_begin(UA_Server *server, UA_UInt16* ns) {
53416UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53417UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53418attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Decimal");
53419retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53420requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU),
53421parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53422referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53423browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Decimal"),
53424 typeDefinition: UA_NODEID_NULL,
53425attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53426return retVal;
53427}
53428
53429static UA_StatusCode function_namespace0_generated_41_finish(UA_Server *server, UA_UInt16* ns) {
53430return UA_Server_addNode_finish(server,
53431nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU)
53432);
53433}
53434
53435/* UInteger - ns=0;i=28 */
53436
53437static UA_StatusCode function_namespace0_generated_42_begin(UA_Server *server, UA_UInt16* ns) {
53438UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53439UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53440attr.isAbstract = true;
53441attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInteger");
53442retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53443requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53444parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53445referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53446browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInteger"),
53447 typeDefinition: UA_NODEID_NULL,
53448attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53449return retVal;
53450}
53451
53452static UA_StatusCode function_namespace0_generated_42_finish(UA_Server *server, UA_UInt16* ns) {
53453return UA_Server_addNode_finish(server,
53454nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU)
53455);
53456}
53457
53458/* UInt64 - ns=0;i=9 */
53459
53460static UA_StatusCode function_namespace0_generated_43_begin(UA_Server *server, UA_UInt16* ns) {
53461UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53462UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53463attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt64");
53464retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53465requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU),
53466parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53467referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53468browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt64"),
53469 typeDefinition: UA_NODEID_NULL,
53470attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53471return retVal;
53472}
53473
53474static UA_StatusCode function_namespace0_generated_43_finish(UA_Server *server, UA_UInt16* ns) {
53475return UA_Server_addNode_finish(server,
53476nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU)
53477);
53478}
53479
53480/* UInt32 - ns=0;i=7 */
53481
53482static UA_StatusCode function_namespace0_generated_44_begin(UA_Server *server, UA_UInt16* ns) {
53483UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53484UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53485attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt32");
53486retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53487requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU),
53488parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53489referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53490browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt32"),
53491 typeDefinition: UA_NODEID_NULL,
53492attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53493return retVal;
53494}
53495
53496static UA_StatusCode function_namespace0_generated_44_finish(UA_Server *server, UA_UInt16* ns) {
53497return UA_Server_addNode_finish(server,
53498nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU)
53499);
53500}
53501
53502/* UInt16 - ns=0;i=5 */
53503
53504static UA_StatusCode function_namespace0_generated_45_begin(UA_Server *server, UA_UInt16* ns) {
53505UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53506UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53507attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt16");
53508retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53509requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU),
53510parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53511referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53512browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt16"),
53513 typeDefinition: UA_NODEID_NULL,
53514attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53515return retVal;
53516}
53517
53518static UA_StatusCode function_namespace0_generated_45_finish(UA_Server *server, UA_UInt16* ns) {
53519return UA_Server_addNode_finish(server,
53520nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU)
53521);
53522}
53523
53524/* Byte - ns=0;i=3 */
53525
53526static UA_StatusCode function_namespace0_generated_46_begin(UA_Server *server, UA_UInt16* ns) {
53527UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53528UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53529attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Byte");
53530retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53531requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU),
53532parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU),
53533referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53534browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Byte"),
53535 typeDefinition: UA_NODEID_NULL,
53536attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53537return retVal;
53538}
53539
53540static UA_StatusCode function_namespace0_generated_46_finish(UA_Server *server, UA_UInt16* ns) {
53541return UA_Server_addNode_finish(server,
53542nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU)
53543);
53544}
53545
53546/* Integer - ns=0;i=27 */
53547
53548static UA_StatusCode function_namespace0_generated_47_begin(UA_Server *server, UA_UInt16* ns) {
53549UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53550UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53551attr.isAbstract = true;
53552attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Integer");
53553retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53554requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53555parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53556referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53557browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Integer"),
53558 typeDefinition: UA_NODEID_NULL,
53559attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53560return retVal;
53561}
53562
53563static UA_StatusCode function_namespace0_generated_47_finish(UA_Server *server, UA_UInt16* ns) {
53564return UA_Server_addNode_finish(server,
53565nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU)
53566);
53567}
53568
53569/* Int64 - ns=0;i=8 */
53570
53571static UA_StatusCode function_namespace0_generated_48_begin(UA_Server *server, UA_UInt16* ns) {
53572UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53573UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53574attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int64");
53575retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53576requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU),
53577parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53578referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53579browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int64"),
53580 typeDefinition: UA_NODEID_NULL,
53581attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53582return retVal;
53583}
53584
53585static UA_StatusCode function_namespace0_generated_48_finish(UA_Server *server, UA_UInt16* ns) {
53586return UA_Server_addNode_finish(server,
53587nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU)
53588);
53589}
53590
53591/* Int32 - ns=0;i=6 */
53592
53593static UA_StatusCode function_namespace0_generated_49_begin(UA_Server *server, UA_UInt16* ns) {
53594UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53595UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53596attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int32");
53597retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53598requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU),
53599parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53600referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53601browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int32"),
53602 typeDefinition: UA_NODEID_NULL,
53603attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53604return retVal;
53605}
53606
53607static UA_StatusCode function_namespace0_generated_49_finish(UA_Server *server, UA_UInt16* ns) {
53608return UA_Server_addNode_finish(server,
53609nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU)
53610);
53611}
53612
53613/* Int16 - ns=0;i=4 */
53614
53615static UA_StatusCode function_namespace0_generated_50_begin(UA_Server *server, UA_UInt16* ns) {
53616UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53617UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53618attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int16");
53619retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53620requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU),
53621parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53622referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53623browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int16"),
53624 typeDefinition: UA_NODEID_NULL,
53625attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53626return retVal;
53627}
53628
53629static UA_StatusCode function_namespace0_generated_50_finish(UA_Server *server, UA_UInt16* ns) {
53630return UA_Server_addNode_finish(server,
53631nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU)
53632);
53633}
53634
53635/* SByte - ns=0;i=2 */
53636
53637static UA_StatusCode function_namespace0_generated_51_begin(UA_Server *server, UA_UInt16* ns) {
53638UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53639UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53640attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SByte");
53641retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53642requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU),
53643parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU),
53644referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53645browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SByte"),
53646 typeDefinition: UA_NODEID_NULL,
53647attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53648return retVal;
53649}
53650
53651static UA_StatusCode function_namespace0_generated_51_finish(UA_Server *server, UA_UInt16* ns) {
53652return UA_Server_addNode_finish(server,
53653nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU)
53654);
53655}
53656
53657/* Double - ns=0;i=11 */
53658
53659static UA_StatusCode function_namespace0_generated_52_begin(UA_Server *server, UA_UInt16* ns) {
53660UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53661UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53662attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Double");
53663retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53664requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU),
53665parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53666referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53667browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Double"),
53668 typeDefinition: UA_NODEID_NULL,
53669attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53670return retVal;
53671}
53672
53673static UA_StatusCode function_namespace0_generated_52_finish(UA_Server *server, UA_UInt16* ns) {
53674return UA_Server_addNode_finish(server,
53675nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU)
53676);
53677}
53678
53679/* Duration - ns=0;i=290 */
53680
53681static UA_StatusCode function_namespace0_generated_53_begin(UA_Server *server, UA_UInt16* ns) {
53682UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53683UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53684attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Duration");
53685retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53686requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU),
53687parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU),
53688referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53689browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Duration"),
53690 typeDefinition: UA_NODEID_NULL,
53691attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53692return retVal;
53693}
53694
53695static UA_StatusCode function_namespace0_generated_53_finish(UA_Server *server, UA_UInt16* ns) {
53696return UA_Server_addNode_finish(server,
53697nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU)
53698);
53699}
53700
53701/* Float - ns=0;i=10 */
53702
53703static UA_StatusCode function_namespace0_generated_54_begin(UA_Server *server, UA_UInt16* ns) {
53704UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53705UA_DataTypeAttributes attr = UA_DataTypeAttributes_default;
53706attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Float");
53707retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE,
53708requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU),
53709parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU),
53710referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53711browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Float"),
53712 typeDefinition: UA_NODEID_NULL,
53713attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL);
53714return retVal;
53715}
53716
53717static UA_StatusCode function_namespace0_generated_54_finish(UA_Server *server, UA_UInt16* ns) {
53718return UA_Server_addNode_finish(server,
53719nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU)
53720);
53721}
53722
53723/* DataItemType - ns=0;i=2365 */
53724
53725static UA_StatusCode function_namespace0_generated_55_begin(UA_Server *server, UA_UInt16* ns) {
53726UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53727UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53728attr.valueRank = -2;
53729/* DataType inherited */
53730attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU);
53731attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataItemType");
53732#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
53733attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A variable that contains live automation data.");
53734#endif
53735retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53736requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53737parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
53738referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53739browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataItemType"),
53740typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53741attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53742return retVal;
53743}
53744
53745static UA_StatusCode function_namespace0_generated_55_finish(UA_Server *server, UA_UInt16* ns) {
53746return UA_Server_addNode_finish(server,
53747nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU)
53748);
53749}
53750
53751/* DiscreteItemType - ns=0;i=2372 */
53752
53753static UA_StatusCode function_namespace0_generated_56_begin(UA_Server *server, UA_UInt16* ns) {
53754UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53755UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53756attr.isAbstract = true;
53757attr.valueRank = -2;
53758/* DataType inherited */
53759attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU);
53760attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiscreteItemType");
53761retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53762requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53763parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
53764referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53765browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiscreteItemType"),
53766typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53767attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53768return retVal;
53769}
53770
53771static UA_StatusCode function_namespace0_generated_56_finish(UA_Server *server, UA_UInt16* ns) {
53772return UA_Server_addNode_finish(server,
53773nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU)
53774);
53775}
53776
53777/* MultiStateDiscreteType - ns=0;i=2376 */
53778
53779static UA_StatusCode function_namespace0_generated_57_begin(UA_Server *server, UA_UInt16* ns) {
53780UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53781UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53782attr.valueRank = -2;
53783attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU);
53784attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateDiscreteType");
53785retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53786requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU),
53787parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53788referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53789browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateDiscreteType"),
53790typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53791attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53792return retVal;
53793}
53794
53795static UA_StatusCode function_namespace0_generated_57_finish(UA_Server *server, UA_UInt16* ns) {
53796return UA_Server_addNode_finish(server,
53797nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU)
53798);
53799}
53800
53801/* EnumStrings - ns=0;i=2377 */
53802
53803static UA_StatusCode function_namespace0_generated_58_begin(UA_Server *server, UA_UInt16* ns) {
53804UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53805UA_VariableAttributes attr = UA_VariableAttributes_default;
53806attr.minimumSamplingInterval = 0.000000;
53807attr.userAccessLevel = 1;
53808attr.accessLevel = 1;
53809attr.valueRank = 1;
53810attr.arrayDimensionsSize = 1;
53811UA_UInt32 arrayDimensions[1];
53812arrayDimensions[0] = 0;
53813attr.arrayDimensions = &arrayDimensions[0];
53814attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53815attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings");
53816retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53817requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU),
53818parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU),
53819referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53820browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"),
53821typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53822attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53823return retVal;
53824}
53825
53826static UA_StatusCode function_namespace0_generated_58_finish(UA_Server *server, UA_UInt16* ns) {
53827return UA_Server_addNode_finish(server,
53828nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU)
53829);
53830}
53831
53832/* TwoStateDiscreteType - ns=0;i=2373 */
53833
53834static UA_StatusCode function_namespace0_generated_59_begin(UA_Server *server, UA_UInt16* ns) {
53835UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53836UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53837attr.valueRank = -2;
53838attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
53839attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TwoStateDiscreteType");
53840retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53841requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53842parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53843referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53844browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TwoStateDiscreteType"),
53845typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53846attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53847return retVal;
53848}
53849
53850static UA_StatusCode function_namespace0_generated_59_finish(UA_Server *server, UA_UInt16* ns) {
53851return UA_Server_addNode_finish(server,
53852nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU)
53853);
53854}
53855
53856/* TrueState - ns=0;i=2375 */
53857
53858static UA_StatusCode function_namespace0_generated_60_begin(UA_Server *server, UA_UInt16* ns) {
53859UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53860UA_VariableAttributes attr = UA_VariableAttributes_default;
53861attr.minimumSamplingInterval = 0.000000;
53862attr.userAccessLevel = 1;
53863attr.accessLevel = 1;
53864/* Value rank inherited */
53865attr.valueRank = -2;
53866attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53867attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TrueState");
53868retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53869requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU),
53870parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53871referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53872browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TrueState"),
53873typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53874attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53875return retVal;
53876}
53877
53878static UA_StatusCode function_namespace0_generated_60_finish(UA_Server *server, UA_UInt16* ns) {
53879return UA_Server_addNode_finish(server,
53880nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU)
53881);
53882}
53883
53884/* FalseState - ns=0;i=2374 */
53885
53886static UA_StatusCode function_namespace0_generated_61_begin(UA_Server *server, UA_UInt16* ns) {
53887UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53888UA_VariableAttributes attr = UA_VariableAttributes_default;
53889attr.minimumSamplingInterval = 0.000000;
53890attr.userAccessLevel = 1;
53891attr.accessLevel = 1;
53892/* Value rank inherited */
53893attr.valueRank = -2;
53894attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
53895attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FalseState");
53896retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53897requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU),
53898parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU),
53899referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53900browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FalseState"),
53901typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53902attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53903return retVal;
53904}
53905
53906static UA_StatusCode function_namespace0_generated_61_finish(UA_Server *server, UA_UInt16* ns) {
53907return UA_Server_addNode_finish(server,
53908nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU)
53909);
53910}
53911
53912/* MultiStateValueDiscreteType - ns=0;i=11238 */
53913
53914static UA_StatusCode function_namespace0_generated_62_begin(UA_Server *server, UA_UInt16* ns) {
53915UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53916UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
53917attr.valueRank = -2;
53918attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU);
53919attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateValueDiscreteType");
53920retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
53921requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53922parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU),
53923referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
53924browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateValueDiscreteType"),
53925typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
53926attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
53927return retVal;
53928}
53929
53930static UA_StatusCode function_namespace0_generated_62_finish(UA_Server *server, UA_UInt16* ns) {
53931return UA_Server_addNode_finish(server,
53932nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU)
53933);
53934}
53935
53936/* ValueAsText - ns=0;i=11461 */
53937
53938static UA_StatusCode function_namespace0_generated_63_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: 21LU);
53947attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValueAsText");
53948retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53949requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU),
53950parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53951referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53952browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValueAsText"),
53953typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53954attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53955return retVal;
53956}
53957
53958static UA_StatusCode function_namespace0_generated_63_finish(UA_Server *server, UA_UInt16* ns) {
53959return UA_Server_addNode_finish(server,
53960nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU)
53961);
53962}
53963
53964/* EnumValues - ns=0;i=11241 */
53965
53966static UA_StatusCode function_namespace0_generated_64_begin(UA_Server *server, UA_UInt16* ns) {
53967UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53968UA_VariableAttributes attr = UA_VariableAttributes_default;
53969attr.minimumSamplingInterval = 0.000000;
53970attr.userAccessLevel = 1;
53971attr.accessLevel = 1;
53972attr.valueRank = 1;
53973attr.arrayDimensionsSize = 1;
53974UA_UInt32 arrayDimensions[1];
53975arrayDimensions[0] = 0;
53976attr.arrayDimensions = &arrayDimensions[0];
53977attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU);
53978attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues");
53979retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
53980requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU),
53981parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU),
53982referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
53983browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"),
53984typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
53985attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
53986return retVal;
53987}
53988
53989static UA_StatusCode function_namespace0_generated_64_finish(UA_Server *server, UA_UInt16* ns) {
53990return UA_Server_addNode_finish(server,
53991nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU)
53992);
53993}
53994
53995/* AnalogItemType - ns=0;i=2368 */
53996
53997static UA_StatusCode function_namespace0_generated_65_begin(UA_Server *server, UA_UInt16* ns) {
53998UA_StatusCode retVal = UA_STATUSCODE_GOOD;
53999UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
54000attr.valueRank = -2;
54001attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU);
54002attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AnalogItemType");
54003retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
54004requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
54005parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
54006referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54007browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AnalogItemType"),
54008typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
54009attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
54010return retVal;
54011}
54012
54013static UA_StatusCode function_namespace0_generated_65_finish(UA_Server *server, UA_UInt16* ns) {
54014return UA_Server_addNode_finish(server,
54015nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU)
54016);
54017}
54018
54019/* EngineeringUnits - ns=0;i=2371 */
54020
54021static UA_StatusCode function_namespace0_generated_66_begin(UA_Server *server, UA_UInt16* ns) {
54022UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54023UA_VariableAttributes attr = UA_VariableAttributes_default;
54024attr.minimumSamplingInterval = 0.000000;
54025attr.userAccessLevel = 1;
54026attr.accessLevel = 1;
54027/* Value rank inherited */
54028attr.valueRank = -2;
54029attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU);
54030attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EngineeringUnits");
54031retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54032requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU),
54033parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
54034referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54035browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EngineeringUnits"),
54036typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54037attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54038return retVal;
54039}
54040
54041static UA_StatusCode function_namespace0_generated_66_finish(UA_Server *server, UA_UInt16* ns) {
54042return UA_Server_addNode_finish(server,
54043nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU)
54044);
54045}
54046
54047/* InstrumentRange - ns=0;i=2370 */
54048
54049static UA_StatusCode function_namespace0_generated_67_begin(UA_Server *server, UA_UInt16* ns) {
54050UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54051UA_VariableAttributes attr = UA_VariableAttributes_default;
54052attr.minimumSamplingInterval = 0.000000;
54053attr.userAccessLevel = 1;
54054attr.accessLevel = 1;
54055/* Value rank inherited */
54056attr.valueRank = -2;
54057attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU);
54058attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InstrumentRange");
54059retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54060requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU),
54061parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
54062referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54063browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InstrumentRange"),
54064typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54065attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54066return retVal;
54067}
54068
54069static UA_StatusCode function_namespace0_generated_67_finish(UA_Server *server, UA_UInt16* ns) {
54070return UA_Server_addNode_finish(server,
54071nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU)
54072);
54073}
54074
54075/* EURange - ns=0;i=2369 */
54076
54077static UA_StatusCode function_namespace0_generated_68_begin(UA_Server *server, UA_UInt16* ns) {
54078UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54079UA_VariableAttributes attr = UA_VariableAttributes_default;
54080attr.minimumSamplingInterval = 0.000000;
54081attr.userAccessLevel = 3;
54082attr.accessLevel = 3;
54083/* Value rank inherited */
54084attr.valueRank = -2;
54085attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU);
54086attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EURange");
54087retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54088requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU),
54089parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU),
54090referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54091browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EURange"),
54092typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54093attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54094return retVal;
54095}
54096
54097static UA_StatusCode function_namespace0_generated_68_finish(UA_Server *server, UA_UInt16* ns) {
54098return UA_Server_addNode_finish(server,
54099nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU)
54100);
54101}
54102
54103/* ValuePrecision - ns=0;i=2367 */
54104
54105static UA_StatusCode function_namespace0_generated_69_begin(UA_Server *server, UA_UInt16* ns) {
54106UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54107UA_VariableAttributes attr = UA_VariableAttributes_default;
54108attr.minimumSamplingInterval = 0.000000;
54109attr.userAccessLevel = 1;
54110attr.accessLevel = 1;
54111/* Value rank inherited */
54112attr.valueRank = -2;
54113attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU);
54114attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValuePrecision");
54115#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54116attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The maximum precision that the server can maintain for the item based on restrictions in the target environment.");
54117#endif
54118retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54119requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU),
54120parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
54121referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54122browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValuePrecision"),
54123typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54124attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54125return retVal;
54126}
54127
54128static UA_StatusCode function_namespace0_generated_69_finish(UA_Server *server, UA_UInt16* ns) {
54129return UA_Server_addNode_finish(server,
54130nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU)
54131);
54132}
54133
54134/* Definition - ns=0;i=2366 */
54135
54136static UA_StatusCode function_namespace0_generated_70_begin(UA_Server *server, UA_UInt16* ns) {
54137UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54138UA_VariableAttributes attr = UA_VariableAttributes_default;
54139attr.minimumSamplingInterval = 0.000000;
54140attr.userAccessLevel = 1;
54141attr.accessLevel = 1;
54142/* Value rank inherited */
54143attr.valueRank = -2;
54144attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
54145attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Definition");
54146#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54147attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A vendor-specific, human readable string that specifies how the value of this DataItem is calculated.");
54148#endif
54149retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54150requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU),
54151parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU),
54152referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54153browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Definition"),
54154typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54155attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54156return retVal;
54157}
54158
54159static UA_StatusCode function_namespace0_generated_70_finish(UA_Server *server, UA_UInt16* ns) {
54160return UA_Server_addNode_finish(server,
54161nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU)
54162);
54163}
54164
54165/* HistoryServerCapabilitiesType - ns=0;i=2330 */
54166
54167static UA_StatusCode function_namespace0_generated_71_begin(UA_Server *server, UA_UInt16* ns) {
54168UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54169UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54170attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilitiesType");
54171retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54172requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU),
54173parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54174referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54175browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilitiesType"),
54176 typeDefinition: UA_NODEID_NULL,
54177attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54178return retVal;
54179}
54180
54181static UA_StatusCode function_namespace0_generated_71_finish(UA_Server *server, UA_UInt16* ns) {
54182return UA_Server_addNode_finish(server,
54183nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU)
54184);
54185}
54186
54187/* EventQueueOverflowEventType - ns=0;i=3035 */
54188
54189static UA_StatusCode function_namespace0_generated_72_begin(UA_Server *server, UA_UInt16* ns) {
54190UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54191UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54192attr.isAbstract = true;
54193attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventQueueOverflowEventType");
54194retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54195requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU),
54196parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54197referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54198browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventQueueOverflowEventType"),
54199 typeDefinition: UA_NODEID_NULL,
54200attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54201return retVal;
54202}
54203
54204static UA_StatusCode function_namespace0_generated_72_finish(UA_Server *server, UA_UInt16* ns) {
54205return UA_Server_addNode_finish(server,
54206nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU)
54207);
54208}
54209
54210/* Severity - ns=0;i=2051 */
54211
54212static UA_StatusCode function_namespace0_generated_73_begin(UA_Server *server, UA_UInt16* ns) {
54213UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54214UA_VariableAttributes attr = UA_VariableAttributes_default;
54215attr.minimumSamplingInterval = 0.000000;
54216attr.userAccessLevel = 1;
54217attr.accessLevel = 1;
54218/* Value rank inherited */
54219attr.valueRank = -2;
54220attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
54221attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Severity");
54222#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54223attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Indicates how urgent an event is.");
54224#endif
54225retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54226requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU),
54227parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54228referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54229browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Severity"),
54230typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54231attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54232return retVal;
54233}
54234
54235static UA_StatusCode function_namespace0_generated_73_finish(UA_Server *server, UA_UInt16* ns) {
54236return UA_Server_addNode_finish(server,
54237nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU)
54238);
54239}
54240
54241/* Message - ns=0;i=2050 */
54242
54243static UA_StatusCode function_namespace0_generated_74_begin(UA_Server *server, UA_UInt16* ns) {
54244UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54245UA_VariableAttributes attr = UA_VariableAttributes_default;
54246attr.minimumSamplingInterval = 0.000000;
54247attr.userAccessLevel = 1;
54248attr.accessLevel = 1;
54249/* Value rank inherited */
54250attr.valueRank = -2;
54251attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
54252attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Message");
54253#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54254attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A localized description of the event.");
54255#endif
54256retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54257requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU),
54258parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54259referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54260browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Message"),
54261typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54262attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54263return retVal;
54264}
54265
54266static UA_StatusCode function_namespace0_generated_74_finish(UA_Server *server, UA_UInt16* ns) {
54267return UA_Server_addNode_finish(server,
54268nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU)
54269);
54270}
54271
54272/* LocalTime - ns=0;i=3190 */
54273
54274static UA_StatusCode function_namespace0_generated_75_begin(UA_Server *server, UA_UInt16* ns) {
54275UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54276UA_VariableAttributes attr = UA_VariableAttributes_default;
54277attr.minimumSamplingInterval = 0.000000;
54278attr.userAccessLevel = 1;
54279attr.accessLevel = 1;
54280/* Value rank inherited */
54281attr.valueRank = -2;
54282attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU);
54283attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalTime");
54284#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54285attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Information about the local time where the event originated.");
54286#endif
54287retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54288requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU),
54289parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54290referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54291browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalTime"),
54292typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54293attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54294return retVal;
54295}
54296
54297static UA_StatusCode function_namespace0_generated_75_finish(UA_Server *server, UA_UInt16* ns) {
54298return UA_Server_addNode_finish(server,
54299nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU)
54300);
54301}
54302
54303/* ReceiveTime - ns=0;i=2047 */
54304
54305static UA_StatusCode function_namespace0_generated_76_begin(UA_Server *server, UA_UInt16* ns) {
54306UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54307UA_VariableAttributes attr = UA_VariableAttributes_default;
54308attr.minimumSamplingInterval = 0.000000;
54309attr.userAccessLevel = 1;
54310attr.accessLevel = 1;
54311/* Value rank inherited */
54312attr.valueRank = -2;
54313attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
54314attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReceiveTime");
54315#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54316attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the server received the event from the underlying system.");
54317#endif
54318retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54319requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU),
54320parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54321referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54322browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReceiveTime"),
54323typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54324attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54325return retVal;
54326}
54327
54328static UA_StatusCode function_namespace0_generated_76_finish(UA_Server *server, UA_UInt16* ns) {
54329return UA_Server_addNode_finish(server,
54330nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU)
54331);
54332}
54333
54334/* Time - ns=0;i=2046 */
54335
54336static UA_StatusCode function_namespace0_generated_77_begin(UA_Server *server, UA_UInt16* ns) {
54337UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54338UA_VariableAttributes attr = UA_VariableAttributes_default;
54339attr.minimumSamplingInterval = 0.000000;
54340attr.userAccessLevel = 1;
54341attr.accessLevel = 1;
54342/* Value rank inherited */
54343attr.valueRank = -2;
54344attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
54345attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Time");
54346#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54347attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the event occurred.");
54348#endif
54349retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54350requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU),
54351parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54352referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54353browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Time"),
54354typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54355attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54356return retVal;
54357}
54358
54359static UA_StatusCode function_namespace0_generated_77_finish(UA_Server *server, UA_UInt16* ns) {
54360return UA_Server_addNode_finish(server,
54361nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU)
54362);
54363}
54364
54365/* SourceName - ns=0;i=2045 */
54366
54367static UA_StatusCode function_namespace0_generated_78_begin(UA_Server *server, UA_UInt16* ns) {
54368UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54369UA_VariableAttributes attr = UA_VariableAttributes_default;
54370attr.minimumSamplingInterval = 0.000000;
54371attr.userAccessLevel = 1;
54372attr.accessLevel = 1;
54373/* Value rank inherited */
54374attr.valueRank = -2;
54375attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
54376attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceName");
54377#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54378attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A description of the source of the event.");
54379#endif
54380retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54381requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU),
54382parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54383referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54384browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceName"),
54385typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54386attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54387return retVal;
54388}
54389
54390static UA_StatusCode function_namespace0_generated_78_finish(UA_Server *server, UA_UInt16* ns) {
54391return UA_Server_addNode_finish(server,
54392nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU)
54393);
54394}
54395
54396/* SourceNode - ns=0;i=2044 */
54397
54398static UA_StatusCode function_namespace0_generated_79_begin(UA_Server *server, UA_UInt16* ns) {
54399UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54400UA_VariableAttributes attr = UA_VariableAttributes_default;
54401attr.minimumSamplingInterval = 0.000000;
54402attr.userAccessLevel = 1;
54403attr.accessLevel = 1;
54404/* Value rank inherited */
54405attr.valueRank = -2;
54406attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU);
54407attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceNode");
54408#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54409attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The source of the event.");
54410#endif
54411retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54412requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU),
54413parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54414referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54415browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceNode"),
54416typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54417attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54418return retVal;
54419}
54420
54421static UA_StatusCode function_namespace0_generated_79_finish(UA_Server *server, UA_UInt16* ns) {
54422return UA_Server_addNode_finish(server,
54423nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU)
54424);
54425}
54426
54427/* EventType - ns=0;i=2043 */
54428
54429static UA_StatusCode function_namespace0_generated_80_begin(UA_Server *server, UA_UInt16* ns) {
54430UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54431UA_VariableAttributes attr = UA_VariableAttributes_default;
54432attr.minimumSamplingInterval = 0.000000;
54433attr.userAccessLevel = 1;
54434attr.accessLevel = 1;
54435/* Value rank inherited */
54436attr.valueRank = -2;
54437attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU);
54438attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventType");
54439#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54440attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The identifier for the event type.");
54441#endif
54442retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54443requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU),
54444parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54445referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54446browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventType"),
54447typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54448attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54449return retVal;
54450}
54451
54452static UA_StatusCode function_namespace0_generated_80_finish(UA_Server *server, UA_UInt16* ns) {
54453return UA_Server_addNode_finish(server,
54454nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU)
54455);
54456}
54457
54458/* EventId - ns=0;i=2042 */
54459
54460static UA_StatusCode function_namespace0_generated_81_begin(UA_Server *server, UA_UInt16* ns) {
54461UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54462UA_VariableAttributes attr = UA_VariableAttributes_default;
54463attr.minimumSamplingInterval = 0.000000;
54464attr.userAccessLevel = 1;
54465attr.accessLevel = 1;
54466/* Value rank inherited */
54467attr.valueRank = -2;
54468attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
54469attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventId");
54470#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
54471attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A globally unique identifier for the event.");
54472#endif
54473retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54474requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU),
54475parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU),
54476referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54477browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventId"),
54478typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54479attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54480return retVal;
54481}
54482
54483static UA_StatusCode function_namespace0_generated_81_finish(UA_Server *server, UA_UInt16* ns) {
54484return UA_Server_addNode_finish(server,
54485nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU)
54486);
54487}
54488
54489/* InterfaceTypes - ns=0;i=17708 */
54490
54491static UA_StatusCode function_namespace0_generated_82_begin(UA_Server *server, UA_UInt16* ns) {
54492UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54493UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54494attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InterfaceTypes");
54495retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54496requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU),
54497parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 86LU),
54498referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
54499browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InterfaceTypes"),
54500typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
54501attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54502return retVal;
54503}
54504
54505static UA_StatusCode function_namespace0_generated_82_finish(UA_Server *server, UA_UInt16* ns) {
54506return UA_Server_addNode_finish(server,
54507nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU)
54508);
54509}
54510
54511/* BaseInterfaceType - ns=0;i=17602 */
54512
54513static UA_StatusCode function_namespace0_generated_83_begin(UA_Server *server, UA_UInt16* ns) {
54514UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54515UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54516attr.isAbstract = true;
54517attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseInterfaceType");
54518retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54519requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU),
54520parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54521referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54522browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BaseInterfaceType"),
54523 typeDefinition: UA_NODEID_NULL,
54524attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54525retVal |= 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);
54526return retVal;
54527}
54528
54529static UA_StatusCode function_namespace0_generated_83_finish(UA_Server *server, UA_UInt16* ns) {
54530return UA_Server_addNode_finish(server,
54531nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU)
54532);
54533}
54534
54535/* BuildInfoType - ns=0;i=3051 */
54536
54537static UA_StatusCode function_namespace0_generated_84_begin(UA_Server *server, UA_UInt16* ns) {
54538UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54539UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
54540/* Value rank inherited */
54541attr.valueRank = -2;
54542attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU);
54543attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfoType");
54544retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
54545requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU),
54546parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
54547referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54548browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfoType"),
54549typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
54550attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
54551return retVal;
54552}
54553
54554static UA_StatusCode function_namespace0_generated_84_finish(UA_Server *server, UA_UInt16* ns) {
54555return UA_Server_addNode_finish(server,
54556nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU)
54557);
54558}
54559
54560/* ServerStatusType - ns=0;i=2138 */
54561
54562static UA_StatusCode function_namespace0_generated_85_begin(UA_Server *server, UA_UInt16* ns) {
54563UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54564UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
54565/* Value rank inherited */
54566attr.valueRank = -2;
54567attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU);
54568attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusType");
54569retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
54570requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU),
54571parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
54572referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54573browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusType"),
54574typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
54575attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
54576return retVal;
54577}
54578
54579static UA_StatusCode function_namespace0_generated_85_finish(UA_Server *server, UA_UInt16* ns) {
54580return UA_Server_addNode_finish(server,
54581nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU)
54582);
54583}
54584
54585/* OperationLimitsType - ns=0;i=11564 */
54586
54587static UA_StatusCode function_namespace0_generated_86_begin(UA_Server *server, UA_UInt16* ns) {
54588UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54589UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54590attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimitsType");
54591retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54592requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54593parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
54594referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54595browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimitsType"),
54596 typeDefinition: UA_NODEID_NULL,
54597attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54598return retVal;
54599}
54600
54601static UA_StatusCode function_namespace0_generated_86_finish(UA_Server *server, UA_UInt16* ns) {
54602return UA_Server_addNode_finish(server,
54603nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU)
54604);
54605}
54606
54607/* MaxMonitoredItemsPerCall - ns=0;i=11574 */
54608
54609static UA_StatusCode function_namespace0_generated_87_begin(UA_Server *server, UA_UInt16* ns) {
54610UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54611UA_VariableAttributes attr = UA_VariableAttributes_default;
54612attr.minimumSamplingInterval = 0.000000;
54613attr.userAccessLevel = 1;
54614attr.accessLevel = 1;
54615/* Value rank inherited */
54616attr.valueRank = -2;
54617attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54618attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall");
54619retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54620requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU),
54621parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54622referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54623browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"),
54624typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54625attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54626return retVal;
54627}
54628
54629static UA_StatusCode function_namespace0_generated_87_finish(UA_Server *server, UA_UInt16* ns) {
54630return UA_Server_addNode_finish(server,
54631nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU)
54632);
54633}
54634
54635/* MaxNodesPerNodeManagement - ns=0;i=11573 */
54636
54637static UA_StatusCode function_namespace0_generated_88_begin(UA_Server *server, UA_UInt16* ns) {
54638UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54639UA_VariableAttributes attr = UA_VariableAttributes_default;
54640attr.minimumSamplingInterval = 0.000000;
54641attr.userAccessLevel = 1;
54642attr.accessLevel = 1;
54643/* Value rank inherited */
54644attr.valueRank = -2;
54645attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54646attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement");
54647retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54648requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU),
54649parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54650referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54651browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"),
54652typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54653attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54654return retVal;
54655}
54656
54657static UA_StatusCode function_namespace0_generated_88_finish(UA_Server *server, UA_UInt16* ns) {
54658return UA_Server_addNode_finish(server,
54659nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU)
54660);
54661}
54662
54663/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */
54664
54665static UA_StatusCode function_namespace0_generated_89_begin(UA_Server *server, UA_UInt16* ns) {
54666UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54667UA_VariableAttributes attr = UA_VariableAttributes_default;
54668attr.minimumSamplingInterval = 0.000000;
54669attr.userAccessLevel = 1;
54670attr.accessLevel = 1;
54671/* Value rank inherited */
54672attr.valueRank = -2;
54673attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54674attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds");
54675retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54676requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU),
54677parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54678referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54679browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"),
54680typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54681attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54682return retVal;
54683}
54684
54685static UA_StatusCode function_namespace0_generated_89_finish(UA_Server *server, UA_UInt16* ns) {
54686return UA_Server_addNode_finish(server,
54687nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU)
54688);
54689}
54690
54691/* MaxNodesPerRegisterNodes - ns=0;i=11571 */
54692
54693static UA_StatusCode function_namespace0_generated_90_begin(UA_Server *server, UA_UInt16* ns) {
54694UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54695UA_VariableAttributes attr = UA_VariableAttributes_default;
54696attr.minimumSamplingInterval = 0.000000;
54697attr.userAccessLevel = 1;
54698attr.accessLevel = 1;
54699/* Value rank inherited */
54700attr.valueRank = -2;
54701attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54702attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes");
54703retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54704requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU),
54705parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54706referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54707browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"),
54708typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54709attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54710return retVal;
54711}
54712
54713static UA_StatusCode function_namespace0_generated_90_finish(UA_Server *server, UA_UInt16* ns) {
54714return UA_Server_addNode_finish(server,
54715nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU)
54716);
54717}
54718
54719/* MaxNodesPerBrowse - ns=0;i=11570 */
54720
54721static UA_StatusCode function_namespace0_generated_91_begin(UA_Server *server, UA_UInt16* ns) {
54722UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54723UA_VariableAttributes attr = UA_VariableAttributes_default;
54724attr.minimumSamplingInterval = 0.000000;
54725attr.userAccessLevel = 1;
54726attr.accessLevel = 1;
54727/* Value rank inherited */
54728attr.valueRank = -2;
54729attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54730attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse");
54731retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54732requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU),
54733parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54734referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54735browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"),
54736typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54737attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54738return retVal;
54739}
54740
54741static UA_StatusCode function_namespace0_generated_91_finish(UA_Server *server, UA_UInt16* ns) {
54742return UA_Server_addNode_finish(server,
54743nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU)
54744);
54745}
54746
54747/* MaxNodesPerMethodCall - ns=0;i=11569 */
54748
54749static UA_StatusCode function_namespace0_generated_92_begin(UA_Server *server, UA_UInt16* ns) {
54750UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54751UA_VariableAttributes attr = UA_VariableAttributes_default;
54752attr.minimumSamplingInterval = 0.000000;
54753attr.userAccessLevel = 1;
54754attr.accessLevel = 1;
54755/* Value rank inherited */
54756attr.valueRank = -2;
54757attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54758attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall");
54759retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54760requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU),
54761parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54762referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54763browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"),
54764typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54765attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54766return retVal;
54767}
54768
54769static UA_StatusCode function_namespace0_generated_92_finish(UA_Server *server, UA_UInt16* ns) {
54770return UA_Server_addNode_finish(server,
54771nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU)
54772);
54773}
54774
54775/* MaxNodesPerWrite - ns=0;i=11567 */
54776
54777static UA_StatusCode function_namespace0_generated_93_begin(UA_Server *server, UA_UInt16* ns) {
54778UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54779UA_VariableAttributes attr = UA_VariableAttributes_default;
54780attr.minimumSamplingInterval = 0.000000;
54781attr.userAccessLevel = 1;
54782attr.accessLevel = 1;
54783/* Value rank inherited */
54784attr.valueRank = -2;
54785attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54786attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite");
54787retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54788requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU),
54789parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54790referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54791browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"),
54792typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54793attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54794return retVal;
54795}
54796
54797static UA_StatusCode function_namespace0_generated_93_finish(UA_Server *server, UA_UInt16* ns) {
54798return UA_Server_addNode_finish(server,
54799nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU)
54800);
54801}
54802
54803/* MaxNodesPerRead - ns=0;i=11565 */
54804
54805static UA_StatusCode function_namespace0_generated_94_begin(UA_Server *server, UA_UInt16* ns) {
54806UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54807UA_VariableAttributes attr = UA_VariableAttributes_default;
54808attr.minimumSamplingInterval = 0.000000;
54809attr.userAccessLevel = 1;
54810attr.accessLevel = 1;
54811/* Value rank inherited */
54812attr.valueRank = -2;
54813attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
54814attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead");
54815retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54816requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU),
54817parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54818referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54819browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"),
54820typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54821attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54822return retVal;
54823}
54824
54825static UA_StatusCode function_namespace0_generated_94_finish(UA_Server *server, UA_UInt16* ns) {
54826return UA_Server_addNode_finish(server,
54827nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU)
54828);
54829}
54830
54831/* ServerRedundancyType - ns=0;i=2034 */
54832
54833static UA_StatusCode function_namespace0_generated_95_begin(UA_Server *server, UA_UInt16* ns) {
54834UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54835UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54836attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancyType");
54837retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54838requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
54839parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54840referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54841browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancyType"),
54842 typeDefinition: UA_NODEID_NULL,
54843attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54844return retVal;
54845}
54846
54847static UA_StatusCode function_namespace0_generated_95_finish(UA_Server *server, UA_UInt16* ns) {
54848return UA_Server_addNode_finish(server,
54849nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU)
54850);
54851}
54852
54853/* RedundancySupport - ns=0;i=2035 */
54854
54855static UA_StatusCode function_namespace0_generated_96_begin(UA_Server *server, UA_UInt16* ns) {
54856UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54857UA_VariableAttributes attr = UA_VariableAttributes_default;
54858attr.minimumSamplingInterval = 0.000000;
54859attr.userAccessLevel = 1;
54860attr.accessLevel = 1;
54861/* Value rank inherited */
54862attr.valueRank = -2;
54863attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU);
54864attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
54865retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
54866requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU),
54867parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
54868referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
54869browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
54870typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
54871attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
54872return retVal;
54873}
54874
54875static UA_StatusCode function_namespace0_generated_96_finish(UA_Server *server, UA_UInt16* ns) {
54876return UA_Server_addNode_finish(server,
54877nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU)
54878);
54879}
54880
54881/* VendorServerInfoType - ns=0;i=2033 */
54882
54883static UA_StatusCode function_namespace0_generated_97_begin(UA_Server *server, UA_UInt16* ns) {
54884UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54885UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54886attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfoType");
54887retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54888requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
54889parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54890referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54891browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfoType"),
54892 typeDefinition: UA_NODEID_NULL,
54893attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54894return retVal;
54895}
54896
54897static UA_StatusCode function_namespace0_generated_97_finish(UA_Server *server, UA_UInt16* ns) {
54898return UA_Server_addNode_finish(server,
54899nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU)
54900);
54901}
54902
54903/* ServerDiagnosticsType - ns=0;i=2020 */
54904
54905static UA_StatusCode function_namespace0_generated_98_begin(UA_Server *server, UA_UInt16* ns) {
54906UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54907UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54908attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsType");
54909retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54910requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU),
54911parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54912referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54913browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsType"),
54914 typeDefinition: UA_NODEID_NULL,
54915attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54916return retVal;
54917}
54918
54919static UA_StatusCode function_namespace0_generated_98_finish(UA_Server *server, UA_UInt16* ns) {
54920return UA_Server_addNode_finish(server,
54921nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU)
54922);
54923}
54924
54925/* ServerCapabilitiesType - ns=0;i=2013 */
54926
54927static UA_StatusCode function_namespace0_generated_99_begin(UA_Server *server, UA_UInt16* ns) {
54928UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54929UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54930attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilitiesType");
54931retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54932requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
54933parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54934referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54935browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilitiesType"),
54936 typeDefinition: UA_NODEID_NULL,
54937attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54938return retVal;
54939}
54940
54941static UA_StatusCode function_namespace0_generated_99_finish(UA_Server *server, UA_UInt16* ns) {
54942return UA_Server_addNode_finish(server,
54943nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU)
54944);
54945}
54946
54947/* OperationLimits - ns=0;i=11551 */
54948
54949static UA_StatusCode function_namespace0_generated_100_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: "OperationLimits");
54953retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54954requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU),
54955parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
54956referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
54957browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"),
54958typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
54959attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
54960return retVal;
54961}
54962
54963static UA_StatusCode function_namespace0_generated_100_finish(UA_Server *server, UA_UInt16* ns) {
54964return UA_Server_addNode_finish(server,
54965nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU)
54966);
54967}
54968
54969/* ServerType - ns=0;i=2004 */
54970
54971static UA_StatusCode function_namespace0_generated_101_begin(UA_Server *server, UA_UInt16* ns) {
54972UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54973UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
54974attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerType");
54975retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
54976requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
54977parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
54978referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
54979browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerType"),
54980 typeDefinition: UA_NODEID_NULL,
54981attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
54982return retVal;
54983}
54984
54985static UA_StatusCode function_namespace0_generated_101_finish(UA_Server *server, UA_UInt16* ns) {
54986return UA_Server_addNode_finish(server,
54987nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU)
54988);
54989}
54990
54991/* Server - ns=0;i=2253 */
54992
54993static UA_StatusCode function_namespace0_generated_102_begin(UA_Server *server, UA_UInt16* ns) {
54994UA_StatusCode retVal = UA_STATUSCODE_GOOD;
54995UA_ObjectAttributes attr = UA_ObjectAttributes_default;
54996attr.eventNotifier = UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT;
54997attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Server");
54998retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
54999requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55000parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 85LU),
55001referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
55002browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Server"),
55003typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
55004attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55005return retVal;
55006}
55007
55008static UA_StatusCode function_namespace0_generated_102_finish(UA_Server *server, UA_UInt16* ns) {
55009return UA_Server_addNode_finish(server,
55010nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU)
55011);
55012}
55013
55014/* Auditing - ns=0;i=2994 */
55015
55016static UA_StatusCode function_namespace0_generated_103_begin(UA_Server *server, UA_UInt16* ns) {
55017UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55018UA_VariableAttributes attr = UA_VariableAttributes_default;
55019attr.minimumSamplingInterval = 1000.000000;
55020attr.userAccessLevel = 1;
55021attr.accessLevel = 1;
55022/* Value rank inherited */
55023attr.valueRank = -2;
55024attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55025attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Auditing");
55026retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55027requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU),
55028parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55029referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55030browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Auditing"),
55031typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55032attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55033return retVal;
55034}
55035
55036static UA_StatusCode function_namespace0_generated_103_finish(UA_Server *server, UA_UInt16* ns) {
55037return UA_Server_addNode_finish(server,
55038nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU)
55039);
55040}
55041
55042/* ServerRedundancy - ns=0;i=2296 */
55043
55044static UA_StatusCode function_namespace0_generated_104_begin(UA_Server *server, UA_UInt16* ns) {
55045UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55046UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55047attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancy");
55048retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55049requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU),
55050parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55051referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55052browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancy"),
55053typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU),
55054attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55055return retVal;
55056}
55057
55058static UA_StatusCode function_namespace0_generated_104_finish(UA_Server *server, UA_UInt16* ns) {
55059return UA_Server_addNode_finish(server,
55060nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU)
55061);
55062}
55063
55064/* RedundancySupport - ns=0;i=3709 */
55065
55066static UA_StatusCode function_namespace0_generated_105_begin(UA_Server *server, UA_UInt16* ns) {
55067UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55068UA_VariableAttributes attr = UA_VariableAttributes_default;
55069attr.minimumSamplingInterval = 0.000000;
55070attr.userAccessLevel = 1;
55071attr.accessLevel = 1;
55072/* Value rank inherited */
55073attr.valueRank = -2;
55074attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU);
55075attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport");
55076retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55077requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU),
55078parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU),
55079referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55080browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"),
55081typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55082attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55083return retVal;
55084}
55085
55086static UA_StatusCode function_namespace0_generated_105_finish(UA_Server *server, UA_UInt16* ns) {
55087return UA_Server_addNode_finish(server,
55088nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU)
55089);
55090}
55091
55092/* VendorServerInfo - ns=0;i=2295 */
55093
55094static UA_StatusCode function_namespace0_generated_106_begin(UA_Server *server, UA_UInt16* ns) {
55095UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55096UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55097attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo");
55098retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55099requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU),
55100parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55101referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55102browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"),
55103typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
55104attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55105return retVal;
55106}
55107
55108static UA_StatusCode function_namespace0_generated_106_finish(UA_Server *server, UA_UInt16* ns) {
55109return UA_Server_addNode_finish(server,
55110nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU)
55111);
55112}
55113
55114/* ServerDiagnostics - ns=0;i=2274 */
55115
55116static UA_StatusCode function_namespace0_generated_107_begin(UA_Server *server, UA_UInt16* ns) {
55117UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55118UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55119attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnostics");
55120retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55121requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU),
55122parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55123referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55124browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnostics"),
55125typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU),
55126attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55127return retVal;
55128}
55129
55130static UA_StatusCode function_namespace0_generated_107_finish(UA_Server *server, UA_UInt16* ns) {
55131return UA_Server_addNode_finish(server,
55132nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU)
55133);
55134}
55135
55136/* EnabledFlag - ns=0;i=2294 */
55137
55138static UA_StatusCode function_namespace0_generated_108_begin(UA_Server *server, UA_UInt16* ns) {
55139UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55140UA_VariableAttributes attr = UA_VariableAttributes_default;
55141attr.minimumSamplingInterval = 0.000000;
55142attr.userAccessLevel = 1;
55143attr.accessLevel = 3;
55144/* Value rank inherited */
55145attr.valueRank = -2;
55146attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55147attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnabledFlag");
55148retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55149requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU),
55150parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU),
55151referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55152browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnabledFlag"),
55153typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55154attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55155return retVal;
55156}
55157
55158static UA_StatusCode function_namespace0_generated_108_finish(UA_Server *server, UA_UInt16* ns) {
55159return UA_Server_addNode_finish(server,
55160nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU)
55161);
55162}
55163
55164/* ServerCapabilities - ns=0;i=2268 */
55165
55166static UA_StatusCode function_namespace0_generated_109_begin(UA_Server *server, UA_UInt16* ns) {
55167UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55168UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55169attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilities");
55170retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55171requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55172parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
55173referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55174browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilities"),
55175typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU),
55176attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55177return retVal;
55178}
55179
55180static UA_StatusCode function_namespace0_generated_109_finish(UA_Server *server, UA_UInt16* ns) {
55181return UA_Server_addNode_finish(server,
55182nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU)
55183);
55184}
55185
55186/* SoftwareCertificates - ns=0;i=3704 */
55187
55188static UA_StatusCode function_namespace0_generated_110_begin(UA_Server *server, UA_UInt16* ns) {
55189UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55190UA_VariableAttributes attr = UA_VariableAttributes_default;
55191attr.minimumSamplingInterval = 0.000000;
55192attr.userAccessLevel = 1;
55193attr.accessLevel = 1;
55194attr.valueRank = 1;
55195attr.arrayDimensionsSize = 1;
55196UA_UInt32 arrayDimensions[1];
55197arrayDimensions[0] = 0;
55198attr.arrayDimensions = &arrayDimensions[0];
55199attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU);
55200attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareCertificates");
55201retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55202requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU),
55203parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55204referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55205browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareCertificates"),
55206typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55207attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55208return retVal;
55209}
55210
55211static UA_StatusCode function_namespace0_generated_110_finish(UA_Server *server, UA_UInt16* ns) {
55212return UA_Server_addNode_finish(server,
55213nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU)
55214);
55215}
55216
55217/* AggregateFunctions - ns=0;i=2997 */
55218
55219static UA_StatusCode function_namespace0_generated_111_begin(UA_Server *server, UA_UInt16* ns) {
55220UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55221UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55222attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions");
55223retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55224requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU),
55225parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55226referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55227browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"),
55228typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55229attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55230return retVal;
55231}
55232
55233static UA_StatusCode function_namespace0_generated_111_finish(UA_Server *server, UA_UInt16* ns) {
55234return UA_Server_addNode_finish(server,
55235nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU)
55236);
55237}
55238
55239/* ModellingRules - ns=0;i=2996 */
55240
55241static UA_StatusCode function_namespace0_generated_112_begin(UA_Server *server, UA_UInt16* ns) {
55242UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55243UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55244attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRules");
55245retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55246requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU),
55247parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55248referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55249browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRules"),
55250typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55251attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55252return retVal;
55253}
55254
55255static UA_StatusCode function_namespace0_generated_112_finish(UA_Server *server, UA_UInt16* ns) {
55256return UA_Server_addNode_finish(server,
55257nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU)
55258);
55259}
55260
55261/* MaxHistoryContinuationPoints - ns=0;i=2737 */
55262
55263static UA_StatusCode function_namespace0_generated_113_begin(UA_Server *server, UA_UInt16* ns) {
55264UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55265UA_VariableAttributes attr = UA_VariableAttributes_default;
55266attr.minimumSamplingInterval = 0.000000;
55267attr.userAccessLevel = 1;
55268attr.accessLevel = 1;
55269/* Value rank inherited */
55270attr.valueRank = -2;
55271attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55272attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxHistoryContinuationPoints");
55273retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55274requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU),
55275parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55276referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55277browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxHistoryContinuationPoints"),
55278typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55279attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55280return retVal;
55281}
55282
55283static UA_StatusCode function_namespace0_generated_113_finish(UA_Server *server, UA_UInt16* ns) {
55284return UA_Server_addNode_finish(server,
55285nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU)
55286);
55287}
55288
55289/* MaxQueryContinuationPoints - ns=0;i=2736 */
55290
55291static UA_StatusCode function_namespace0_generated_114_begin(UA_Server *server, UA_UInt16* ns) {
55292UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55293UA_VariableAttributes attr = UA_VariableAttributes_default;
55294attr.minimumSamplingInterval = 0.000000;
55295attr.userAccessLevel = 1;
55296attr.accessLevel = 1;
55297/* Value rank inherited */
55298attr.valueRank = -2;
55299attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55300attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxQueryContinuationPoints");
55301retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55302requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU),
55303parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55304referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55305browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxQueryContinuationPoints"),
55306typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55307attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55308return retVal;
55309}
55310
55311static UA_StatusCode function_namespace0_generated_114_finish(UA_Server *server, UA_UInt16* ns) {
55312return UA_Server_addNode_finish(server,
55313nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU)
55314);
55315}
55316
55317/* MaxBrowseContinuationPoints - ns=0;i=2735 */
55318
55319static UA_StatusCode function_namespace0_generated_115_begin(UA_Server *server, UA_UInt16* ns) {
55320UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55321UA_VariableAttributes attr = UA_VariableAttributes_default;
55322attr.minimumSamplingInterval = 0.000000;
55323attr.userAccessLevel = 1;
55324attr.accessLevel = 1;
55325/* Value rank inherited */
55326attr.valueRank = -2;
55327attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU);
55328attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxBrowseContinuationPoints");
55329retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55330requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU),
55331parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55332referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55333browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxBrowseContinuationPoints"),
55334typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55335attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55336return retVal;
55337}
55338
55339static UA_StatusCode function_namespace0_generated_115_finish(UA_Server *server, UA_UInt16* ns) {
55340return UA_Server_addNode_finish(server,
55341nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU)
55342);
55343}
55344
55345/* MinSupportedSampleRate - ns=0;i=2272 */
55346
55347static UA_StatusCode function_namespace0_generated_116_begin(UA_Server *server, UA_UInt16* ns) {
55348UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55349UA_VariableAttributes attr = UA_VariableAttributes_default;
55350attr.minimumSamplingInterval = 0.000000;
55351attr.userAccessLevel = 1;
55352attr.accessLevel = 1;
55353/* Value rank inherited */
55354attr.valueRank = -2;
55355attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU);
55356attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MinSupportedSampleRate");
55357retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55358requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU),
55359parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55360referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55361browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MinSupportedSampleRate"),
55362typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55363attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55364return retVal;
55365}
55366
55367static UA_StatusCode function_namespace0_generated_116_finish(UA_Server *server, UA_UInt16* ns) {
55368return UA_Server_addNode_finish(server,
55369nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU)
55370);
55371}
55372
55373/* LocaleIdArray - ns=0;i=2271 */
55374
55375static UA_StatusCode function_namespace0_generated_117_begin(UA_Server *server, UA_UInt16* ns) {
55376UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55377UA_VariableAttributes attr = UA_VariableAttributes_default;
55378attr.minimumSamplingInterval = 0.000000;
55379attr.userAccessLevel = 1;
55380attr.accessLevel = 1;
55381attr.valueRank = 1;
55382attr.arrayDimensionsSize = 1;
55383UA_UInt32 arrayDimensions[1];
55384arrayDimensions[0] = 0;
55385attr.arrayDimensions = &arrayDimensions[0];
55386attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU);
55387attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIdArray");
55388retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55389requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU),
55390parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55391referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55392browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIdArray"),
55393typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55394attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55395return retVal;
55396}
55397
55398static UA_StatusCode function_namespace0_generated_117_finish(UA_Server *server, UA_UInt16* ns) {
55399return UA_Server_addNode_finish(server,
55400nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU)
55401);
55402}
55403
55404/* ServerProfileArray - ns=0;i=2269 */
55405
55406static UA_StatusCode function_namespace0_generated_118_begin(UA_Server *server, UA_UInt16* ns) {
55407UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55408UA_VariableAttributes attr = UA_VariableAttributes_default;
55409attr.minimumSamplingInterval = 0.000000;
55410attr.userAccessLevel = 1;
55411attr.accessLevel = 1;
55412attr.valueRank = 1;
55413attr.arrayDimensionsSize = 1;
55414UA_UInt32 arrayDimensions[1];
55415arrayDimensions[0] = 0;
55416attr.arrayDimensions = &arrayDimensions[0];
55417attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
55418attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerProfileArray");
55419retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55420requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU),
55421parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55422referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55423browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerProfileArray"),
55424typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55425attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55426return retVal;
55427}
55428
55429static UA_StatusCode function_namespace0_generated_118_finish(UA_Server *server, UA_UInt16* ns) {
55430return UA_Server_addNode_finish(server,
55431nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU)
55432);
55433}
55434
55435/* OperationLimits - ns=0;i=11704 */
55436
55437static UA_StatusCode function_namespace0_generated_119_begin(UA_Server *server, UA_UInt16* ns) {
55438UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55439UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55440attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimits");
55441retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55442requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55443parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55444referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55445browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"),
55446typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU),
55447attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55448return retVal;
55449}
55450
55451static UA_StatusCode function_namespace0_generated_119_finish(UA_Server *server, UA_UInt16* ns) {
55452return UA_Server_addNode_finish(server,
55453nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU)
55454);
55455}
55456
55457/* MaxMonitoredItemsPerCall - ns=0;i=11714 */
55458
55459static UA_StatusCode function_namespace0_generated_120_begin(UA_Server *server, UA_UInt16* ns) {
55460UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55461UA_VariableAttributes attr = UA_VariableAttributes_default;
55462attr.minimumSamplingInterval = 0.000000;
55463attr.userAccessLevel = 1;
55464attr.accessLevel = 1;
55465/* Value rank inherited */
55466attr.valueRank = -2;
55467attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55468attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall");
55469retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55470requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU),
55471parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55472referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55473browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"),
55474typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55475attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55476return retVal;
55477}
55478
55479static UA_StatusCode function_namespace0_generated_120_finish(UA_Server *server, UA_UInt16* ns) {
55480return UA_Server_addNode_finish(server,
55481nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU)
55482);
55483}
55484
55485/* MaxNodesPerNodeManagement - ns=0;i=11713 */
55486
55487static UA_StatusCode function_namespace0_generated_121_begin(UA_Server *server, UA_UInt16* ns) {
55488UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55489UA_VariableAttributes attr = UA_VariableAttributes_default;
55490attr.minimumSamplingInterval = 0.000000;
55491attr.userAccessLevel = 1;
55492attr.accessLevel = 1;
55493/* Value rank inherited */
55494attr.valueRank = -2;
55495attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55496attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement");
55497retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55498requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU),
55499parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55500referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55501browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"),
55502typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55503attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55504return retVal;
55505}
55506
55507static UA_StatusCode function_namespace0_generated_121_finish(UA_Server *server, UA_UInt16* ns) {
55508return UA_Server_addNode_finish(server,
55509nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU)
55510);
55511}
55512
55513/* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */
55514
55515static UA_StatusCode function_namespace0_generated_122_begin(UA_Server *server, UA_UInt16* ns) {
55516UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55517UA_VariableAttributes attr = UA_VariableAttributes_default;
55518attr.minimumSamplingInterval = 0.000000;
55519attr.userAccessLevel = 1;
55520attr.accessLevel = 1;
55521/* Value rank inherited */
55522attr.valueRank = -2;
55523attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55524attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds");
55525retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55526requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU),
55527parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55528referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55529browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"),
55530typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55531attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55532return retVal;
55533}
55534
55535static UA_StatusCode function_namespace0_generated_122_finish(UA_Server *server, UA_UInt16* ns) {
55536return UA_Server_addNode_finish(server,
55537nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU)
55538);
55539}
55540
55541/* MaxNodesPerRegisterNodes - ns=0;i=11711 */
55542
55543static UA_StatusCode function_namespace0_generated_123_begin(UA_Server *server, UA_UInt16* ns) {
55544UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55545UA_VariableAttributes attr = UA_VariableAttributes_default;
55546attr.minimumSamplingInterval = 0.000000;
55547attr.userAccessLevel = 1;
55548attr.accessLevel = 1;
55549/* Value rank inherited */
55550attr.valueRank = -2;
55551attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55552attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes");
55553retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55554requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU),
55555parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55556referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55557browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"),
55558typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55559attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55560return retVal;
55561}
55562
55563static UA_StatusCode function_namespace0_generated_123_finish(UA_Server *server, UA_UInt16* ns) {
55564return UA_Server_addNode_finish(server,
55565nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU)
55566);
55567}
55568
55569/* MaxNodesPerBrowse - ns=0;i=11710 */
55570
55571static UA_StatusCode function_namespace0_generated_124_begin(UA_Server *server, UA_UInt16* ns) {
55572UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55573UA_VariableAttributes attr = UA_VariableAttributes_default;
55574attr.minimumSamplingInterval = 0.000000;
55575attr.userAccessLevel = 1;
55576attr.accessLevel = 1;
55577/* Value rank inherited */
55578attr.valueRank = -2;
55579attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55580attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse");
55581retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55582requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU),
55583parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55584referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55585browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"),
55586typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55587attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55588return retVal;
55589}
55590
55591static UA_StatusCode function_namespace0_generated_124_finish(UA_Server *server, UA_UInt16* ns) {
55592return UA_Server_addNode_finish(server,
55593nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU)
55594);
55595}
55596
55597/* MaxNodesPerMethodCall - ns=0;i=11709 */
55598
55599static UA_StatusCode function_namespace0_generated_125_begin(UA_Server *server, UA_UInt16* ns) {
55600UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55601UA_VariableAttributes attr = UA_VariableAttributes_default;
55602attr.minimumSamplingInterval = 0.000000;
55603attr.userAccessLevel = 1;
55604attr.accessLevel = 1;
55605/* Value rank inherited */
55606attr.valueRank = -2;
55607attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55608attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall");
55609retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55610requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU),
55611parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55612referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55613browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"),
55614typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55615attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55616return retVal;
55617}
55618
55619static UA_StatusCode function_namespace0_generated_125_finish(UA_Server *server, UA_UInt16* ns) {
55620return UA_Server_addNode_finish(server,
55621nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU)
55622);
55623}
55624
55625/* MaxNodesPerWrite - ns=0;i=11707 */
55626
55627static UA_StatusCode function_namespace0_generated_126_begin(UA_Server *server, UA_UInt16* ns) {
55628UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55629UA_VariableAttributes attr = UA_VariableAttributes_default;
55630attr.minimumSamplingInterval = 0.000000;
55631attr.userAccessLevel = 1;
55632attr.accessLevel = 1;
55633/* Value rank inherited */
55634attr.valueRank = -2;
55635attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55636attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite");
55637retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55638requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU),
55639parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55640referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55641browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"),
55642typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55643attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55644return retVal;
55645}
55646
55647static UA_StatusCode function_namespace0_generated_126_finish(UA_Server *server, UA_UInt16* ns) {
55648return UA_Server_addNode_finish(server,
55649nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU)
55650);
55651}
55652
55653/* MaxNodesPerRead - ns=0;i=11705 */
55654
55655static UA_StatusCode function_namespace0_generated_127_begin(UA_Server *server, UA_UInt16* ns) {
55656UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55657UA_VariableAttributes attr = UA_VariableAttributes_default;
55658attr.minimumSamplingInterval = 0.000000;
55659attr.userAccessLevel = 1;
55660attr.accessLevel = 1;
55661/* Value rank inherited */
55662attr.valueRank = -2;
55663attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55664attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead");
55665retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55666requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU),
55667parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU),
55668referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55669browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"),
55670typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55671attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55672return retVal;
55673}
55674
55675static UA_StatusCode function_namespace0_generated_127_finish(UA_Server *server, UA_UInt16* ns) {
55676return UA_Server_addNode_finish(server,
55677nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU)
55678);
55679}
55680
55681/* HistoryServerCapabilities - ns=0;i=11192 */
55682
55683static UA_StatusCode function_namespace0_generated_128_begin(UA_Server *server, UA_UInt16* ns) {
55684UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55685UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55686attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilities");
55687retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55688requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55689parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU),
55690referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55691browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilities"),
55692typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU),
55693attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55694return retVal;
55695}
55696
55697static UA_StatusCode function_namespace0_generated_128_finish(UA_Server *server, UA_UInt16* ns) {
55698return UA_Server_addNode_finish(server,
55699nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU)
55700);
55701}
55702
55703/* DeleteEventCapability - ns=0;i=11502 */
55704
55705static UA_StatusCode function_namespace0_generated_129_begin(UA_Server *server, UA_UInt16* ns) {
55706UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55707UA_VariableAttributes attr = UA_VariableAttributes_default;
55708attr.minimumSamplingInterval = 0.000000;
55709attr.userAccessLevel = 1;
55710attr.accessLevel = 1;
55711/* Value rank inherited */
55712attr.valueRank = -2;
55713attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55714attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteEventCapability");
55715retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55716requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU),
55717parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55718referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55719browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteEventCapability"),
55720typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55721attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55722return retVal;
55723}
55724
55725static UA_StatusCode function_namespace0_generated_129_finish(UA_Server *server, UA_UInt16* ns) {
55726return UA_Server_addNode_finish(server,
55727nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU)
55728);
55729}
55730
55731/* UpdateEventCapability - ns=0;i=11283 */
55732
55733static UA_StatusCode function_namespace0_generated_130_begin(UA_Server *server, UA_UInt16* ns) {
55734UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55735UA_VariableAttributes attr = UA_VariableAttributes_default;
55736attr.minimumSamplingInterval = 0.000000;
55737attr.userAccessLevel = 1;
55738attr.accessLevel = 1;
55739/* Value rank inherited */
55740attr.valueRank = -2;
55741attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55742attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateEventCapability");
55743retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55744requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU),
55745parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55746referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55747browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateEventCapability"),
55748typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55749attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55750return retVal;
55751}
55752
55753static UA_StatusCode function_namespace0_generated_130_finish(UA_Server *server, UA_UInt16* ns) {
55754return UA_Server_addNode_finish(server,
55755nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU)
55756);
55757}
55758
55759/* ReplaceEventCapability - ns=0;i=11282 */
55760
55761static UA_StatusCode function_namespace0_generated_131_begin(UA_Server *server, UA_UInt16* ns) {
55762UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55763UA_VariableAttributes attr = UA_VariableAttributes_default;
55764attr.minimumSamplingInterval = 0.000000;
55765attr.userAccessLevel = 1;
55766attr.accessLevel = 1;
55767/* Value rank inherited */
55768attr.valueRank = -2;
55769attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55770attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceEventCapability");
55771retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55772requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU),
55773parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55774referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55775browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceEventCapability"),
55776typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55777attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55778return retVal;
55779}
55780
55781static UA_StatusCode function_namespace0_generated_131_finish(UA_Server *server, UA_UInt16* ns) {
55782return UA_Server_addNode_finish(server,
55783nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU)
55784);
55785}
55786
55787/* InsertEventCapability - ns=0;i=11281 */
55788
55789static UA_StatusCode function_namespace0_generated_132_begin(UA_Server *server, UA_UInt16* ns) {
55790UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55791UA_VariableAttributes attr = UA_VariableAttributes_default;
55792attr.minimumSamplingInterval = 0.000000;
55793attr.userAccessLevel = 1;
55794attr.accessLevel = 1;
55795/* Value rank inherited */
55796attr.valueRank = -2;
55797attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55798attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertEventCapability");
55799retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55800requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU),
55801parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55802referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55803browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertEventCapability"),
55804typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55805attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55806return retVal;
55807}
55808
55809static UA_StatusCode function_namespace0_generated_132_finish(UA_Server *server, UA_UInt16* ns) {
55810return UA_Server_addNode_finish(server,
55811nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU)
55812);
55813}
55814
55815/* InsertAnnotationCapability - ns=0;i=11275 */
55816
55817static UA_StatusCode function_namespace0_generated_133_begin(UA_Server *server, UA_UInt16* ns) {
55818UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55819UA_VariableAttributes attr = UA_VariableAttributes_default;
55820attr.minimumSamplingInterval = 0.000000;
55821attr.userAccessLevel = 1;
55822attr.accessLevel = 1;
55823/* Value rank inherited */
55824attr.valueRank = -2;
55825attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55826attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertAnnotationCapability");
55827retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55828requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU),
55829parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55830referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55831browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertAnnotationCapability"),
55832typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55833attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55834return retVal;
55835}
55836
55837static UA_StatusCode function_namespace0_generated_133_finish(UA_Server *server, UA_UInt16* ns) {
55838return UA_Server_addNode_finish(server,
55839nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU)
55840);
55841}
55842
55843/* MaxReturnEventValues - ns=0;i=11274 */
55844
55845static UA_StatusCode function_namespace0_generated_134_begin(UA_Server *server, UA_UInt16* ns) {
55846UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55847UA_VariableAttributes attr = UA_VariableAttributes_default;
55848attr.minimumSamplingInterval = 0.000000;
55849attr.userAccessLevel = 1;
55850attr.accessLevel = 1;
55851/* Value rank inherited */
55852attr.valueRank = -2;
55853attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55854attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnEventValues");
55855retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55856requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU),
55857parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55858referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55859browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnEventValues"),
55860typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55861attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55862return retVal;
55863}
55864
55865static UA_StatusCode function_namespace0_generated_134_finish(UA_Server *server, UA_UInt16* ns) {
55866return UA_Server_addNode_finish(server,
55867nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU)
55868);
55869}
55870
55871/* MaxReturnDataValues - ns=0;i=11273 */
55872
55873static UA_StatusCode function_namespace0_generated_135_begin(UA_Server *server, UA_UInt16* ns) {
55874UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55875UA_VariableAttributes attr = UA_VariableAttributes_default;
55876attr.minimumSamplingInterval = 0.000000;
55877attr.userAccessLevel = 1;
55878attr.accessLevel = 1;
55879/* Value rank inherited */
55880attr.valueRank = -2;
55881attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
55882attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnDataValues");
55883retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55884requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU),
55885parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55886referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55887browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnDataValues"),
55888typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55889attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55890return retVal;
55891}
55892
55893static UA_StatusCode function_namespace0_generated_135_finish(UA_Server *server, UA_UInt16* ns) {
55894return UA_Server_addNode_finish(server,
55895nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU)
55896);
55897}
55898
55899/* AccessHistoryEventsCapability - ns=0;i=11242 */
55900
55901static UA_StatusCode function_namespace0_generated_136_begin(UA_Server *server, UA_UInt16* ns) {
55902UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55903UA_VariableAttributes attr = UA_VariableAttributes_default;
55904attr.minimumSamplingInterval = 0.000000;
55905attr.userAccessLevel = 1;
55906attr.accessLevel = 1;
55907/* Value rank inherited */
55908attr.valueRank = -2;
55909attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55910attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryEventsCapability");
55911retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55912requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU),
55913parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55914referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55915browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryEventsCapability"),
55916typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55917attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55918return retVal;
55919}
55920
55921static UA_StatusCode function_namespace0_generated_136_finish(UA_Server *server, UA_UInt16* ns) {
55922return UA_Server_addNode_finish(server,
55923nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU)
55924);
55925}
55926
55927/* AggregateFunctions - ns=0;i=11201 */
55928
55929static UA_StatusCode function_namespace0_generated_137_begin(UA_Server *server, UA_UInt16* ns) {
55930UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55931UA_ObjectAttributes attr = UA_ObjectAttributes_default;
55932attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions");
55933retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
55934requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU),
55935parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55936referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
55937browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"),
55938typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU),
55939attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
55940return retVal;
55941}
55942
55943static UA_StatusCode function_namespace0_generated_137_finish(UA_Server *server, UA_UInt16* ns) {
55944return UA_Server_addNode_finish(server,
55945nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU)
55946);
55947}
55948
55949/* DeleteAtTimeCapability - ns=0;i=11200 */
55950
55951static UA_StatusCode function_namespace0_generated_138_begin(UA_Server *server, UA_UInt16* ns) {
55952UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55953UA_VariableAttributes attr = UA_VariableAttributes_default;
55954attr.minimumSamplingInterval = 0.000000;
55955attr.userAccessLevel = 1;
55956attr.accessLevel = 1;
55957/* Value rank inherited */
55958attr.valueRank = -2;
55959attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55960attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteAtTimeCapability");
55961retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55962requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU),
55963parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55964referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55965browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteAtTimeCapability"),
55966typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55967attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55968return retVal;
55969}
55970
55971static UA_StatusCode function_namespace0_generated_138_finish(UA_Server *server, UA_UInt16* ns) {
55972return UA_Server_addNode_finish(server,
55973nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU)
55974);
55975}
55976
55977/* DeleteRawCapability - ns=0;i=11199 */
55978
55979static UA_StatusCode function_namespace0_generated_139_begin(UA_Server *server, UA_UInt16* ns) {
55980UA_StatusCode retVal = UA_STATUSCODE_GOOD;
55981UA_VariableAttributes attr = UA_VariableAttributes_default;
55982attr.minimumSamplingInterval = 0.000000;
55983attr.userAccessLevel = 1;
55984attr.accessLevel = 1;
55985/* Value rank inherited */
55986attr.valueRank = -2;
55987attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
55988attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteRawCapability");
55989retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
55990requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU),
55991parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
55992referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
55993browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteRawCapability"),
55994typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
55995attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
55996return retVal;
55997}
55998
55999static UA_StatusCode function_namespace0_generated_139_finish(UA_Server *server, UA_UInt16* ns) {
56000return UA_Server_addNode_finish(server,
56001nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU)
56002);
56003}
56004
56005/* UpdateDataCapability - ns=0;i=11198 */
56006
56007static UA_StatusCode function_namespace0_generated_140_begin(UA_Server *server, UA_UInt16* ns) {
56008UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56009UA_VariableAttributes attr = UA_VariableAttributes_default;
56010attr.minimumSamplingInterval = 0.000000;
56011attr.userAccessLevel = 1;
56012attr.accessLevel = 1;
56013/* Value rank inherited */
56014attr.valueRank = -2;
56015attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
56016attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateDataCapability");
56017retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56018requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU),
56019parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
56020referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56021browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateDataCapability"),
56022typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56023attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56024return retVal;
56025}
56026
56027static UA_StatusCode function_namespace0_generated_140_finish(UA_Server *server, UA_UInt16* ns) {
56028return UA_Server_addNode_finish(server,
56029nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU)
56030);
56031}
56032
56033/* ReplaceDataCapability - ns=0;i=11197 */
56034
56035static UA_StatusCode function_namespace0_generated_141_begin(UA_Server *server, UA_UInt16* ns) {
56036UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56037UA_VariableAttributes attr = UA_VariableAttributes_default;
56038attr.minimumSamplingInterval = 0.000000;
56039attr.userAccessLevel = 1;
56040attr.accessLevel = 1;
56041/* Value rank inherited */
56042attr.valueRank = -2;
56043attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
56044attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceDataCapability");
56045retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56046requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU),
56047parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
56048referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56049browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceDataCapability"),
56050typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56051attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56052return retVal;
56053}
56054
56055static UA_StatusCode function_namespace0_generated_141_finish(UA_Server *server, UA_UInt16* ns) {
56056return UA_Server_addNode_finish(server,
56057nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU)
56058);
56059}
56060
56061/* InsertDataCapability - ns=0;i=11196 */
56062
56063static UA_StatusCode function_namespace0_generated_142_begin(UA_Server *server, UA_UInt16* ns) {
56064UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56065UA_VariableAttributes attr = UA_VariableAttributes_default;
56066attr.minimumSamplingInterval = 0.000000;
56067attr.userAccessLevel = 1;
56068attr.accessLevel = 1;
56069/* Value rank inherited */
56070attr.valueRank = -2;
56071attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
56072attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertDataCapability");
56073retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56074requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU),
56075parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
56076referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56077browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertDataCapability"),
56078typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56079attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56080return retVal;
56081}
56082
56083static UA_StatusCode function_namespace0_generated_142_finish(UA_Server *server, UA_UInt16* ns) {
56084return UA_Server_addNode_finish(server,
56085nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU)
56086);
56087}
56088
56089/* AccessHistoryDataCapability - ns=0;i=11193 */
56090
56091static UA_StatusCode function_namespace0_generated_143_begin(UA_Server *server, UA_UInt16* ns) {
56092UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56093UA_VariableAttributes attr = UA_VariableAttributes_default;
56094attr.minimumSamplingInterval = 0.000000;
56095attr.userAccessLevel = 1;
56096attr.accessLevel = 1;
56097/* Value rank inherited */
56098attr.valueRank = -2;
56099attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU);
56100attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryDataCapability");
56101retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56102requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU),
56103parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU),
56104referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56105browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryDataCapability"),
56106typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56107attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56108return retVal;
56109}
56110
56111static UA_StatusCode function_namespace0_generated_143_finish(UA_Server *server, UA_UInt16* ns) {
56112return UA_Server_addNode_finish(server,
56113nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU)
56114);
56115}
56116
56117/* ServiceLevel - ns=0;i=2267 */
56118
56119static UA_StatusCode function_namespace0_generated_144_begin(UA_Server *server, UA_UInt16* ns) {
56120UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56121UA_VariableAttributes attr = UA_VariableAttributes_default;
56122attr.minimumSamplingInterval = 1000.000000;
56123attr.userAccessLevel = 1;
56124attr.accessLevel = 1;
56125/* Value rank inherited */
56126attr.valueRank = -2;
56127attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU);
56128attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServiceLevel");
56129retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56130requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU),
56131parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56132referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56133browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServiceLevel"),
56134typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56135attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56136return retVal;
56137}
56138
56139static UA_StatusCode function_namespace0_generated_144_finish(UA_Server *server, UA_UInt16* ns) {
56140return UA_Server_addNode_finish(server,
56141nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU)
56142);
56143}
56144
56145/* ServerStatus - ns=0;i=2256 */
56146
56147static UA_StatusCode function_namespace0_generated_145_begin(UA_Server *server, UA_UInt16* ns) {
56148UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56149UA_VariableAttributes attr = UA_VariableAttributes_default;
56150attr.minimumSamplingInterval = 1000.000000;
56151attr.userAccessLevel = 1;
56152attr.accessLevel = 1;
56153/* Value rank inherited */
56154attr.valueRank = -2;
56155attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU);
56156attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatus");
56157retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56158requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56159parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56160referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56161browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatus"),
56162typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU),
56163attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56164return retVal;
56165}
56166
56167static UA_StatusCode function_namespace0_generated_145_finish(UA_Server *server, UA_UInt16* ns) {
56168return UA_Server_addNode_finish(server,
56169nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU)
56170);
56171}
56172
56173/* ShutdownReason - ns=0;i=2993 */
56174
56175static UA_StatusCode function_namespace0_generated_146_begin(UA_Server *server, UA_UInt16* ns) {
56176UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56177UA_VariableAttributes attr = UA_VariableAttributes_default;
56178attr.minimumSamplingInterval = 0.000000;
56179attr.userAccessLevel = 1;
56180attr.accessLevel = 1;
56181/* Value rank inherited */
56182attr.valueRank = -2;
56183attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU);
56184attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ShutdownReason");
56185retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56186requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU),
56187parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56188referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56189browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ShutdownReason"),
56190typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56191attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56192return retVal;
56193}
56194
56195static UA_StatusCode function_namespace0_generated_146_finish(UA_Server *server, UA_UInt16* ns) {
56196return UA_Server_addNode_finish(server,
56197nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU)
56198);
56199}
56200
56201/* SecondsTillShutdown - ns=0;i=2992 */
56202
56203static UA_StatusCode function_namespace0_generated_147_begin(UA_Server *server, UA_UInt16* ns) {
56204UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56205UA_VariableAttributes attr = UA_VariableAttributes_default;
56206attr.minimumSamplingInterval = 0.000000;
56207attr.userAccessLevel = 1;
56208attr.accessLevel = 1;
56209/* Value rank inherited */
56210attr.valueRank = -2;
56211attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56212attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecondsTillShutdown");
56213retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56214requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU),
56215parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56216referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56217browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecondsTillShutdown"),
56218typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56219attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56220return retVal;
56221}
56222
56223static UA_StatusCode function_namespace0_generated_147_finish(UA_Server *server, UA_UInt16* ns) {
56224return UA_Server_addNode_finish(server,
56225nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU)
56226);
56227}
56228
56229/* BuildInfo - ns=0;i=2260 */
56230
56231static UA_StatusCode function_namespace0_generated_148_begin(UA_Server *server, UA_UInt16* ns) {
56232UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56233UA_VariableAttributes attr = UA_VariableAttributes_default;
56234attr.minimumSamplingInterval = 0.000000;
56235attr.userAccessLevel = 1;
56236attr.accessLevel = 1;
56237/* Value rank inherited */
56238attr.valueRank = -2;
56239attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU);
56240attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo");
56241retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56242requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56243parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56244referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56245browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"),
56246typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU),
56247attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56248return retVal;
56249}
56250
56251static UA_StatusCode function_namespace0_generated_148_finish(UA_Server *server, UA_UInt16* ns) {
56252return UA_Server_addNode_finish(server,
56253nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU)
56254);
56255}
56256
56257/* BuildDate - ns=0;i=2266 */
56258
56259static UA_StatusCode function_namespace0_generated_149_begin(UA_Server *server, UA_UInt16* ns) {
56260UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56261UA_VariableAttributes attr = UA_VariableAttributes_default;
56262attr.minimumSamplingInterval = 1000.000000;
56263attr.userAccessLevel = 1;
56264attr.accessLevel = 1;
56265/* Value rank inherited */
56266attr.valueRank = -2;
56267attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56268attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildDate");
56269retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56270requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU),
56271parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56272referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56273browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildDate"),
56274typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56275attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56276return retVal;
56277}
56278
56279static UA_StatusCode function_namespace0_generated_149_finish(UA_Server *server, UA_UInt16* ns) {
56280return UA_Server_addNode_finish(server,
56281nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU)
56282);
56283}
56284
56285/* BuildNumber - ns=0;i=2265 */
56286
56287static UA_StatusCode function_namespace0_generated_150_begin(UA_Server *server, UA_UInt16* ns) {
56288UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56289UA_VariableAttributes attr = UA_VariableAttributes_default;
56290attr.minimumSamplingInterval = 1000.000000;
56291attr.userAccessLevel = 1;
56292attr.accessLevel = 1;
56293/* Value rank inherited */
56294attr.valueRank = -2;
56295attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56296attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildNumber");
56297retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56298requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU),
56299parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56300referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56301browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildNumber"),
56302typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56303attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56304return retVal;
56305}
56306
56307static UA_StatusCode function_namespace0_generated_150_finish(UA_Server *server, UA_UInt16* ns) {
56308return UA_Server_addNode_finish(server,
56309nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU)
56310);
56311}
56312
56313/* SoftwareVersion - ns=0;i=2264 */
56314
56315static UA_StatusCode function_namespace0_generated_151_begin(UA_Server *server, UA_UInt16* ns) {
56316UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56317UA_VariableAttributes attr = UA_VariableAttributes_default;
56318attr.minimumSamplingInterval = 1000.000000;
56319attr.userAccessLevel = 1;
56320attr.accessLevel = 1;
56321/* Value rank inherited */
56322attr.valueRank = -2;
56323attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56324attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareVersion");
56325retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56326requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU),
56327parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56328referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56329browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareVersion"),
56330typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56331attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56332return retVal;
56333}
56334
56335static UA_StatusCode function_namespace0_generated_151_finish(UA_Server *server, UA_UInt16* ns) {
56336return UA_Server_addNode_finish(server,
56337nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU)
56338);
56339}
56340
56341/* ManufacturerName - ns=0;i=2263 */
56342
56343static UA_StatusCode function_namespace0_generated_152_begin(UA_Server *server, UA_UInt16* ns) {
56344UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56345UA_VariableAttributes attr = UA_VariableAttributes_default;
56346attr.minimumSamplingInterval = 1000.000000;
56347attr.userAccessLevel = 1;
56348attr.accessLevel = 1;
56349/* Value rank inherited */
56350attr.valueRank = -2;
56351attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56352attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ManufacturerName");
56353retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56354requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU),
56355parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56356referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56357browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ManufacturerName"),
56358typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56359attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56360return retVal;
56361}
56362
56363static UA_StatusCode function_namespace0_generated_152_finish(UA_Server *server, UA_UInt16* ns) {
56364return UA_Server_addNode_finish(server,
56365nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU)
56366);
56367}
56368
56369/* ProductUri - ns=0;i=2262 */
56370
56371static UA_StatusCode function_namespace0_generated_153_begin(UA_Server *server, UA_UInt16* ns) {
56372UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56373UA_VariableAttributes attr = UA_VariableAttributes_default;
56374attr.minimumSamplingInterval = 1000.000000;
56375attr.userAccessLevel = 1;
56376attr.accessLevel = 1;
56377/* Value rank inherited */
56378attr.valueRank = -2;
56379attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56380attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductUri");
56381retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56382requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU),
56383parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56384referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56385browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductUri"),
56386typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56387attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56388return retVal;
56389}
56390
56391static UA_StatusCode function_namespace0_generated_153_finish(UA_Server *server, UA_UInt16* ns) {
56392return UA_Server_addNode_finish(server,
56393nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU)
56394);
56395}
56396
56397/* ProductName - ns=0;i=2261 */
56398
56399static UA_StatusCode function_namespace0_generated_154_begin(UA_Server *server, UA_UInt16* ns) {
56400UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56401UA_VariableAttributes attr = UA_VariableAttributes_default;
56402attr.minimumSamplingInterval = 1000.000000;
56403attr.userAccessLevel = 1;
56404attr.accessLevel = 1;
56405/* Value rank inherited */
56406attr.valueRank = -2;
56407attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56408attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductName");
56409retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56410requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU),
56411parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU),
56412referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56413browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductName"),
56414typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56415attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56416return retVal;
56417}
56418
56419static UA_StatusCode function_namespace0_generated_154_finish(UA_Server *server, UA_UInt16* ns) {
56420return UA_Server_addNode_finish(server,
56421nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU)
56422);
56423}
56424
56425/* State - ns=0;i=2259 */
56426
56427static UA_StatusCode function_namespace0_generated_155_begin(UA_Server *server, UA_UInt16* ns) {
56428UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56429UA_VariableAttributes attr = UA_VariableAttributes_default;
56430attr.minimumSamplingInterval = 0.000000;
56431attr.userAccessLevel = 1;
56432attr.accessLevel = 1;
56433/* Value rank inherited */
56434attr.valueRank = -2;
56435attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU);
56436attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State");
56437retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56438requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU),
56439parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56440referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56441browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"),
56442typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56443attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56444return retVal;
56445}
56446
56447static UA_StatusCode function_namespace0_generated_155_finish(UA_Server *server, UA_UInt16* ns) {
56448return UA_Server_addNode_finish(server,
56449nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU)
56450);
56451}
56452
56453/* CurrentTime - ns=0;i=2258 */
56454
56455static UA_StatusCode function_namespace0_generated_156_begin(UA_Server *server, UA_UInt16* ns) {
56456UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56457UA_VariableAttributes attr = UA_VariableAttributes_default;
56458attr.minimumSamplingInterval = 0.000000;
56459attr.userAccessLevel = 1;
56460attr.accessLevel = 1;
56461/* Value rank inherited */
56462attr.valueRank = -2;
56463attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56464attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentTime");
56465retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56466requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU),
56467parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56468referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56469browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentTime"),
56470typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56471attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56472return retVal;
56473}
56474
56475static UA_StatusCode function_namespace0_generated_156_finish(UA_Server *server, UA_UInt16* ns) {
56476return UA_Server_addNode_finish(server,
56477nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU)
56478);
56479}
56480
56481/* StartTime - ns=0;i=2257 */
56482
56483static UA_StatusCode function_namespace0_generated_157_begin(UA_Server *server, UA_UInt16* ns) {
56484UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56485UA_VariableAttributes attr = UA_VariableAttributes_default;
56486attr.minimumSamplingInterval = 0.000000;
56487attr.userAccessLevel = 1;
56488attr.accessLevel = 1;
56489/* Value rank inherited */
56490attr.valueRank = -2;
56491attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU);
56492attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StartTime");
56493retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56494requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU),
56495parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU),
56496referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56497browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StartTime"),
56498typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
56499attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56500return retVal;
56501}
56502
56503static UA_StatusCode function_namespace0_generated_157_finish(UA_Server *server, UA_UInt16* ns) {
56504return UA_Server_addNode_finish(server,
56505nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU)
56506);
56507}
56508
56509/* NamespaceArray - ns=0;i=2255 */
56510
56511static UA_StatusCode function_namespace0_generated_158_begin(UA_Server *server, UA_UInt16* ns) {
56512UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56513UA_VariableAttributes attr = UA_VariableAttributes_default;
56514attr.minimumSamplingInterval = 1000.000000;
56515attr.userAccessLevel = 1;
56516attr.accessLevel = 1;
56517attr.valueRank = 1;
56518attr.arrayDimensionsSize = 1;
56519UA_UInt32 arrayDimensions[1];
56520arrayDimensions[0] = 0;
56521attr.arrayDimensions = &arrayDimensions[0];
56522attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56523attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceArray");
56524retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56525requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU),
56526parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56527referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56528browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceArray"),
56529typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56530attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56531return retVal;
56532}
56533
56534static UA_StatusCode function_namespace0_generated_158_finish(UA_Server *server, UA_UInt16* ns) {
56535return UA_Server_addNode_finish(server,
56536nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU)
56537);
56538}
56539
56540/* ServerArray - ns=0;i=2254 */
56541
56542static UA_StatusCode function_namespace0_generated_159_begin(UA_Server *server, UA_UInt16* ns) {
56543UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56544UA_VariableAttributes attr = UA_VariableAttributes_default;
56545attr.minimumSamplingInterval = 1000.000000;
56546attr.userAccessLevel = 1;
56547attr.accessLevel = 1;
56548attr.valueRank = 1;
56549attr.arrayDimensionsSize = 1;
56550UA_UInt32 arrayDimensions[1];
56551arrayDimensions[0] = 0;
56552attr.arrayDimensions = &arrayDimensions[0];
56553attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
56554attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerArray");
56555retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56556requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU),
56557parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56558referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56559browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerArray"),
56560typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56561attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56562return retVal;
56563}
56564
56565static UA_StatusCode function_namespace0_generated_159_finish(UA_Server *server, UA_UInt16* ns) {
56566return UA_Server_addNode_finish(server,
56567nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU)
56568);
56569}
56570
56571/* GetMonitoredItems - ns=0;i=11492 */
56572
56573static UA_StatusCode function_namespace0_generated_160_begin(UA_Server *server, UA_UInt16* ns) {
56574#ifdef UA_ENABLE_METHODCALLS
56575UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56576UA_MethodAttributes attr = UA_MethodAttributes_default;
56577attr.executable = true;
56578attr.userExecutable = true;
56579attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "GetMonitoredItems");
56580retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD,
56581requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56582parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU),
56583referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56584browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "GetMonitoredItems"),
56585 typeDefinition: UA_NODEID_NULL,
56586attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL);
56587return retVal;
56588#else
56589return UA_STATUSCODE_GOOD;
56590#endif /* UA_ENABLE_METHODCALLS */
56591}
56592
56593static UA_StatusCode function_namespace0_generated_160_finish(UA_Server *server, UA_UInt16* ns) {
56594#ifdef UA_ENABLE_METHODCALLS
56595return UA_Server_addMethodNode_finish(server,
56596nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU)
56597, NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL);
56598#else
56599return UA_STATUSCODE_GOOD;
56600#endif /* UA_ENABLE_METHODCALLS */
56601}
56602
56603/* OutputArguments - ns=0;i=11494 */
56604
56605static UA_StatusCode function_namespace0_generated_161_begin(UA_Server *server, UA_UInt16* ns) {
56606#ifdef UA_ENABLE_METHODCALLS
56607UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56608UA_VariableAttributes attr = UA_VariableAttributes_default;
56609attr.minimumSamplingInterval = 0.000000;
56610attr.userAccessLevel = 1;
56611attr.accessLevel = 1;
56612attr.valueRank = 1;
56613attr.arrayDimensionsSize = 1;
56614UA_UInt32 arrayDimensions[1];
56615arrayDimensions[0] = 0;
56616attr.arrayDimensions = &arrayDimensions[0];
56617attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU);
56618UA_Argument variablenode_ns_0_i_11494_variant_DataContents[2];
56619
56620UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56621variablenode_ns_0_i_11494_variant_DataContents[0].name = UA_STRING(chars: "ServerHandles");
56622variablenode_ns_0_i_11494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56623variablenode_ns_0_i_11494_variant_DataContents[0].valueRank = (UA_Int32) 1;
56624UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, 1);
56625UA_init(p: variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
56626variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions[0] = (UA_UInt32) 0;
56627variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensionsSize = 1;
56628variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions;
56629
56630UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56631variablenode_ns_0_i_11494_variant_DataContents[1].name = UA_STRING(chars: "ClientHandles");
56632variablenode_ns_0_i_11494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56633variablenode_ns_0_i_11494_variant_DataContents[1].valueRank = (UA_Int32) 1;
56634UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, 1);
56635UA_init(p: variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]);
56636variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions[0] = (UA_UInt32) 0;
56637variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensionsSize = 1;
56638variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions;
56639UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11494_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56640attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments");
56641retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56642requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU),
56643parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56644referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56645browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"),
56646typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56647attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56648
56649
56650return retVal;
56651#else
56652return UA_STATUSCODE_GOOD;
56653#endif /* UA_ENABLE_METHODCALLS */
56654}
56655
56656static UA_StatusCode function_namespace0_generated_161_finish(UA_Server *server, UA_UInt16* ns) {
56657#ifdef UA_ENABLE_METHODCALLS
56658return UA_Server_addNode_finish(server,
56659nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU)
56660);
56661#else
56662return UA_STATUSCODE_GOOD;
56663#endif /* UA_ENABLE_METHODCALLS */
56664}
56665
56666/* InputArguments - ns=0;i=11493 */
56667
56668static UA_StatusCode function_namespace0_generated_162_begin(UA_Server *server, UA_UInt16* ns) {
56669#ifdef UA_ENABLE_METHODCALLS
56670UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56671UA_VariableAttributes attr = UA_VariableAttributes_default;
56672attr.minimumSamplingInterval = 0.000000;
56673attr.userAccessLevel = 1;
56674attr.accessLevel = 1;
56675attr.valueRank = 1;
56676attr.arrayDimensionsSize = 1;
56677UA_UInt32 arrayDimensions[1];
56678arrayDimensions[0] = 0;
56679attr.arrayDimensions = &arrayDimensions[0];
56680attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU);
56681UA_Argument variablenode_ns_0_i_11493_variant_DataContents[1];
56682
56683UA_init(p: &variablenode_ns_0_i_11493_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56684variablenode_ns_0_i_11493_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId");
56685variablenode_ns_0_i_11493_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU);
56686variablenode_ns_0_i_11493_variant_DataContents[0].valueRank = (UA_Int32) -1;
56687UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11493_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]);
56688attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments");
56689retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56690requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU),
56691parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU),
56692referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56693browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"),
56694typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56695attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56696
56697return retVal;
56698#else
56699return UA_STATUSCODE_GOOD;
56700#endif /* UA_ENABLE_METHODCALLS */
56701}
56702
56703static UA_StatusCode function_namespace0_generated_162_finish(UA_Server *server, UA_UInt16* ns) {
56704#ifdef UA_ENABLE_METHODCALLS
56705return UA_Server_addNode_finish(server,
56706nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU)
56707);
56708#else
56709return UA_STATUSCODE_GOOD;
56710#endif /* UA_ENABLE_METHODCALLS */
56711}
56712
56713/* VendorServerInfo - ns=0;i=2011 */
56714
56715static UA_StatusCode function_namespace0_generated_163_begin(UA_Server *server, UA_UInt16* ns) {
56716UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56717UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56718attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo");
56719retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56720requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU),
56721parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU),
56722referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
56723browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"),
56724typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU),
56725attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56726return retVal;
56727}
56728
56729static UA_StatusCode function_namespace0_generated_163_finish(UA_Server *server, UA_UInt16* ns) {
56730return UA_Server_addNode_finish(server,
56731nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU)
56732);
56733}
56734
56735/* ModellingRuleType - ns=0;i=77 */
56736
56737static UA_StatusCode function_namespace0_generated_164_begin(UA_Server *server, UA_UInt16* ns) {
56738UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56739UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
56740attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRuleType");
56741retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
56742requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56743parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
56744referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
56745browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRuleType"),
56746 typeDefinition: UA_NODEID_NULL,
56747attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
56748return retVal;
56749}
56750
56751static UA_StatusCode function_namespace0_generated_164_finish(UA_Server *server, UA_UInt16* ns) {
56752return UA_Server_addNode_finish(server,
56753nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU)
56754);
56755}
56756
56757/* ExposesItsArray - ns=0;i=83 */
56758
56759static UA_StatusCode function_namespace0_generated_165_begin(UA_Server *server, UA_UInt16* ns) {
56760UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56761UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56762attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExposesItsArray");
56763retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56764requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU),
56765parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56766referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56767browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExposesItsArray"),
56768typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56769attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56770return retVal;
56771}
56772
56773static UA_StatusCode function_namespace0_generated_165_finish(UA_Server *server, UA_UInt16* ns) {
56774return UA_Server_addNode_finish(server,
56775nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU)
56776);
56777}
56778
56779/* NamingRule - ns=0;i=114 */
56780
56781static UA_StatusCode function_namespace0_generated_166_begin(UA_Server *server, UA_UInt16* ns) {
56782UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56783UA_VariableAttributes attr = UA_VariableAttributes_default;
56784attr.minimumSamplingInterval = 0.000000;
56785attr.userAccessLevel = 1;
56786attr.accessLevel = 1;
56787/* Value rank inherited */
56788attr.valueRank = -2;
56789attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56790UA_Int32 *variablenode_ns_0_i_114_variant_DataContents = UA_Int32_new();
56791if (!variablenode_ns_0_i_114_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56792UA_Int32_init(p: variablenode_ns_0_i_114_variant_DataContents);
56793*variablenode_ns_0_i_114_variant_DataContents = (UA_Int32) 3;
56794UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_114_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56795attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56796retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56797requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU),
56798parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU),
56799referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56800browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56801typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56802attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56803UA_Int32_delete(p: variablenode_ns_0_i_114_variant_DataContents);
56804return retVal;
56805}
56806
56807static UA_StatusCode function_namespace0_generated_166_finish(UA_Server *server, UA_UInt16* ns) {
56808return UA_Server_addNode_finish(server,
56809nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU)
56810);
56811}
56812
56813/* Optional - ns=0;i=80 */
56814
56815static UA_StatusCode function_namespace0_generated_167_begin(UA_Server *server, UA_UInt16* ns) {
56816UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56817UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56818attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Optional");
56819retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56820requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU),
56821parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56822referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56823browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Optional"),
56824typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56825attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56826retVal |= 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);
56827retVal |= 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);
56828retVal |= 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);
56829retVal |= 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);
56830retVal |= 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);
56831retVal |= 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);
56832retVal |= 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);
56833retVal |= 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);
56834retVal |= 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);
56835retVal |= 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);
56836retVal |= 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);
56837retVal |= 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);
56838retVal |= 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);
56839retVal |= 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);
56840return retVal;
56841}
56842
56843static UA_StatusCode function_namespace0_generated_167_finish(UA_Server *server, UA_UInt16* ns) {
56844return UA_Server_addNode_finish(server,
56845nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU)
56846);
56847}
56848
56849/* NamingRule - ns=0;i=113 */
56850
56851static UA_StatusCode function_namespace0_generated_168_begin(UA_Server *server, UA_UInt16* ns) {
56852UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56853UA_VariableAttributes attr = UA_VariableAttributes_default;
56854attr.minimumSamplingInterval = 0.000000;
56855attr.userAccessLevel = 1;
56856attr.accessLevel = 1;
56857/* Value rank inherited */
56858attr.valueRank = -2;
56859attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56860UA_Int32 *variablenode_ns_0_i_113_variant_DataContents = UA_Int32_new();
56861if (!variablenode_ns_0_i_113_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56862UA_Int32_init(p: variablenode_ns_0_i_113_variant_DataContents);
56863*variablenode_ns_0_i_113_variant_DataContents = (UA_Int32) 2;
56864UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_113_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56865attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56866retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56867requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU),
56868parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU),
56869referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56870browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56871typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56872attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56873UA_Int32_delete(p: variablenode_ns_0_i_113_variant_DataContents);
56874return retVal;
56875}
56876
56877static UA_StatusCode function_namespace0_generated_168_finish(UA_Server *server, UA_UInt16* ns) {
56878return UA_Server_addNode_finish(server,
56879nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU)
56880);
56881}
56882
56883/* Mandatory - ns=0;i=78 */
56884
56885static UA_StatusCode function_namespace0_generated_169_begin(UA_Server *server, UA_UInt16* ns) {
56886UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56887UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56888attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Mandatory");
56889retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56890requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU),
56891parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56892referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56893browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Mandatory"),
56894typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56895attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56896retVal |= UA_Server_addReference(server, sourceId: UA_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);
56897retVal |= UA_Server_addReference(server, sourceId: UA_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);
56898retVal |= UA_Server_addReference(server, sourceId: UA_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);
56899retVal |= UA_Server_addReference(server, sourceId: UA_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);
56900retVal |= UA_Server_addReference(server, sourceId: UA_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);
56901retVal |= UA_Server_addReference(server, sourceId: UA_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);
56902retVal |= UA_Server_addReference(server, sourceId: UA_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);
56903retVal |= UA_Server_addReference(server, sourceId: UA_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);
56904retVal |= UA_Server_addReference(server, sourceId: UA_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);
56905retVal |= UA_Server_addReference(server, sourceId: UA_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);
56906retVal |= UA_Server_addReference(server, sourceId: UA_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);
56907retVal |= UA_Server_addReference(server, sourceId: UA_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);
56908retVal |= UA_Server_addReference(server, sourceId: UA_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);
56909retVal |= UA_Server_addReference(server, sourceId: UA_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);
56910retVal |= UA_Server_addReference(server, sourceId: UA_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);
56911retVal |= UA_Server_addReference(server, sourceId: UA_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);
56912retVal |= UA_Server_addReference(server, sourceId: UA_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);
56913retVal |= UA_Server_addReference(server, sourceId: UA_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);
56914retVal |= UA_Server_addReference(server, sourceId: UA_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);
56915return retVal;
56916}
56917
56918static UA_StatusCode function_namespace0_generated_169_finish(UA_Server *server, UA_UInt16* ns) {
56919return UA_Server_addNode_finish(server,
56920nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU)
56921);
56922}
56923
56924/* NamingRule - ns=0;i=112 */
56925
56926static UA_StatusCode function_namespace0_generated_170_begin(UA_Server *server, UA_UInt16* ns) {
56927UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56928UA_VariableAttributes attr = UA_VariableAttributes_default;
56929attr.minimumSamplingInterval = 0.000000;
56930attr.userAccessLevel = 1;
56931attr.accessLevel = 1;
56932/* Value rank inherited */
56933attr.valueRank = -2;
56934attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56935UA_Int32 *variablenode_ns_0_i_112_variant_DataContents = UA_Int32_new();
56936if (!variablenode_ns_0_i_112_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56937UA_Int32_init(p: variablenode_ns_0_i_112_variant_DataContents);
56938*variablenode_ns_0_i_112_variant_DataContents = (UA_Int32) 1;
56939UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_112_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56940attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56941retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56942requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU),
56943parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU),
56944referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
56945browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
56946typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
56947attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
56948UA_Int32_delete(p: variablenode_ns_0_i_112_variant_DataContents);
56949return retVal;
56950}
56951
56952static UA_StatusCode function_namespace0_generated_170_finish(UA_Server *server, UA_UInt16* ns) {
56953return UA_Server_addNode_finish(server,
56954nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU)
56955);
56956}
56957
56958/* MandatoryPlaceholder - ns=0;i=11510 */
56959
56960static UA_StatusCode function_namespace0_generated_171_begin(UA_Server *server, UA_UInt16* ns) {
56961UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56962UA_ObjectAttributes attr = UA_ObjectAttributes_default;
56963attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MandatoryPlaceholder");
56964retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
56965requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU),
56966parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56967referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
56968browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MandatoryPlaceholder"),
56969typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
56970attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
56971return retVal;
56972}
56973
56974static UA_StatusCode function_namespace0_generated_171_finish(UA_Server *server, UA_UInt16* ns) {
56975return UA_Server_addNode_finish(server,
56976nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU)
56977);
56978}
56979
56980/* NamingRule - ns=0;i=11511 */
56981
56982static UA_StatusCode function_namespace0_generated_172_begin(UA_Server *server, UA_UInt16* ns) {
56983UA_StatusCode retVal = UA_STATUSCODE_GOOD;
56984UA_VariableAttributes attr = UA_VariableAttributes_default;
56985attr.minimumSamplingInterval = 0.000000;
56986attr.userAccessLevel = 1;
56987attr.accessLevel = 1;
56988/* Value rank inherited */
56989attr.valueRank = -2;
56990attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
56991UA_Int32 *variablenode_ns_0_i_11511_variant_DataContents = UA_Int32_new();
56992if (!variablenode_ns_0_i_11511_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
56993UA_Int32_init(p: variablenode_ns_0_i_11511_variant_DataContents);
56994*variablenode_ns_0_i_11511_variant_DataContents = (UA_Int32) 1;
56995UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11511_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
56996attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
56997retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
56998requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU),
56999parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU),
57000referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57001browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
57002typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57003attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57004UA_Int32_delete(p: variablenode_ns_0_i_11511_variant_DataContents);
57005return retVal;
57006}
57007
57008static UA_StatusCode function_namespace0_generated_172_finish(UA_Server *server, UA_UInt16* ns) {
57009return UA_Server_addNode_finish(server,
57010nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU)
57011);
57012}
57013
57014/* OptionalPlaceholder - ns=0;i=11508 */
57015
57016static UA_StatusCode function_namespace0_generated_173_begin(UA_Server *server, UA_UInt16* ns) {
57017UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57018UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57019attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OptionalPlaceholder");
57020retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57021requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU),
57022parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57023referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57024browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OptionalPlaceholder"),
57025typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
57026attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57027return retVal;
57028}
57029
57030static UA_StatusCode function_namespace0_generated_173_finish(UA_Server *server, UA_UInt16* ns) {
57031return UA_Server_addNode_finish(server,
57032nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU)
57033);
57034}
57035
57036/* NamingRule - ns=0;i=11509 */
57037
57038static UA_StatusCode function_namespace0_generated_174_begin(UA_Server *server, UA_UInt16* ns) {
57039UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57040UA_VariableAttributes attr = UA_VariableAttributes_default;
57041attr.minimumSamplingInterval = 0.000000;
57042attr.userAccessLevel = 1;
57043attr.accessLevel = 1;
57044/* Value rank inherited */
57045attr.valueRank = -2;
57046attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
57047UA_Int32 *variablenode_ns_0_i_11509_variant_DataContents = UA_Int32_new();
57048if (!variablenode_ns_0_i_11509_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57049UA_Int32_init(p: variablenode_ns_0_i_11509_variant_DataContents);
57050*variablenode_ns_0_i_11509_variant_DataContents = (UA_Int32) 2;
57051UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11509_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
57052attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
57053retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57054requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU),
57055parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU),
57056referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57057browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
57058typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57059attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57060UA_Int32_delete(p: variablenode_ns_0_i_11509_variant_DataContents);
57061return retVal;
57062}
57063
57064static UA_StatusCode function_namespace0_generated_174_finish(UA_Server *server, UA_UInt16* ns) {
57065return UA_Server_addNode_finish(server,
57066nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU)
57067);
57068}
57069
57070/* NamingRule - ns=0;i=111 */
57071
57072static UA_StatusCode function_namespace0_generated_175_begin(UA_Server *server, UA_UInt16* ns) {
57073UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57074UA_VariableAttributes attr = UA_VariableAttributes_default;
57075attr.minimumSamplingInterval = 0.000000;
57076attr.userAccessLevel = 1;
57077attr.accessLevel = 1;
57078/* Value rank inherited */
57079attr.valueRank = -2;
57080attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU);
57081UA_Int32 *variablenode_ns_0_i_111_variant_DataContents = UA_Int32_new();
57082if (!variablenode_ns_0_i_111_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57083UA_Int32_init(p: variablenode_ns_0_i_111_variant_DataContents);
57084*variablenode_ns_0_i_111_variant_DataContents = (UA_Int32) 1;
57085UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_111_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]);
57086attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule");
57087retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57088requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU),
57089parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU),
57090referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57091browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"),
57092typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57093attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57094UA_Int32_delete(p: variablenode_ns_0_i_111_variant_DataContents);
57095retVal |= 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);
57096return retVal;
57097}
57098
57099static UA_StatusCode function_namespace0_generated_175_finish(UA_Server *server, UA_UInt16* ns) {
57100return UA_Server_addNode_finish(server,
57101nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU)
57102);
57103}
57104
57105/* DataTypeEncodingType - ns=0;i=76 */
57106
57107static UA_StatusCode function_namespace0_generated_176_begin(UA_Server *server, UA_UInt16* ns) {
57108UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57109UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
57110attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeEncodingType");
57111retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
57112requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57113parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57114referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57115browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeEncodingType"),
57116 typeDefinition: UA_NODEID_NULL,
57117attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
57118return retVal;
57119}
57120
57121static UA_StatusCode function_namespace0_generated_176_finish(UA_Server *server, UA_UInt16* ns) {
57122return UA_Server_addNode_finish(server,
57123nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU)
57124);
57125}
57126
57127/* Default Binary - ns=0;i=8251 */
57128
57129static UA_StatusCode function_namespace0_generated_177_begin(UA_Server *server, UA_UInt16* ns) {
57130UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57131UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57132attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
57133retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57134requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU),
57135parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57136referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57137browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
57138typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57139attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57140retVal |= 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);
57141return retVal;
57142}
57143
57144static UA_StatusCode function_namespace0_generated_177_finish(UA_Server *server, UA_UInt16* ns) {
57145return UA_Server_addNode_finish(server,
57146nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU)
57147);
57148}
57149
57150/* Default Binary - ns=0;i=298 */
57151
57152static UA_StatusCode function_namespace0_generated_178_begin(UA_Server *server, UA_UInt16* ns) {
57153UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57154UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57155attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
57156retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57157requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU),
57158parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57159referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57160browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
57161typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57162attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57163retVal |= 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);
57164return retVal;
57165}
57166
57167static UA_StatusCode function_namespace0_generated_178_finish(UA_Server *server, UA_UInt16* ns) {
57168return UA_Server_addNode_finish(server,
57169nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU)
57170);
57171}
57172
57173/* Default JSON - ns=0;i=15376 */
57174
57175static UA_StatusCode function_namespace0_generated_179_begin(UA_Server *server, UA_UInt16* ns) {
57176UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57177UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57178attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON");
57179retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57180requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU),
57181parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57182referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57183browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"),
57184typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57185attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57186retVal |= 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);
57187return retVal;
57188}
57189
57190static UA_StatusCode function_namespace0_generated_179_finish(UA_Server *server, UA_UInt16* ns) {
57191return UA_Server_addNode_finish(server,
57192nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU)
57193);
57194}
57195
57196/* Default JSON - ns=0;i=15375 */
57197
57198static UA_StatusCode function_namespace0_generated_180_begin(UA_Server *server, UA_UInt16* ns) {
57199UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57200UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57201attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON");
57202retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57203requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU),
57204parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57205referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57206browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"),
57207typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU),
57208attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57209retVal |= 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);
57210return retVal;
57211}
57212
57213static UA_StatusCode function_namespace0_generated_180_finish(UA_Server *server, UA_UInt16* ns) {
57214return UA_Server_addNode_finish(server,
57215nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU)
57216);
57217}
57218
57219/* DataTypeSystemType - ns=0;i=75 */
57220
57221static UA_StatusCode function_namespace0_generated_181_begin(UA_Server *server, UA_UInt16* ns) {
57222UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57223UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default;
57224attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeSystemType");
57225retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE,
57226requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57227parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57228referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57229browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeSystemType"),
57230 typeDefinition: UA_NODEID_NULL,
57231attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL);
57232return retVal;
57233}
57234
57235static UA_StatusCode function_namespace0_generated_181_finish(UA_Server *server, UA_UInt16* ns) {
57236return UA_Server_addNode_finish(server,
57237nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU)
57238);
57239}
57240
57241/* OPC Binary - ns=0;i=93 */
57242
57243static UA_StatusCode function_namespace0_generated_182_begin(UA_Server *server, UA_UInt16* ns) {
57244UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57245UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57246attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OPC Binary");
57247retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57248requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU),
57249parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU),
57250referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
57251browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OPC Binary"),
57252typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57253attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57254return retVal;
57255}
57256
57257static UA_StatusCode function_namespace0_generated_182_finish(UA_Server *server, UA_UInt16* ns) {
57258return UA_Server_addNode_finish(server,
57259nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU)
57260);
57261}
57262
57263/* XML Schema - ns=0;i=92 */
57264
57265static UA_StatusCode function_namespace0_generated_183_begin(UA_Server *server, UA_UInt16* ns) {
57266UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57267UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57268attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XML Schema");
57269retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57270requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU),
57271parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU),
57272referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU),
57273browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XML Schema"),
57274typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU),
57275attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57276return retVal;
57277}
57278
57279static UA_StatusCode function_namespace0_generated_183_finish(UA_Server *server, UA_UInt16* ns) {
57280return UA_Server_addNode_finish(server,
57281nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU)
57282);
57283}
57284
57285/* DataTypeDictionaryType - ns=0;i=72 */
57286
57287static UA_StatusCode function_namespace0_generated_184_begin(UA_Server *server, UA_UInt16* ns) {
57288UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57289UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
57290/* Value rank inherited */
57291attr.valueRank = -2;
57292attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57293attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDictionaryType");
57294retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
57295requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57296parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
57297referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57298browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDictionaryType"),
57299typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57300attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
57301return retVal;
57302}
57303
57304static UA_StatusCode function_namespace0_generated_184_finish(UA_Server *server, UA_UInt16* ns) {
57305return UA_Server_addNode_finish(server,
57306nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU)
57307);
57308}
57309
57310/* Opc.Ua - ns=0;i=7617 */
57311static 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};
57312
57313
57314
57315static UA_StatusCode function_namespace0_generated_185_begin(UA_Server *server, UA_UInt16* ns) {
57316UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57317UA_VariableAttributes attr = UA_VariableAttributes_default;
57318attr.minimumSamplingInterval = 0.000000;
57319attr.userAccessLevel = 1;
57320attr.accessLevel = 1;
57321/* Value rank inherited */
57322attr.valueRank = -2;
57323attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57324UA_ByteString *variablenode_ns_0_i_7617_variant_DataContents = UA_ByteString_new();
57325if (!variablenode_ns_0_i_7617_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57326UA_ByteString_init(p: variablenode_ns_0_i_7617_variant_DataContents);
57327variablenode_ns_0_i_7617_variant_DataContents->length = 177218;
57328variablenode_ns_0_i_7617_variant_DataContents->data = (UA_Byte *)(void*)(uintptr_t)variablenode_ns_0_i_7617_variant_DataContents_byteArray;
57329UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7617_variant_DataContents, type: &UA_TYPES[UA_TYPES_BYTESTRING]);
57330attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Opc.Ua");
57331retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57332requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57333parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU),
57334referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57335browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Opc.Ua"),
57336typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57337attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57338variablenode_ns_0_i_7617_variant_DataContents->data = NULL;
57339variablenode_ns_0_i_7617_variant_DataContents->length = 0;
57340UA_ByteString_delete(p: variablenode_ns_0_i_7617_variant_DataContents);
57341return retVal;
57342}
57343
57344static UA_StatusCode function_namespace0_generated_185_finish(UA_Server *server, UA_UInt16* ns) {
57345return UA_Server_addNode_finish(server,
57346nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU)
57347);
57348}
57349
57350/* NamespaceUri - ns=0;i=107 */
57351
57352static UA_StatusCode function_namespace0_generated_186_begin(UA_Server *server, UA_UInt16* ns) {
57353UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57354UA_VariableAttributes attr = UA_VariableAttributes_default;
57355attr.minimumSamplingInterval = 0.000000;
57356attr.userAccessLevel = 1;
57357attr.accessLevel = 1;
57358/* Value rank inherited */
57359attr.valueRank = -2;
57360attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57361attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceUri");
57362#ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
57363attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A URI that uniquely identifies the dictionary.");
57364#endif
57365retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57366requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU),
57367parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57368referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57369browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceUri"),
57370typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57371attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57372retVal |= 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);
57373return retVal;
57374}
57375
57376static UA_StatusCode function_namespace0_generated_186_finish(UA_Server *server, UA_UInt16* ns) {
57377return UA_Server_addNode_finish(server,
57378nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU)
57379);
57380}
57381
57382/* DataTypeVersion - ns=0;i=106 */
57383
57384static UA_StatusCode function_namespace0_generated_187_begin(UA_Server *server, UA_UInt16* ns) {
57385UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57386UA_VariableAttributes attr = UA_VariableAttributes_default;
57387attr.minimumSamplingInterval = 0.000000;
57388attr.userAccessLevel = 1;
57389attr.accessLevel = 1;
57390/* Value rank inherited */
57391attr.valueRank = -2;
57392attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57393attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion");
57394retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57395requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU),
57396parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU),
57397referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57398browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"),
57399typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57400attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57401retVal |= 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);
57402return retVal;
57403}
57404
57405static UA_StatusCode function_namespace0_generated_187_finish(UA_Server *server, UA_UInt16* ns) {
57406return UA_Server_addNode_finish(server,
57407nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU)
57408);
57409}
57410
57411/* DataTypeDescriptionType - ns=0;i=69 */
57412
57413static UA_StatusCode function_namespace0_generated_188_begin(UA_Server *server, UA_UInt16* ns) {
57414UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57415UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default;
57416/* Value rank inherited */
57417attr.valueRank = -2;
57418attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57419attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDescriptionType");
57420retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE,
57421requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57422parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU),
57423referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU),
57424browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDescriptionType"),
57425typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57426attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL);
57427return retVal;
57428}
57429
57430static UA_StatusCode function_namespace0_generated_188_finish(UA_Server *server, UA_UInt16* ns) {
57431return UA_Server_addNode_finish(server,
57432nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU)
57433);
57434}
57435
57436/* EnumValueType - ns=0;i=7656 */
57437
57438static UA_StatusCode function_namespace0_generated_189_begin(UA_Server *server, UA_UInt16* ns) {
57439UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57440UA_VariableAttributes attr = UA_VariableAttributes_default;
57441attr.minimumSamplingInterval = 0.000000;
57442attr.userAccessLevel = 1;
57443attr.accessLevel = 1;
57444/* Value rank inherited */
57445attr.valueRank = -2;
57446attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57447UA_String *variablenode_ns_0_i_7656_variant_DataContents = UA_String_new();
57448if (!variablenode_ns_0_i_7656_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57449UA_String_init(p: variablenode_ns_0_i_7656_variant_DataContents);
57450*variablenode_ns_0_i_7656_variant_DataContents = UA_STRING_ALLOC("EnumValueType");
57451UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7656_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]);
57452attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType");
57453retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57454requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU),
57455parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57456referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57457browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"),
57458typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57459attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57460UA_String_delete(p: variablenode_ns_0_i_7656_variant_DataContents);
57461retVal |= 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);
57462return retVal;
57463}
57464
57465static UA_StatusCode function_namespace0_generated_189_finish(UA_Server *server, UA_UInt16* ns) {
57466return UA_Server_addNode_finish(server,
57467nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU)
57468);
57469}
57470
57471/* Argument - ns=0;i=7650 */
57472
57473static UA_StatusCode function_namespace0_generated_190_begin(UA_Server *server, UA_UInt16* ns) {
57474UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57475UA_VariableAttributes attr = UA_VariableAttributes_default;
57476attr.minimumSamplingInterval = 0.000000;
57477attr.userAccessLevel = 1;
57478attr.accessLevel = 1;
57479/* Value rank inherited */
57480attr.valueRank = -2;
57481attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57482UA_String *variablenode_ns_0_i_7650_variant_DataContents = UA_String_new();
57483if (!variablenode_ns_0_i_7650_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY;
57484UA_String_init(p: variablenode_ns_0_i_7650_variant_DataContents);
57485*variablenode_ns_0_i_7650_variant_DataContents = UA_STRING_ALLOC("Argument");
57486UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7650_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]);
57487attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument");
57488retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57489requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU),
57490parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU),
57491referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU),
57492browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"),
57493typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57494attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57495UA_String_delete(p: variablenode_ns_0_i_7650_variant_DataContents);
57496retVal |= 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);
57497return retVal;
57498}
57499
57500static UA_StatusCode function_namespace0_generated_190_finish(UA_Server *server, UA_UInt16* ns) {
57501return UA_Server_addNode_finish(server,
57502nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU)
57503);
57504}
57505
57506/* DictionaryFragment - ns=0;i=105 */
57507
57508static UA_StatusCode function_namespace0_generated_191_begin(UA_Server *server, UA_UInt16* ns) {
57509UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57510UA_VariableAttributes attr = UA_VariableAttributes_default;
57511attr.minimumSamplingInterval = 0.000000;
57512attr.userAccessLevel = 1;
57513attr.accessLevel = 1;
57514/* Value rank inherited */
57515attr.valueRank = -2;
57516attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU);
57517attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DictionaryFragment");
57518retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57519requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU),
57520parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57521referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57522browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DictionaryFragment"),
57523typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57524attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57525retVal |= 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);
57526return retVal;
57527}
57528
57529static UA_StatusCode function_namespace0_generated_191_finish(UA_Server *server, UA_UInt16* ns) {
57530return UA_Server_addNode_finish(server,
57531nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU)
57532);
57533}
57534
57535/* DataTypeVersion - ns=0;i=104 */
57536
57537static UA_StatusCode function_namespace0_generated_192_begin(UA_Server *server, UA_UInt16* ns) {
57538UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57539UA_VariableAttributes attr = UA_VariableAttributes_default;
57540attr.minimumSamplingInterval = 0.000000;
57541attr.userAccessLevel = 1;
57542attr.accessLevel = 1;
57543/* Value rank inherited */
57544attr.valueRank = -2;
57545attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU);
57546attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion");
57547retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE,
57548requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU),
57549parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU),
57550referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU),
57551browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"),
57552typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU),
57553attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL);
57554retVal |= 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);
57555return retVal;
57556}
57557
57558static UA_StatusCode function_namespace0_generated_192_finish(UA_Server *server, UA_UInt16* ns) {
57559return UA_Server_addNode_finish(server,
57560nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU)
57561);
57562}
57563
57564/* Default XML - ns=0;i=3063 */
57565
57566static UA_StatusCode function_namespace0_generated_193_begin(UA_Server *server, UA_UInt16* ns) {
57567UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57568UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57569attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default XML");
57570retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57571requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU),
57572parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57573referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57574browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default XML"),
57575typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57576attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57577return retVal;
57578}
57579
57580static UA_StatusCode function_namespace0_generated_193_finish(UA_Server *server, UA_UInt16* ns) {
57581return UA_Server_addNode_finish(server,
57582nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU)
57583);
57584}
57585
57586/* Default Binary - ns=0;i=3062 */
57587
57588static UA_StatusCode function_namespace0_generated_194_begin(UA_Server *server, UA_UInt16* ns) {
57589UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57590UA_ObjectAttributes attr = UA_ObjectAttributes_default;
57591attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary");
57592retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT,
57593requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU),
57594parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57595referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU),
57596browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"),
57597typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU),
57598attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL);
57599return retVal;
57600}
57601
57602static UA_StatusCode function_namespace0_generated_194_finish(UA_Server *server, UA_UInt16* ns) {
57603return UA_Server_addNode_finish(server,
57604nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU)
57605);
57606}
57607
57608UA_StatusCode namespace0_generated(UA_Server *server) {
57609UA_StatusCode retVal = UA_STATUSCODE_GOOD;
57610/* Use namespace ids generated by the server */
57611UA_UInt16 ns[1];
57612ns[0] = UA_Server_addNamespace(server, name: "http://opcfoundation.org/UA/");
57613
57614/* Load custom datatype definitions into the server */
57615if((retVal = function_namespace0_generated_0_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57616if((retVal = function_namespace0_generated_0_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57617if((retVal = function_namespace0_generated_1_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57618if((retVal = function_namespace0_generated_1_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57619if((retVal = function_namespace0_generated_2_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57620if((retVal = function_namespace0_generated_2_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57621if((retVal = function_namespace0_generated_3_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57622if((retVal = function_namespace0_generated_3_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57623if((retVal = function_namespace0_generated_4_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57624if((retVal = function_namespace0_generated_4_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57625if((retVal = function_namespace0_generated_5_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57626if((retVal = function_namespace0_generated_5_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57627if((retVal = function_namespace0_generated_6_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57628if((retVal = function_namespace0_generated_7_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57629if((retVal = function_namespace0_generated_8_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57630if((retVal = function_namespace0_generated_9_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57631if((retVal = function_namespace0_generated_10_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57632if((retVal = function_namespace0_generated_11_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57633if((retVal = function_namespace0_generated_12_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57634if((retVal = function_namespace0_generated_13_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57635if((retVal = function_namespace0_generated_14_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57636if((retVal = function_namespace0_generated_15_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57637if((retVal = function_namespace0_generated_16_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57638if((retVal = function_namespace0_generated_17_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57639if((retVal = function_namespace0_generated_18_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57640if((retVal = function_namespace0_generated_19_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57641if((retVal = function_namespace0_generated_20_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57642if((retVal = function_namespace0_generated_21_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57643if((retVal = function_namespace0_generated_22_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57644if((retVal = function_namespace0_generated_23_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57645if((retVal = function_namespace0_generated_24_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57646if((retVal = function_namespace0_generated_25_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57647if((retVal = function_namespace0_generated_26_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57648if((retVal = function_namespace0_generated_27_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57649if((retVal = function_namespace0_generated_28_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57650if((retVal = function_namespace0_generated_29_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57651if((retVal = function_namespace0_generated_30_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57652if((retVal = function_namespace0_generated_31_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57653if((retVal = function_namespace0_generated_32_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57654if((retVal = function_namespace0_generated_33_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57655if((retVal = function_namespace0_generated_34_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57656if((retVal = function_namespace0_generated_35_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57657if((retVal = function_namespace0_generated_36_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57658if((retVal = function_namespace0_generated_37_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57659if((retVal = function_namespace0_generated_38_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57660if((retVal = function_namespace0_generated_39_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57661if((retVal = function_namespace0_generated_40_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57662if((retVal = function_namespace0_generated_41_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57663if((retVal = function_namespace0_generated_42_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57664if((retVal = function_namespace0_generated_43_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57665if((retVal = function_namespace0_generated_44_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57666if((retVal = function_namespace0_generated_45_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57667if((retVal = function_namespace0_generated_46_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57668if((retVal = function_namespace0_generated_47_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57669if((retVal = function_namespace0_generated_48_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57670if((retVal = function_namespace0_generated_49_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57671if((retVal = function_namespace0_generated_50_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57672if((retVal = function_namespace0_generated_51_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57673if((retVal = function_namespace0_generated_52_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57674if((retVal = function_namespace0_generated_53_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57675if((retVal = function_namespace0_generated_54_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57676if((retVal = function_namespace0_generated_55_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57677if((retVal = function_namespace0_generated_56_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57678if((retVal = function_namespace0_generated_57_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57679if((retVal = function_namespace0_generated_58_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57680if((retVal = function_namespace0_generated_59_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57681if((retVal = function_namespace0_generated_60_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57682if((retVal = function_namespace0_generated_61_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57683if((retVal = function_namespace0_generated_62_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57684if((retVal = function_namespace0_generated_63_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57685if((retVal = function_namespace0_generated_64_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57686if((retVal = function_namespace0_generated_65_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57687if((retVal = function_namespace0_generated_66_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57688if((retVal = function_namespace0_generated_67_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57689if((retVal = function_namespace0_generated_68_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57690if((retVal = function_namespace0_generated_69_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57691if((retVal = function_namespace0_generated_70_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57692if((retVal = function_namespace0_generated_71_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57693if((retVal = function_namespace0_generated_72_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57694if((retVal = function_namespace0_generated_73_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57695if((retVal = function_namespace0_generated_74_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57696if((retVal = function_namespace0_generated_75_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57697if((retVal = function_namespace0_generated_76_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57698if((retVal = function_namespace0_generated_77_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57699if((retVal = function_namespace0_generated_78_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57700if((retVal = function_namespace0_generated_79_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57701if((retVal = function_namespace0_generated_80_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57702if((retVal = function_namespace0_generated_81_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57703if((retVal = function_namespace0_generated_82_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57704if((retVal = function_namespace0_generated_83_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57705if((retVal = function_namespace0_generated_84_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57706if((retVal = function_namespace0_generated_85_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57707if((retVal = function_namespace0_generated_86_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57708if((retVal = function_namespace0_generated_87_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57709if((retVal = function_namespace0_generated_88_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57710if((retVal = function_namespace0_generated_89_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57711if((retVal = function_namespace0_generated_90_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57712if((retVal = function_namespace0_generated_91_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57713if((retVal = function_namespace0_generated_92_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57714if((retVal = function_namespace0_generated_93_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57715if((retVal = function_namespace0_generated_94_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57716if((retVal = function_namespace0_generated_95_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57717if((retVal = function_namespace0_generated_96_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57718if((retVal = function_namespace0_generated_97_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57719if((retVal = function_namespace0_generated_98_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57720if((retVal = function_namespace0_generated_99_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57721if((retVal = function_namespace0_generated_100_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57722if((retVal = function_namespace0_generated_101_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57723if((retVal = function_namespace0_generated_102_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57724if((retVal = function_namespace0_generated_103_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57725if((retVal = function_namespace0_generated_104_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57726if((retVal = function_namespace0_generated_105_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57727if((retVal = function_namespace0_generated_106_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57728if((retVal = function_namespace0_generated_107_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57729if((retVal = function_namespace0_generated_108_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57730if((retVal = function_namespace0_generated_109_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57731if((retVal = function_namespace0_generated_110_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57732if((retVal = function_namespace0_generated_111_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57733if((retVal = function_namespace0_generated_112_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57734if((retVal = function_namespace0_generated_113_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57735if((retVal = function_namespace0_generated_114_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57736if((retVal = function_namespace0_generated_115_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57737if((retVal = function_namespace0_generated_116_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57738if((retVal = function_namespace0_generated_117_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57739if((retVal = function_namespace0_generated_118_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57740if((retVal = function_namespace0_generated_119_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57741if((retVal = function_namespace0_generated_120_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57742if((retVal = function_namespace0_generated_121_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57743if((retVal = function_namespace0_generated_122_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57744if((retVal = function_namespace0_generated_123_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57745if((retVal = function_namespace0_generated_124_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57746if((retVal = function_namespace0_generated_125_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57747if((retVal = function_namespace0_generated_126_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57748if((retVal = function_namespace0_generated_127_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57749if((retVal = function_namespace0_generated_128_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57750if((retVal = function_namespace0_generated_129_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57751if((retVal = function_namespace0_generated_130_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57752if((retVal = function_namespace0_generated_131_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57753if((retVal = function_namespace0_generated_132_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57754if((retVal = function_namespace0_generated_133_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57755if((retVal = function_namespace0_generated_134_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57756if((retVal = function_namespace0_generated_135_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57757if((retVal = function_namespace0_generated_136_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57758if((retVal = function_namespace0_generated_137_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57759if((retVal = function_namespace0_generated_138_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57760if((retVal = function_namespace0_generated_139_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57761if((retVal = function_namespace0_generated_140_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57762if((retVal = function_namespace0_generated_141_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57763if((retVal = function_namespace0_generated_142_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57764if((retVal = function_namespace0_generated_143_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57765if((retVal = function_namespace0_generated_144_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57766if((retVal = function_namespace0_generated_145_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57767if((retVal = function_namespace0_generated_146_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57768if((retVal = function_namespace0_generated_147_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57769if((retVal = function_namespace0_generated_148_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57770if((retVal = function_namespace0_generated_149_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57771if((retVal = function_namespace0_generated_150_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57772if((retVal = function_namespace0_generated_151_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57773if((retVal = function_namespace0_generated_152_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57774if((retVal = function_namespace0_generated_153_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57775if((retVal = function_namespace0_generated_154_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57776if((retVal = function_namespace0_generated_155_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57777if((retVal = function_namespace0_generated_156_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57778if((retVal = function_namespace0_generated_157_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57779if((retVal = function_namespace0_generated_158_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57780if((retVal = function_namespace0_generated_159_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57781if((retVal = function_namespace0_generated_160_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57782if((retVal = function_namespace0_generated_161_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57783if((retVal = function_namespace0_generated_162_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57784if((retVal = function_namespace0_generated_163_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57785if((retVal = function_namespace0_generated_164_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57786if((retVal = function_namespace0_generated_165_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57787if((retVal = function_namespace0_generated_166_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57788if((retVal = function_namespace0_generated_167_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57789if((retVal = function_namespace0_generated_168_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57790if((retVal = function_namespace0_generated_169_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57791if((retVal = function_namespace0_generated_170_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57792if((retVal = function_namespace0_generated_171_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57793if((retVal = function_namespace0_generated_172_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57794if((retVal = function_namespace0_generated_173_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57795if((retVal = function_namespace0_generated_174_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57796if((retVal = function_namespace0_generated_175_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57797if((retVal = function_namespace0_generated_176_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57798if((retVal = function_namespace0_generated_177_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57799if((retVal = function_namespace0_generated_178_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57800if((retVal = function_namespace0_generated_179_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57801if((retVal = function_namespace0_generated_180_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57802if((retVal = function_namespace0_generated_181_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57803if((retVal = function_namespace0_generated_182_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57804if((retVal = function_namespace0_generated_183_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57805if((retVal = function_namespace0_generated_184_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57806if((retVal = function_namespace0_generated_185_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57807if((retVal = function_namespace0_generated_186_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57808if((retVal = function_namespace0_generated_187_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57809if((retVal = function_namespace0_generated_188_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57810if((retVal = function_namespace0_generated_189_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57811if((retVal = function_namespace0_generated_190_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57812if((retVal = function_namespace0_generated_191_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57813if((retVal = function_namespace0_generated_192_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57814if((retVal = function_namespace0_generated_193_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57815if((retVal = function_namespace0_generated_194_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57816if((retVal = function_namespace0_generated_194_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57817if((retVal = function_namespace0_generated_193_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57818if((retVal = function_namespace0_generated_192_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57819if((retVal = function_namespace0_generated_191_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57820if((retVal = function_namespace0_generated_190_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57821if((retVal = function_namespace0_generated_189_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57822if((retVal = function_namespace0_generated_188_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57823if((retVal = function_namespace0_generated_187_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57824if((retVal = function_namespace0_generated_186_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57825if((retVal = function_namespace0_generated_185_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57826if((retVal = function_namespace0_generated_184_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57827if((retVal = function_namespace0_generated_183_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57828if((retVal = function_namespace0_generated_182_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57829if((retVal = function_namespace0_generated_181_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57830if((retVal = function_namespace0_generated_180_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57831if((retVal = function_namespace0_generated_179_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57832if((retVal = function_namespace0_generated_178_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57833if((retVal = function_namespace0_generated_177_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57834if((retVal = function_namespace0_generated_176_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57835if((retVal = function_namespace0_generated_175_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57836if((retVal = function_namespace0_generated_174_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57837if((retVal = function_namespace0_generated_173_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57838if((retVal = function_namespace0_generated_172_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57839if((retVal = function_namespace0_generated_171_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57840if((retVal = function_namespace0_generated_170_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57841if((retVal = function_namespace0_generated_169_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57842if((retVal = function_namespace0_generated_168_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57843if((retVal = function_namespace0_generated_167_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57844if((retVal = function_namespace0_generated_166_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57845if((retVal = function_namespace0_generated_165_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57846if((retVal = function_namespace0_generated_164_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57847if((retVal = function_namespace0_generated_163_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57848if((retVal = function_namespace0_generated_162_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57849if((retVal = function_namespace0_generated_161_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57850if((retVal = function_namespace0_generated_160_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57851if((retVal = function_namespace0_generated_159_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57852if((retVal = function_namespace0_generated_158_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57853if((retVal = function_namespace0_generated_157_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57854if((retVal = function_namespace0_generated_156_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57855if((retVal = function_namespace0_generated_155_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57856if((retVal = function_namespace0_generated_154_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57857if((retVal = function_namespace0_generated_153_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57858if((retVal = function_namespace0_generated_152_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57859if((retVal = function_namespace0_generated_151_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57860if((retVal = function_namespace0_generated_150_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57861if((retVal = function_namespace0_generated_149_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57862if((retVal = function_namespace0_generated_148_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57863if((retVal = function_namespace0_generated_147_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57864if((retVal = function_namespace0_generated_146_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57865if((retVal = function_namespace0_generated_145_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57866if((retVal = function_namespace0_generated_144_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57867if((retVal = function_namespace0_generated_143_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57868if((retVal = function_namespace0_generated_142_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57869if((retVal = function_namespace0_generated_141_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57870if((retVal = function_namespace0_generated_140_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57871if((retVal = function_namespace0_generated_139_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57872if((retVal = function_namespace0_generated_138_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57873if((retVal = function_namespace0_generated_137_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57874if((retVal = function_namespace0_generated_136_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57875if((retVal = function_namespace0_generated_135_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57876if((retVal = function_namespace0_generated_134_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57877if((retVal = function_namespace0_generated_133_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57878if((retVal = function_namespace0_generated_132_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57879if((retVal = function_namespace0_generated_131_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57880if((retVal = function_namespace0_generated_130_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57881if((retVal = function_namespace0_generated_129_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57882if((retVal = function_namespace0_generated_128_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57883if((retVal = function_namespace0_generated_127_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57884if((retVal = function_namespace0_generated_126_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57885if((retVal = function_namespace0_generated_125_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57886if((retVal = function_namespace0_generated_124_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57887if((retVal = function_namespace0_generated_123_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57888if((retVal = function_namespace0_generated_122_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57889if((retVal = function_namespace0_generated_121_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57890if((retVal = function_namespace0_generated_120_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57891if((retVal = function_namespace0_generated_119_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57892if((retVal = function_namespace0_generated_118_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57893if((retVal = function_namespace0_generated_117_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57894if((retVal = function_namespace0_generated_116_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57895if((retVal = function_namespace0_generated_115_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57896if((retVal = function_namespace0_generated_114_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57897if((retVal = function_namespace0_generated_113_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57898if((retVal = function_namespace0_generated_112_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57899if((retVal = function_namespace0_generated_111_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57900if((retVal = function_namespace0_generated_110_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57901if((retVal = function_namespace0_generated_109_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57902if((retVal = function_namespace0_generated_108_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57903if((retVal = function_namespace0_generated_107_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57904if((retVal = function_namespace0_generated_106_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57905if((retVal = function_namespace0_generated_105_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57906if((retVal = function_namespace0_generated_104_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57907if((retVal = function_namespace0_generated_103_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57908if((retVal = function_namespace0_generated_102_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57909if((retVal = function_namespace0_generated_101_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57910if((retVal = function_namespace0_generated_100_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57911if((retVal = function_namespace0_generated_99_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57912if((retVal = function_namespace0_generated_98_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57913if((retVal = function_namespace0_generated_97_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57914if((retVal = function_namespace0_generated_96_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57915if((retVal = function_namespace0_generated_95_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57916if((retVal = function_namespace0_generated_94_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57917if((retVal = function_namespace0_generated_93_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57918if((retVal = function_namespace0_generated_92_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57919if((retVal = function_namespace0_generated_91_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57920if((retVal = function_namespace0_generated_90_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57921if((retVal = function_namespace0_generated_89_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57922if((retVal = function_namespace0_generated_88_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57923if((retVal = function_namespace0_generated_87_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57924if((retVal = function_namespace0_generated_86_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57925if((retVal = function_namespace0_generated_85_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57926if((retVal = function_namespace0_generated_84_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57927if((retVal = function_namespace0_generated_83_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57928if((retVal = function_namespace0_generated_82_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57929if((retVal = function_namespace0_generated_81_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57930if((retVal = function_namespace0_generated_80_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57931if((retVal = function_namespace0_generated_79_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57932if((retVal = function_namespace0_generated_78_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57933if((retVal = function_namespace0_generated_77_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57934if((retVal = function_namespace0_generated_76_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57935if((retVal = function_namespace0_generated_75_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57936if((retVal = function_namespace0_generated_74_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57937if((retVal = function_namespace0_generated_73_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57938if((retVal = function_namespace0_generated_72_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57939if((retVal = function_namespace0_generated_71_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57940if((retVal = function_namespace0_generated_70_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57941if((retVal = function_namespace0_generated_69_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57942if((retVal = function_namespace0_generated_68_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57943if((retVal = function_namespace0_generated_67_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57944if((retVal = function_namespace0_generated_66_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57945if((retVal = function_namespace0_generated_65_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57946if((retVal = function_namespace0_generated_64_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57947if((retVal = function_namespace0_generated_63_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57948if((retVal = function_namespace0_generated_62_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57949if((retVal = function_namespace0_generated_61_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57950if((retVal = function_namespace0_generated_60_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57951if((retVal = function_namespace0_generated_59_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57952if((retVal = function_namespace0_generated_58_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57953if((retVal = function_namespace0_generated_57_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57954if((retVal = function_namespace0_generated_56_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57955if((retVal = function_namespace0_generated_55_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57956if((retVal = function_namespace0_generated_54_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57957if((retVal = function_namespace0_generated_53_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57958if((retVal = function_namespace0_generated_52_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57959if((retVal = function_namespace0_generated_51_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57960if((retVal = function_namespace0_generated_50_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57961if((retVal = function_namespace0_generated_49_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57962if((retVal = function_namespace0_generated_48_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57963if((retVal = function_namespace0_generated_47_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57964if((retVal = function_namespace0_generated_46_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57965if((retVal = function_namespace0_generated_45_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57966if((retVal = function_namespace0_generated_44_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57967if((retVal = function_namespace0_generated_43_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57968if((retVal = function_namespace0_generated_42_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57969if((retVal = function_namespace0_generated_41_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57970if((retVal = function_namespace0_generated_40_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57971if((retVal = function_namespace0_generated_39_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57972if((retVal = function_namespace0_generated_38_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57973if((retVal = function_namespace0_generated_37_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57974if((retVal = function_namespace0_generated_36_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57975if((retVal = function_namespace0_generated_35_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57976if((retVal = function_namespace0_generated_34_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57977if((retVal = function_namespace0_generated_33_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57978if((retVal = function_namespace0_generated_32_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57979if((retVal = function_namespace0_generated_31_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57980if((retVal = function_namespace0_generated_30_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57981if((retVal = function_namespace0_generated_29_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57982if((retVal = function_namespace0_generated_28_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57983if((retVal = function_namespace0_generated_27_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57984if((retVal = function_namespace0_generated_26_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57985if((retVal = function_namespace0_generated_25_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57986if((retVal = function_namespace0_generated_24_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57987if((retVal = function_namespace0_generated_23_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57988if((retVal = function_namespace0_generated_22_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57989if((retVal = function_namespace0_generated_21_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57990if((retVal = function_namespace0_generated_20_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57991if((retVal = function_namespace0_generated_19_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57992if((retVal = function_namespace0_generated_18_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57993if((retVal = function_namespace0_generated_17_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57994if((retVal = function_namespace0_generated_16_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57995if((retVal = function_namespace0_generated_15_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57996if((retVal = function_namespace0_generated_14_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57997if((retVal = function_namespace0_generated_13_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57998if((retVal = function_namespace0_generated_12_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
57999if((retVal = function_namespace0_generated_11_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58000if((retVal = function_namespace0_generated_10_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58001if((retVal = function_namespace0_generated_9_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58002if((retVal = function_namespace0_generated_8_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58003if((retVal = function_namespace0_generated_7_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58004if((retVal = function_namespace0_generated_6_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal;
58005return retVal;
58006}
58007
58008/**** amalgamated original file "/src/ua_types_lex.c" ****/
58009
58010/* Generated by re2c 1.1.1 */
58011/* This Source Code Form is subject to the terms of the Mozilla Public
58012 * License, v. 2.0. If a copy of the MPL was not distributed with this
58013 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
58014 *
58015 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
58016 *
58017 */
58018
58019
58020/* Lexing and parsing of builtin data types. These are helper functions that not
58021 * required by the SDK internally. But they are useful for users who want to use
58022 * standard-specified humand readable encodings for NodeIds, etc.
58023 *
58024 * This compilation unit uses the re2c lexer generator. The final C source is
58025 * generated with the following script:
58026 *
58027 * re2c -i --no-generation-date ua_types_lex.re > ua_types_lex.c
58028 *
58029 * In order that users of the SDK don't need to install re2c, always commit a
58030 * recent ua_types_lex.c if changes are made to the lexer. */
58031
58032#define YYCURSOR pos
58033#define YYMARKER context.marker
58034#define YYPEEK() (YYCURSOR < end) ? *YYCURSOR : 0 /* The lexer sees a stream of
58035 * \0 when the input ends*/
58036#define YYSKIP() ++YYCURSOR;
58037#define YYBACKUP() YYMARKER = YYCURSOR
58038#define YYRESTORE() YYCURSOR = YYMARKER
58039#define YYSTAGP(t) t = YYCURSOR
58040#define YYSTAGN(t) t = NULL
58041
58042typedef struct {
58043 const char *marker;
58044 const char *yyt1;const char *yyt2;const char *yyt3;const char *yyt4;const char *yyt5;
58045} LexContext;
58046
58047
58048
58049static UA_StatusCode
58050parse_guid(UA_Guid *guid, const UA_Byte *s, const UA_Byte *e) {
58051 size_t len = (size_t)(e - s);
58052 if(len != 36 || s[8] != '-' || s[13] != '-' || s[23] != '-')
58053 return UA_STATUSCODE_BADINTERNALERROR;
58054
58055 UA_UInt32 tmp;
58056 if(UA_readNumberWithBase(buf: s, buflen: 8, number: &tmp, base: 16) != 8)
58057 return UA_STATUSCODE_BADINTERNALERROR;
58058 guid->data1 = tmp;
58059
58060 if(UA_readNumberWithBase(buf: &s[9], buflen: 4, number: &tmp, base: 16) != 4)
58061 return UA_STATUSCODE_BADINTERNALERROR;
58062 guid->data2 = (UA_UInt16)tmp;
58063
58064 if(UA_readNumberWithBase(buf: &s[14], buflen: 4, number: &tmp, base: 16) != 4)
58065 return UA_STATUSCODE_BADINTERNALERROR;
58066 guid->data3 = (UA_UInt16)tmp;
58067
58068 if(UA_readNumberWithBase(buf: &s[19], buflen: 2, number: &tmp, base: 16) != 2)
58069 return UA_STATUSCODE_BADINTERNALERROR;
58070 guid->data4[0] = (UA_Byte)tmp;
58071
58072 if(UA_readNumberWithBase(buf: &s[21], buflen: 2, number: &tmp, base: 16) != 2)
58073 return UA_STATUSCODE_BADINTERNALERROR;
58074 guid->data4[1] = (UA_Byte)tmp;
58075
58076 for(size_t pos = 2, spos = 24; pos < 8; pos++, spos += 2) {
58077 if(UA_readNumberWithBase(buf: &s[spos], buflen: 2, number: &tmp, base: 16) != 2)
58078 return UA_STATUSCODE_BADINTERNALERROR;
58079 guid->data4[pos] = (UA_Byte)tmp;
58080 }
58081
58082 return UA_STATUSCODE_GOOD;
58083}
58084
58085UA_StatusCode
58086UA_Guid_parse(UA_Guid *guid, const UA_String str) {
58087 UA_StatusCode res = parse_guid(guid, s: str.data, e: str.data + str.length);
58088 if(res != UA_STATUSCODE_GOOD)
58089 *guid = UA_GUID_NULL;
58090 return res;
58091}
58092
58093static UA_StatusCode
58094parse_nodeid_body(UA_NodeId *id, const char *body, const char *end) {
58095 size_t len = (size_t)(end - (body+2));
58096 UA_StatusCode res = UA_STATUSCODE_GOOD;
58097 switch(*body) {
58098 case 'i': {
58099 if(UA_readNumber(buf: (const UA_Byte*)body+2, buflen: len, number: &id->identifier.numeric) != len)
58100 return UA_STATUSCODE_BADINTERNALERROR;
58101 id->identifierType = UA_NODEIDTYPE_NUMERIC;
58102 break;
58103 }
58104 case 's': {
58105 UA_String tmpstr;
58106 tmpstr.data = (UA_Byte*)(uintptr_t)body+2;
58107 tmpstr.length = len;
58108 res = UA_String_copy(src: &tmpstr, dst: &id->identifier.string);
58109 if(res != UA_STATUSCODE_GOOD)
58110 break;
58111 id->identifierType = UA_NODEIDTYPE_STRING;
58112 break;
58113 }
58114 case 'g':
58115 res = parse_guid(guid: &id->identifier.guid, s: (const UA_Byte*)body+2, e: (const UA_Byte*)end);
58116 if(res == UA_STATUSCODE_GOOD)
58117 id->identifierType = UA_NODEIDTYPE_GUID;
58118 break;
58119 case 'b':
58120 id->identifier.byteString.data =
58121 UA_unbase64(src: (const unsigned char*)body+2, len,
58122 out_len: &id->identifier.byteString.length);
58123 if(!id->identifier.byteString.data && len > 0)
58124 return UA_STATUSCODE_BADINTERNALERROR;
58125 id->identifierType = UA_NODEIDTYPE_BYTESTRING;
58126 break;
58127 default:
58128 return UA_STATUSCODE_BADINTERNALERROR;
58129 }
58130 return res;
58131}
58132
58133static UA_StatusCode
58134parse_nodeid(UA_NodeId *id, const char *pos, const char *end) {
58135 *id = UA_NODEID_NULL; /* Reset the NodeId */
58136 LexContext context;
58137 memset(s: &context, c: 0, n: sizeof(LexContext));
58138 const char *ns = NULL, *nse= NULL;
58139
58140
58141{
58142 char yych;
58143 yych = YYPEEK ();
58144 switch (yych) {
58145 case 'b':
58146 case 'g':
58147 case 'i':
58148 case 's':
58149 YYSTAGN (context.yyt1);
58150 YYSTAGN (context.yyt2);
58151 goto yy4;
58152 case 'n': goto yy5;
58153 default: goto yy2;
58154 }
58155yy2:
58156 YYSKIP ();
58157yy3:
58158 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
58159yy4:
58160 YYSKIP ();
58161 yych = YYPEEK ();
58162 switch (yych) {
58163 case '=': goto yy6;
58164 default: goto yy3;
58165 }
58166yy5:
58167 YYSKIP ();
58168 YYBACKUP ();
58169 yych = YYPEEK ();
58170 switch (yych) {
58171 case 's': goto yy8;
58172 default: goto yy3;
58173 }
58174yy6:
58175 YYSKIP ();
58176 ns = context.yyt1;
58177 nse = context.yyt2;
58178 {
58179 (void)pos; // Get rid of a dead store clang-analyzer warning
58180 if(ns) {
58181 UA_UInt32 tmp;
58182 size_t len = (size_t)(nse - ns);
58183 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58184 return UA_STATUSCODE_BADINTERNALERROR;
58185 id->namespaceIndex = (UA_UInt16)tmp;
58186 }
58187
58188 // From the current position until the end
58189 return parse_nodeid_body(id, body: &pos[-2], end);
58190 }
58191yy8:
58192 YYSKIP ();
58193 yych = YYPEEK ();
58194 switch (yych) {
58195 case '=': goto yy10;
58196 default: goto yy9;
58197 }
58198yy9:
58199 YYRESTORE ();
58200 goto yy3;
58201yy10:
58202 YYSKIP ();
58203 yych = YYPEEK ();
58204 switch (yych) {
58205 case '0':
58206 case '1':
58207 case '2':
58208 case '3':
58209 case '4':
58210 case '5':
58211 case '6':
58212 case '7':
58213 case '8':
58214 case '9':
58215 YYSTAGP (context.yyt1);
58216 goto yy11;
58217 default: goto yy9;
58218 }
58219yy11:
58220 YYSKIP ();
58221 yych = YYPEEK ();
58222 switch (yych) {
58223 case '0':
58224 case '1':
58225 case '2':
58226 case '3':
58227 case '4':
58228 case '5':
58229 case '6':
58230 case '7':
58231 case '8':
58232 case '9': goto yy11;
58233 case ';':
58234 YYSTAGP (context.yyt2);
58235 goto yy13;
58236 default: goto yy9;
58237 }
58238yy13:
58239 YYSKIP ();
58240 yych = YYPEEK ();
58241 switch (yych) {
58242 case 'b':
58243 case 'g':
58244 case 'i':
58245 case 's': goto yy14;
58246 default: goto yy9;
58247 }
58248yy14:
58249 YYSKIP ();
58250 yych = YYPEEK ();
58251 switch (yych) {
58252 case '=': goto yy6;
58253 default: goto yy9;
58254 }
58255}
58256
58257}
58258
58259UA_StatusCode
58260UA_NodeId_parse(UA_NodeId *id, const UA_String str) {
58261 UA_StatusCode res =
58262 parse_nodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58263 if(res != UA_STATUSCODE_GOOD)
58264 UA_NodeId_clear(p: id);
58265 return res;
58266}
58267
58268static UA_StatusCode
58269parse_expandednodeid(UA_ExpandedNodeId *id, const char *pos, const char *end) {
58270 *id = UA_EXPANDEDNODEID_NULL; /* Reset the NodeId */
58271 LexContext context;
58272 memset(s: &context, c: 0, n: sizeof(LexContext));
58273 const char *svr = NULL, *svre = NULL, *nsu = NULL, *ns = NULL, *body = NULL;
58274
58275
58276{
58277 char yych;
58278 yych = YYPEEK ();
58279 switch (yych) {
58280 case 'b':
58281 case 'g':
58282 case 'i':
58283 YYSTAGN (context.yyt1);
58284 YYSTAGN (context.yyt2);
58285 YYSTAGN (context.yyt3);
58286 YYSTAGP (context.yyt4);
58287 YYSTAGN (context.yyt5);
58288 goto yy19;
58289 case 'n':
58290 YYSTAGN (context.yyt1);
58291 YYSTAGN (context.yyt2);
58292 goto yy20;
58293 case 's':
58294 YYSTAGN (context.yyt1);
58295 YYSTAGN (context.yyt2);
58296 YYSTAGN (context.yyt3);
58297 YYSTAGP (context.yyt4);
58298 YYSTAGN (context.yyt5);
58299 goto yy21;
58300 default: goto yy17;
58301 }
58302yy17:
58303 YYSKIP ();
58304yy18:
58305 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
58306yy19:
58307 YYSKIP ();
58308 yych = YYPEEK ();
58309 switch (yych) {
58310 case '=': goto yy22;
58311 default: goto yy18;
58312 }
58313yy20:
58314 YYSKIP ();
58315 YYBACKUP ();
58316 yych = YYPEEK ();
58317 switch (yych) {
58318 case 's': goto yy24;
58319 default: goto yy18;
58320 }
58321yy21:
58322 YYSKIP ();
58323 YYBACKUP ();
58324 yych = YYPEEK ();
58325 switch (yych) {
58326 case '=': goto yy22;
58327 case 'v': goto yy26;
58328 default: goto yy18;
58329 }
58330yy22:
58331 YYSKIP ();
58332 svr = context.yyt1;
58333 svre = context.yyt2;
58334 ns = context.yyt3;
58335 nsu = context.yyt5;
58336 body = context.yyt4;
58337 {
58338 (void)pos; // Get rid of a dead store clang-analyzer warning
58339 if(svr) {
58340 size_t len = (size_t)((svre) - svr);
58341 if(UA_readNumber(buf: (const UA_Byte*)svr, buflen: len, number: &id->serverIndex) != len)
58342 return UA_STATUSCODE_BADINTERNALERROR;
58343 }
58344
58345 if(nsu) {
58346 size_t len = (size_t)((body-1) - nsu);
58347 UA_String nsuri;
58348 nsuri.data = (UA_Byte*)(uintptr_t)nsu;
58349 nsuri.length = len;
58350 UA_StatusCode res = UA_String_copy(src: &nsuri, dst: &id->namespaceUri);
58351 if(res != UA_STATUSCODE_GOOD)
58352 return res;
58353 } else if(ns) {
58354 UA_UInt32 tmp;
58355 size_t len = (size_t)((body-1) - ns);
58356 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58357 return UA_STATUSCODE_BADINTERNALERROR;
58358 id->nodeId.namespaceIndex = (UA_UInt16)tmp;
58359 }
58360
58361 // From the current position until the end
58362 return parse_nodeid_body(id: &id->nodeId, body: &pos[-2], end);
58363 }
58364yy24:
58365 YYSKIP ();
58366 yych = YYPEEK ();
58367 switch (yych) {
58368 case '=': goto yy27;
58369 case 'u': goto yy28;
58370 default: goto yy25;
58371 }
58372yy25:
58373 YYRESTORE ();
58374 goto yy18;
58375yy26:
58376 YYSKIP ();
58377 yych = YYPEEK ();
58378 switch (yych) {
58379 case 'r': goto yy29;
58380 default: goto yy25;
58381 }
58382yy27:
58383 YYSKIP ();
58384 yych = YYPEEK ();
58385 switch (yych) {
58386 case '0':
58387 case '1':
58388 case '2':
58389 case '3':
58390 case '4':
58391 case '5':
58392 case '6':
58393 case '7':
58394 case '8':
58395 case '9':
58396 YYSTAGP (context.yyt3);
58397 goto yy30;
58398 default: goto yy25;
58399 }
58400yy28:
58401 YYSKIP ();
58402 yych = YYPEEK ();
58403 switch (yych) {
58404 case '=': goto yy32;
58405 default: goto yy25;
58406 }
58407yy29:
58408 YYSKIP ();
58409 yych = YYPEEK ();
58410 switch (yych) {
58411 case '=': goto yy33;
58412 default: goto yy25;
58413 }
58414yy30:
58415 YYSKIP ();
58416 yych = YYPEEK ();
58417 switch (yych) {
58418 case '0':
58419 case '1':
58420 case '2':
58421 case '3':
58422 case '4':
58423 case '5':
58424 case '6':
58425 case '7':
58426 case '8':
58427 case '9': goto yy30;
58428 case ';': goto yy34;
58429 default: goto yy25;
58430 }
58431yy32:
58432 YYSKIP ();
58433 yych = YYPEEK ();
58434 switch (yych) {
58435 case '\n': goto yy25;
58436 case ';':
58437 YYSTAGP (context.yyt5);
58438 goto yy37;
58439 default:
58440 YYSTAGP (context.yyt5);
58441 goto yy35;
58442 }
58443yy33:
58444 YYSKIP ();
58445 yych = YYPEEK ();
58446 switch (yych) {
58447 case '0':
58448 case '1':
58449 case '2':
58450 case '3':
58451 case '4':
58452 case '5':
58453 case '6':
58454 case '7':
58455 case '8':
58456 case '9':
58457 YYSTAGP (context.yyt1);
58458 goto yy38;
58459 default: goto yy25;
58460 }
58461yy34:
58462 YYSKIP ();
58463 yych = YYPEEK ();
58464 switch (yych) {
58465 case 'b':
58466 case 'g':
58467 case 'i':
58468 case 's':
58469 YYSTAGP (context.yyt4);
58470 YYSTAGN (context.yyt5);
58471 goto yy40;
58472 default: goto yy25;
58473 }
58474yy35:
58475 YYSKIP ();
58476 yych = YYPEEK ();
58477 switch (yych) {
58478 case '\n': goto yy25;
58479 case ';': goto yy37;
58480 default: goto yy35;
58481 }
58482yy37:
58483 YYSKIP ();
58484 yych = YYPEEK ();
58485 switch (yych) {
58486 case 'b':
58487 case 'g':
58488 case 'i':
58489 case 's':
58490 YYSTAGN (context.yyt3);
58491 YYSTAGP (context.yyt4);
58492 goto yy40;
58493 default: goto yy25;
58494 }
58495yy38:
58496 YYSKIP ();
58497 yych = YYPEEK ();
58498 switch (yych) {
58499 case '0':
58500 case '1':
58501 case '2':
58502 case '3':
58503 case '4':
58504 case '5':
58505 case '6':
58506 case '7':
58507 case '8':
58508 case '9': goto yy38;
58509 case ';':
58510 YYSTAGP (context.yyt2);
58511 goto yy41;
58512 default: goto yy25;
58513 }
58514yy40:
58515 YYSKIP ();
58516 yych = YYPEEK ();
58517 switch (yych) {
58518 case '=': goto yy22;
58519 default: goto yy25;
58520 }
58521yy41:
58522 YYSKIP ();
58523 yych = YYPEEK ();
58524 switch (yych) {
58525 case 'b':
58526 case 'g':
58527 case 'i':
58528 case 's':
58529 YYSTAGN (context.yyt3);
58530 YYSTAGP (context.yyt4);
58531 YYSTAGN (context.yyt5);
58532 goto yy40;
58533 case 'n': goto yy42;
58534 default: goto yy25;
58535 }
58536yy42:
58537 YYSKIP ();
58538 yych = YYPEEK ();
58539 switch (yych) {
58540 case 's': goto yy24;
58541 default: goto yy25;
58542 }
58543}
58544
58545}
58546
58547UA_StatusCode
58548UA_ExpandedNodeId_parse(UA_ExpandedNodeId *id, const UA_String str) {
58549 UA_StatusCode res =
58550 parse_expandednodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58551 if(res != UA_STATUSCODE_GOOD)
58552 UA_ExpandedNodeId_clear(p: id);
58553 return res;
58554}
58555
58556static UA_StatusCode
58557relativepath_addelem(UA_RelativePath *rp, UA_RelativePathElement *el) {
58558 /* Allocate memory */
58559 UA_RelativePathElement *newArray = (UA_RelativePathElement*)
58560 UA_realloc(ptr: rp->elements, size: sizeof(UA_RelativePathElement) * (rp->elementsSize + 1));
58561 if(!newArray)
58562 return UA_STATUSCODE_BADOUTOFMEMORY;
58563 rp->elements = newArray;
58564
58565 /* Move to the target */
58566 rp->elements[rp->elementsSize] = *el;
58567 rp->elementsSize++;
58568 return UA_STATUSCODE_GOOD;
58569}
58570
58571/* Parse name string with '&' as the escape character */
58572static UA_StatusCode
58573parse_refpath_qn_name(UA_QualifiedName *qn, const char **pos, const char *end) {
58574 /* Allocate the max length the name can have */
58575 size_t maxlen = (size_t)(end - *pos);
58576 if(maxlen == 0) {
58577 qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
58578 return UA_STATUSCODE_GOOD;
58579 }
58580 char *name = (char*)UA_malloc(size: maxlen);
58581 if(!name)
58582 return UA_STATUSCODE_BADOUTOFMEMORY;
58583
58584 size_t index = 0;
58585 for(; *pos < end; (*pos)++) {
58586 char c = **pos;
58587 /* Unescaped special characer: The end of the QualifiedName */
58588 if(c == '/' || c == '.' || c == '<' || c == '>' ||
58589 c == ':' || c == '#' || c == '!')
58590 break;
58591
58592 /* Escaped character */
58593 if(c == '&') {
58594 (*pos)++;
58595 if(*pos >= end ||
58596 (**pos != '/' && **pos != '.' && **pos != '<' && **pos != '>' &&
58597 **pos != ':' && **pos != '#' && **pos != '!' && **pos != '&')) {
58598 UA_free(ptr: name);
58599 return UA_STATUSCODE_BADINTERNALERROR;
58600 }
58601 c = **pos;
58602 }
58603
58604 /* Unescaped normal character */
58605 name[index] = c;
58606 index++;
58607 }
58608
58609 if(index > 0) {
58610 qn->name.data = (UA_Byte*)name;
58611 qn->name.length = index;
58612 } else {
58613 qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL;
58614 UA_free(ptr: name);
58615 }
58616 return UA_STATUSCODE_GOOD;
58617}
58618
58619static UA_StatusCode
58620parse_refpath_qn(UA_QualifiedName *qn, const char *pos, const char *end) {
58621 LexContext context;
58622 memset(s: &context, c: 0, n: sizeof(LexContext));
58623 const char *ns = NULL, *nse = NULL;
58624 UA_QualifiedName_init(p: qn);
58625
58626
58627{
58628 char yych;
58629 yych = YYPEEK ();
58630 switch (yych) {
58631 case '0':
58632 case '1':
58633 case '2':
58634 case '3':
58635 case '4':
58636 case '5':
58637 case '6':
58638 case '7':
58639 case '8':
58640 case '9':
58641 YYSTAGP (context.yyt1);
58642 goto yy47;
58643 default: goto yy45;
58644 }
58645yy45:
58646 YYSKIP ();
58647yy46:
58648 { pos--; goto parse_qn_name; }
58649yy47:
58650 YYSKIP ();
58651 YYBACKUP ();
58652 yych = YYPEEK ();
58653 switch (yych) {
58654 case '0':
58655 case '1':
58656 case '2':
58657 case '3':
58658 case '4':
58659 case '5':
58660 case '6':
58661 case '7':
58662 case '8':
58663 case '9':
58664 case ':': goto yy49;
58665 default: goto yy46;
58666 }
58667yy48:
58668 YYSKIP ();
58669 yych = YYPEEK ();
58670yy49:
58671 switch (yych) {
58672 case '0':
58673 case '1':
58674 case '2':
58675 case '3':
58676 case '4':
58677 case '5':
58678 case '6':
58679 case '7':
58680 case '8':
58681 case '9': goto yy48;
58682 case ':':
58683 YYSTAGP (context.yyt2);
58684 goto yy51;
58685 default: goto yy50;
58686 }
58687yy50:
58688 YYRESTORE ();
58689 goto yy46;
58690yy51:
58691 YYSKIP ();
58692 ns = context.yyt1;
58693 nse = context.yyt2;
58694 {
58695 UA_UInt32 tmp;
58696 size_t len = (size_t)(nse - ns);
58697 if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len)
58698 return UA_STATUSCODE_BADINTERNALERROR;
58699 qn->namespaceIndex = (UA_UInt16)tmp;
58700 goto parse_qn_name;
58701 }
58702}
58703
58704
58705 parse_qn_name:
58706 return parse_refpath_qn_name(qn, pos: &pos, end);
58707}
58708
58709/* List of well-known ReferenceTypes that don't require lookup in the server */
58710
58711typedef struct {
58712 char *browseName;
58713 UA_UInt32 identifier;
58714} RefTypeNames;
58715
58716#define KNOWNREFTYPES 17
58717static const RefTypeNames knownRefTypes[KNOWNREFTYPES] = {
58718 {"References", UA_NS0ID_REFERENCES},
58719 {"HierachicalReferences", UA_NS0ID_HIERARCHICALREFERENCES},
58720 {"NonHierachicalReferences", UA_NS0ID_NONHIERARCHICALREFERENCES},
58721 {"HasChild", UA_NS0ID_HASCHILD},
58722 {"Aggregates", UA_NS0ID_AGGREGATES},
58723 {"HasComponent", UA_NS0ID_HASCOMPONENT},
58724 {"HasProperty", UA_NS0ID_HASPROPERTY},
58725 {"HasOrderedComponent", UA_NS0ID_HASORDEREDCOMPONENT},
58726 {"HasSubtype", UA_NS0ID_HASSUBTYPE},
58727 {"Organizes", UA_NS0ID_ORGANIZES},
58728 {"HasModellingRule", UA_NS0ID_HASMODELLINGRULE},
58729 {"HasTypeDefinition", UA_NS0ID_HASTYPEDEFINITION},
58730 {"HasEncoding", UA_NS0ID_HASENCODING},
58731 {"GeneratesEvent", UA_NS0ID_GENERATESEVENT},
58732 {"AlwaysGeneratesEvent", UA_NS0ID_ALWAYSGENERATESEVENT},
58733 {"HasEventSource", UA_NS0ID_HASEVENTSOURCE},
58734 {"HasNotifier", UA_NS0ID_HASNOTIFIER}
58735};
58736
58737static UA_StatusCode
58738lookup_reftype(UA_NodeId *refTypeId, UA_QualifiedName *qn) {
58739 if(qn->namespaceIndex != 0)
58740 return UA_STATUSCODE_BADNOTFOUND;
58741
58742 for(size_t i = 0; i < KNOWNREFTYPES; i++) {
58743 UA_String tmp = UA_STRING(chars: knownRefTypes[i].browseName);
58744 if(UA_String_equal(s1: &qn->name, s2: &tmp)) {
58745 *refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: knownRefTypes[i].identifier);
58746 return UA_STATUSCODE_GOOD;
58747 }
58748 }
58749
58750 return UA_STATUSCODE_BADNOTFOUND;
58751}
58752
58753static UA_StatusCode
58754parse_relativepath(UA_RelativePath *rp, const char *pos, const char *end) {
58755 LexContext context;
58756 memset(s: &context, c: 0, n: sizeof(LexContext));
58757 const char *begin = NULL, *finish = NULL;
58758 UA_StatusCode res = UA_STATUSCODE_GOOD;
58759 UA_RelativePath_init(p: rp); /* Reset the BrowsePath */
58760
58761 /* Add one element to the path in every iteration */
58762 UA_RelativePathElement current;
58763 loop:
58764 UA_RelativePathElement_init(p: &current);
58765 current.includeSubtypes = true; /* Follow subtypes by default */
58766
58767 /* Get the ReferenceType and its modifiers */
58768
58769{
58770 char yych;
58771 unsigned int yyaccept = 0;
58772 yych = YYPEEK ();
58773 switch (yych) {
58774 case 0x00: goto yy55;
58775 case '.': goto yy59;
58776 case '/': goto yy61;
58777 case '<': goto yy63;
58778 default: goto yy57;
58779 }
58780yy55:
58781 YYSKIP ();
58782 { (void)pos; return UA_STATUSCODE_GOOD; }
58783yy57:
58784 YYSKIP ();
58785yy58:
58786 { (void)pos; return UA_STATUSCODE_BADINTERNALERROR; }
58787yy59:
58788 YYSKIP ();
58789 {
58790 current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES);
58791 goto reftype_target;
58792 }
58793yy61:
58794 YYSKIP ();
58795 {
58796 current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES);
58797 goto reftype_target;
58798 }
58799yy63:
58800 yyaccept = 0;
58801 YYSKIP ();
58802 YYBACKUP ();
58803 yych = YYPEEK ();
58804 switch (yych) {
58805 case 0x00:
58806 case '>': goto yy58;
58807 case '&':
58808 YYSTAGP (context.yyt1);
58809 goto yy67;
58810 default:
58811 YYSTAGP (context.yyt1);
58812 goto yy64;
58813 }
58814yy64:
58815 YYSKIP ();
58816 yych = YYPEEK ();
58817 switch (yych) {
58818 case 0x00: goto yy66;
58819 case '&': goto yy67;
58820 case '>':
58821 YYSTAGP (context.yyt2);
58822 goto yy69;
58823 default: goto yy64;
58824 }
58825yy66:
58826 YYRESTORE ();
58827 if (yyaccept == 0) {
58828 goto yy58;
58829 } else {
58830 goto yy70;
58831 }
58832yy67:
58833 YYSKIP ();
58834 yych = YYPEEK ();
58835 switch (yych) {
58836 case 0x00: goto yy66;
58837 case '&': goto yy67;
58838 case '>':
58839 YYSTAGP (context.yyt2);
58840 goto yy71;
58841 default: goto yy64;
58842 }
58843yy69:
58844 YYSKIP ();
58845yy70:
58846 begin = context.yyt1;
58847 finish = context.yyt2;
58848 {
58849 for(; begin < finish; begin++) {
58850 if(*begin== '#')
58851 current.includeSubtypes = false;
58852 else if(*begin == '!')
58853 current.isInverse = true;
58854 else
58855 break;
58856 }
58857 UA_QualifiedName refqn;
58858 res |= parse_refpath_qn(qn: &refqn, pos: begin, end: finish);
58859 res |= lookup_reftype(refTypeId: &current.referenceTypeId, qn: &refqn);
58860 UA_QualifiedName_clear(p: &refqn);
58861 goto reftype_target;
58862 }
58863yy71:
58864 yyaccept = 1;
58865 YYSKIP ();
58866 YYBACKUP ();
58867 yych = YYPEEK ();
58868 switch (yych) {
58869 case 0x00: goto yy70;
58870 case '&': goto yy67;
58871 case '>':
58872 YYSTAGP (context.yyt2);
58873 goto yy69;
58874 default: goto yy64;
58875 }
58876}
58877
58878
58879 /* Get the TargetName component */
58880 reftype_target:
58881 if(res != UA_STATUSCODE_GOOD)
58882 return res;
58883
58884
58885{
58886 char yych;
58887 yych = YYPEEK ();
58888 switch (yych) {
58889 case 0x00:
58890 case '.':
58891 case '/':
58892 case '<': goto yy74;
58893 case '&':
58894 YYSTAGP (context.yyt1);
58895 goto yy79;
58896 default:
58897 YYSTAGP (context.yyt1);
58898 goto yy76;
58899 }
58900yy74:
58901 YYSKIP ();
58902 { pos--; goto add_element; }
58903yy76:
58904 YYSKIP ();
58905 yych = YYPEEK ();
58906 switch (yych) {
58907 case 0x00:
58908 case '.':
58909 case '/':
58910 case '<': goto yy78;
58911 case '&': goto yy79;
58912 default: goto yy76;
58913 }
58914yy78:
58915 begin = context.yyt1;
58916 {
58917 res = parse_refpath_qn(qn: &current.targetName, pos: begin, end: pos);
58918 goto add_element;
58919 }
58920yy79:
58921 YYSKIP ();
58922 yych = YYPEEK ();
58923 switch (yych) {
58924 case 0x00: goto yy78;
58925 case '&': goto yy79;
58926 default: goto yy76;
58927 }
58928}
58929
58930
58931 /* Add the current element to the path and continue to the next element */
58932 add_element:
58933 res |= relativepath_addelem(rp, el: &current);
58934 if(res != UA_STATUSCODE_GOOD) {
58935 UA_RelativePathElement_clear(p: &current);
58936 return res;
58937 }
58938 goto loop;
58939}
58940
58941UA_StatusCode
58942UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str) {
58943 UA_StatusCode res =
58944 parse_relativepath(rp, pos: (const char*)str.data, end: (const char*)str.data+str.length);
58945 if(res != UA_STATUSCODE_GOOD)
58946 UA_RelativePath_clear(p: rp);
58947 return res;
58948}
58949
58950/**** amalgamated original file "/src/server/ua_subscription.c" ****/
58951
58952/* This Source Code Form is subject to the terms of the Mozilla Public
58953 * License, v. 2.0. If a copy of the MPL was not distributed with this
58954 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
58955 *
58956 * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
58957 * Copyright 2015 (c) Chris Iatrou
58958 * Copyright 2015-2016 (c) Sten Grüner
58959 * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA
58960 * Copyright 2015 (c) Joakim L. Gilje
58961 * Copyright 2016-2017 (c) Florian Palm
58962 * Copyright 2015-2016 (c) Oleksiy Vasylyev
58963 * Copyright 2017 (c) frax2222
58964 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
58965 * Copyright 2017 (c) Ari Breitkreuz, fortiss GmbH
58966 * Copyright 2017 (c) Mattias Bornhager
58967 * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
58968 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
58969 */
58970
58971
58972#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
58973
58974#define UA_MAX_RETRANSMISSIONQUEUESIZE 256
58975
58976UA_Subscription *
58977UA_Subscription_new(void) {
58978 /* Allocate the memory */
58979 UA_Subscription *newSub = (UA_Subscription*)UA_calloc(nmemb: 1, size: sizeof(UA_Subscription));
58980 if(!newSub)
58981 return NULL;
58982
58983 /* The first publish response is sent immediately */
58984 newSub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
58985
58986 /* Even if the first publish response is a keepalive the sequence number is 1.
58987 * This can happen by a subscription without a monitored item (see CTT test scripts). */
58988 newSub->nextSequenceNumber = 1;
58989
58990 TAILQ_INIT(&newSub->retransmissionQueue);
58991 TAILQ_INIT(&newSub->notificationQueue);
58992 return newSub;
58993}
58994
58995void
58996UA_Subscription_delete(UA_Server *server, UA_Subscription *sub) {
58997 UA_LOCK_ASSERT(&server->serviceMutex, 1);
58998
58999 /* Unregister the publish callback */
59000 Subscription_unregisterPublishCallback(server, sub);
59001
59002 /* Remove the diagnostics object for the subscription */
59003#ifdef UA_ENABLE_DIAGNOSTICS
59004 if(sub->session) {
59005 /* Use a browse path to find the node */
59006 char subIdStr[32];
59007 snprintf(subIdStr, 32, "%u", sub->subscriptionId);
59008 UA_BrowsePath bp;
59009 UA_BrowsePath_init(&bp);
59010 bp.startingNode = sub->session->sessionId;
59011 UA_RelativePathElement rpe[2];
59012 memset(rpe, 0, sizeof(UA_RelativePathElement) * 2);
59013 rpe[0].targetName = UA_QUALIFIEDNAME(0, "SubscriptionDiagnosticsArray");
59014 rpe[1].targetName = UA_QUALIFIEDNAME(0, subIdStr);
59015 bp.relativePath.elements = rpe;
59016 bp.relativePath.elementsSize = 2;
59017 UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, &bp);
59018
59019 /* Delete all nodes matching the browse path */
59020 for(size_t i = 0; i < bpr.targetsSize; i++) {
59021 if(bpr.targets[i].remainingPathIndex < UA_UINT32_MAX)
59022 continue;
59023 deleteNode(server, bpr.targets[i].targetId.nodeId, true);
59024 }
59025 UA_BrowsePathResult_clear(&bpr);
59026 }
59027#endif
59028
59029 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub, "Subscription deleted");
59030
59031 /* Detach from the session if necessary */
59032 if(sub->session)
59033 UA_Session_detachSubscription(server, session: sub->session, sub, true);
59034
59035 /* Remove from the server if not previously registered */
59036 if(sub->serverListEntry.le_prev) {
59037 LIST_REMOVE(sub, serverListEntry);
59038 UA_assert(server->subscriptionsSize > 0);
59039 server->subscriptionsSize--;
59040 server->serverDiagnosticsSummary.currentSubscriptionCount--;
59041 }
59042
59043 /* Delete monitored Items */
59044 UA_assert(server->monitoredItemsSize >= sub->monitoredItemsSize);
59045 UA_MonitoredItem *mon, *tmp_mon;
59046 LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, tmp_mon) {
59047 UA_MonitoredItem_delete(server, monitoredItem: mon);
59048 }
59049 UA_assert(sub->monitoredItemsSize == 0);
59050
59051 /* Delete Retransmission Queue */
59052 UA_NotificationMessageEntry *nme, *nme_tmp;
59053 TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) {
59054 TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry);
59055 UA_NotificationMessage_clear(p: &nme->message);
59056 UA_free(ptr: nme);
59057 if(sub->session)
59058 --sub->session->totalRetransmissionQueueSize;
59059 --sub->retransmissionQueueSize;
59060 }
59061 UA_assert(sub->retransmissionQueueSize == 0);
59062
59063 /* Add a delayed callback to remove the Subscription when the current jobs
59064 * have completed. Pointers to the subscription may still exist upwards in
59065 * the call stack. */
59066 sub->delayedFreePointers.callback = NULL;
59067 sub->delayedFreePointers.application = server;
59068 sub->delayedFreePointers.data = NULL;
59069 sub->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
59070 sub->delayedFreePointers.interval = 0; /* Remove the structure */
59071 UA_Timer_addTimerEntry(t: &server->timer, te: &sub->delayedFreePointers, NULL);
59072}
59073
59074UA_MonitoredItem *
59075UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId) {
59076 UA_MonitoredItem *mon;
59077 LIST_FOREACH(mon, &sub->monitoredItems, listEntry) {
59078 if(mon->monitoredItemId == monitoredItemId)
59079 break;
59080 }
59081 return mon;
59082}
59083
59084static void
59085removeOldestRetransmissionMessageFromSub(UA_Subscription *sub) {
59086 UA_NotificationMessageEntry *oldestEntry =
59087 TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
59088 TAILQ_REMOVE(&sub->retransmissionQueue, oldestEntry, listEntry);
59089 UA_NotificationMessage_clear(p: &oldestEntry->message);
59090 UA_free(ptr: oldestEntry);
59091 --sub->retransmissionQueueSize;
59092 if(sub->session)
59093 --sub->session->totalRetransmissionQueueSize;
59094
59095#ifdef UA_ENABLE_DIAGNOSTICS
59096 sub->discardedMessageCount++;
59097#endif
59098}
59099
59100static void
59101removeOldestRetransmissionMessageFromSession(UA_Session *session) {
59102 UA_NotificationMessageEntry *oldestEntry = NULL;
59103 UA_Subscription *oldestSub = NULL;
59104 UA_Subscription *sub;
59105 TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) {
59106 UA_NotificationMessageEntry *first =
59107 TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue);
59108 if(!first)
59109 continue;
59110 if(!oldestEntry || oldestEntry->message.publishTime > first->message.publishTime) {
59111 oldestEntry = first;
59112 oldestSub = sub;
59113 }
59114 }
59115 UA_assert(oldestEntry);
59116 UA_assert(oldestSub);
59117
59118 removeOldestRetransmissionMessageFromSub(sub: oldestSub);
59119}
59120
59121static void
59122UA_Subscription_addRetransmissionMessage(UA_Server *server, UA_Subscription *sub,
59123 UA_NotificationMessageEntry *entry) {
59124 /* Release the oldest entry if there is not enough space */
59125 UA_Session *session = sub->session;
59126 if(sub->retransmissionQueueSize >= UA_MAX_RETRANSMISSIONQUEUESIZE) {
59127 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59128 "Subscription retransmission queue overflow");
59129 removeOldestRetransmissionMessageFromSub(sub);
59130 } else if(session && server->config.maxRetransmissionQueueSize > 0 &&
59131 session->totalRetransmissionQueueSize >=
59132 server->config.maxRetransmissionQueueSize) {
59133 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59134 "Session-wide retransmission queue overflow");
59135 removeOldestRetransmissionMessageFromSession(session: sub->session);
59136 }
59137
59138 /* Add entry */
59139 TAILQ_INSERT_TAIL(&sub->retransmissionQueue, entry, listEntry);
59140 ++sub->retransmissionQueueSize;
59141 if(session)
59142 ++session->totalRetransmissionQueueSize;
59143}
59144
59145UA_StatusCode
59146UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequenceNumber) {
59147 /* Find the retransmission message */
59148 UA_NotificationMessageEntry *entry;
59149 TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) {
59150 if(entry->message.sequenceNumber == sequenceNumber)
59151 break;
59152 }
59153 if(!entry)
59154 return UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN;
59155
59156 /* Remove the retransmission message */
59157 TAILQ_REMOVE(&sub->retransmissionQueue, entry, listEntry);
59158 --sub->retransmissionQueueSize;
59159 UA_NotificationMessage_clear(p: &entry->message);
59160 UA_free(ptr: entry);
59161
59162 if(sub->session)
59163 --sub->session->totalRetransmissionQueueSize;
59164
59165 return UA_STATUSCODE_GOOD;
59166}
59167
59168/* The output counters are only set when the preparation is successful */
59169static UA_StatusCode
59170prepareNotificationMessage(UA_Server *server, UA_Subscription *sub,
59171 UA_NotificationMessage *message,
59172 size_t maxNotifications) {
59173 UA_assert(maxNotifications > 0);
59174
59175 /* Allocate an ExtensionObject for Event- and DataChange-Notifications. Also
59176 * there can be StatusChange-Notifications. The standard says in Part 4,
59177 * 7.2.1:
59178 *
59179 * If a Subscription contains MonitoredItems for events and data, this array
59180 * should have not more than 2 elements. */
59181 message->notificationData = (UA_ExtensionObject*)
59182 UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]);
59183 if(!message->notificationData)
59184 return UA_STATUSCODE_BADOUTOFMEMORY;
59185 message->notificationDataSize = 2;
59186
59187 /* Pre-allocate DataChangeNotifications */
59188 size_t notificationDataIdx = 0;
59189 size_t dcnPos = 0; /* How many DataChangeNotifications? */
59190 UA_DataChangeNotification *dcn = NULL;
59191 if(sub->dataChangeNotifications > 0) {
59192 dcn = UA_DataChangeNotification_new();
59193 if(!dcn) {
59194 UA_NotificationMessage_clear(p: message);
59195 return UA_STATUSCODE_BADOUTOFMEMORY;
59196 }
59197 UA_ExtensionObject_setValue(eo: message->notificationData, p: dcn,
59198 type: &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]);
59199 size_t dcnSize = sub->dataChangeNotifications;
59200 if(dcnSize > maxNotifications)
59201 dcnSize = maxNotifications;
59202 dcn->monitoredItems = (UA_MonitoredItemNotification*)
59203 UA_Array_new(size: dcnSize, type: &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]);
59204 if(!dcn->monitoredItems) {
59205 UA_NotificationMessage_clear(p: message);
59206 return UA_STATUSCODE_BADOUTOFMEMORY;
59207 }
59208 dcn->monitoredItemsSize = dcnSize;
59209 notificationDataIdx++;
59210 }
59211
59212#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59213 size_t enlPos = 0; /* How many EventNotifications? */
59214 UA_EventNotificationList *enl = NULL;
59215 if(sub->eventNotifications > 0) {
59216 enl = UA_EventNotificationList_new();
59217 if(!enl) {
59218 UA_NotificationMessage_clear(p: message);
59219 return UA_STATUSCODE_BADOUTOFMEMORY;
59220 }
59221 UA_ExtensionObject_setValue(eo: &message->notificationData[notificationDataIdx],
59222 p: enl, type: &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]);
59223 size_t enlSize = sub->eventNotifications;
59224 if(enlSize > maxNotifications)
59225 enlSize = maxNotifications;
59226 enl->events = (UA_EventFieldList*)
59227 UA_Array_new(size: enlSize, type: &UA_TYPES[UA_TYPES_EVENTFIELDLIST]);
59228 if(!enl->events) {
59229 UA_NotificationMessage_clear(p: message);
59230 return UA_STATUSCODE_BADOUTOFMEMORY;
59231 }
59232 enl->eventsSize = enlSize;
59233 notificationDataIdx++;
59234 }
59235#endif
59236
59237 UA_assert(notificationDataIdx > 0);
59238 message->notificationDataSize = notificationDataIdx;
59239
59240 /* <-- The point of no return --> */
59241
59242 /* How many notifications were moved to the response overall? */
59243 size_t totalNotifications = 0;
59244 UA_Notification *notification, *notification_tmp;
59245 TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue,
59246 globalEntry, notification_tmp) {
59247 if(totalNotifications >= maxNotifications)
59248 break;
59249
59250 /* Move the content to the response */
59251 switch(notification->mon->itemToMonitor.attributeId) {
59252#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59253 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59254 UA_assert(enl != NULL); /* Have at least one event notification */
59255 enl->events[enlPos] = notification->data.event;
59256 UA_EventFieldList_init(p: &notification->data.event);
59257 enlPos++;
59258 break;
59259#endif
59260 default:
59261 UA_assert(dcn != NULL); /* Have at least one change notification */
59262 dcn->monitoredItems[dcnPos] = notification->data.dataChange;
59263 UA_DataValue_init(p: &notification->data.dataChange.value);
59264 dcnPos++;
59265 break;
59266 }
59267
59268 /* If there are Notifications *before this one* in the MonitoredItem-
59269 * local queue, remove all of them. These are earlier Notifications that
59270 * are non-reporting. And we don't want them to show up after the
59271 * current Notification has been sent out. */
59272 UA_Notification *prev;
59273 while((prev = TAILQ_PREV(notification, NotificationQueue, localEntry))) {
59274 UA_Notification_delete(n: prev);
59275 }
59276
59277 /* Delete the notification, remove from the queues and decrease the counters */
59278 UA_Notification_delete(n: notification);
59279
59280 totalNotifications++;
59281 }
59282
59283 /* Set sizes */
59284 if(dcn) {
59285 dcn->monitoredItemsSize = dcnPos;
59286 if(dcnPos == 0) {
59287 UA_free(ptr: dcn->monitoredItems);
59288 dcn->monitoredItems = NULL;
59289 }
59290 }
59291
59292#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59293 if(enl) {
59294 enl->eventsSize = enlPos;
59295 if(enlPos == 0) {
59296 UA_free(ptr: enl->events);
59297 enl->events = NULL;
59298 }
59299 }
59300#endif
59301
59302 return UA_STATUSCODE_GOOD;
59303}
59304
59305/* According to OPC Unified Architecture, Part 4 5.13.1.1 i) The value 0 is
59306 * never used for the sequence number */
59307static UA_UInt32
59308UA_Subscription_nextSequenceNumber(UA_UInt32 sequenceNumber) {
59309 UA_UInt32 nextSequenceNumber = sequenceNumber + 1;
59310 if(nextSequenceNumber == 0)
59311 nextSequenceNumber = 1;
59312 return nextSequenceNumber;
59313}
59314
59315static void
59316publishCallback(UA_Server *server, UA_Subscription *sub) {
59317 UA_LOCK(&server->serviceMutex);
59318 UA_Subscription_sampleAndPublish(server, sub);
59319 UA_UNLOCK(&server->serviceMutex);
59320}
59321
59322static void
59323sendStatusChangeDelete(UA_Server *server, UA_Subscription *sub,
59324 UA_PublishResponseEntry *pre) {
59325 /* Cannot send out the StatusChange because no response is queued.
59326 * Delete the Subscription without sending the StatusChange. */
59327 if(!pre) {
59328 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59329 "Cannot send the StatusChange notification. "
59330 "Removing the subscription.");
59331 UA_Subscription_delete(server, sub);
59332 return;
59333 }
59334
59335 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59336 "Sending out a StatusChange "
59337 "notification and removing the subscription");
59338
59339 /* Populate the response */
59340 UA_PublishResponse *response = &pre->response;
59341
59342 UA_StatusChangeNotification scn;
59343 UA_StatusChangeNotification_init(p: &scn);
59344 scn.status = sub->statusChange;
59345
59346 UA_ExtensionObject notificationData;
59347 UA_ExtensionObject_setValue(eo: &notificationData, p: &scn,
59348 type: &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]);
59349
59350 response->responseHeader.timestamp = UA_DateTime_now();
59351 response->notificationMessage.notificationData = &notificationData;
59352 response->notificationMessage.notificationDataSize = 1;
59353 response->subscriptionId = sub->subscriptionId;
59354 response->notificationMessage.publishTime = response->responseHeader.timestamp;
59355 response->notificationMessage.sequenceNumber = sub->nextSequenceNumber;
59356
59357 /* Send the response */
59358 UA_assert(sub->session); /* Otherwise pre is NULL */
59359 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59360 "Sending out a publish response");
59361 sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId,
59362 response: (UA_Response *)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59363
59364 /* Clean up */
59365 response->notificationMessage.notificationData = NULL;
59366 response->notificationMessage.notificationDataSize = 0;
59367 UA_PublishResponse_clear(p: &pre->response);
59368 UA_free(ptr: pre);
59369
59370 /* Delete the subscription */
59371 UA_Subscription_delete(server, sub);
59372}
59373
59374/* Called every time we set the subscription late (or it is still late) */
59375static void
59376UA_Subscription_isLate(UA_Subscription *sub) {
59377 sub->state = UA_SUBSCRIPTIONSTATE_LATE;
59378#ifdef UA_ENABLE_DIAGNOSTICS
59379 sub->latePublishRequestCount++;
59380#endif
59381}
59382
59383/* Returns true if done */
59384UA_Boolean
59385UA_Subscription_publishOnce(UA_Server *server, UA_Subscription *sub) {
59386 /* Dequeue a response */
59387 UA_PublishResponseEntry *pre = NULL;
59388 if(sub->session)
59389 pre = UA_Session_dequeuePublishReq(session: sub->session);
59390
59391 /* Update the LifetimeCounter */
59392 if(pre) {
59393 sub->currentLifetimeCount = 0;
59394 } else {
59395 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59396 "The publish queue is empty");
59397 ++sub->currentLifetimeCount;
59398 if(sub->currentLifetimeCount > sub->lifeTimeCount) {
59399 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59400 "End of subscription lifetime");
59401 /* Set the StatusChange to delete the subscription. */
59402 sub->statusChange = UA_STATUSCODE_BADTIMEOUT;
59403 }
59404 }
59405
59406 /* Send a StatusChange notification if possible and delete the
59407 * Subscription */
59408 if(sub->statusChange != UA_STATUSCODE_GOOD) {
59409 sendStatusChangeDelete(server, sub, pre);
59410 return true;
59411 }
59412
59413 /* Count the available notifications */
59414 UA_UInt32 notifications = (sub->publishingEnabled) ? sub->notificationQueueSize : 0;
59415 if(notifications > sub->notificationsPerPublish)
59416 notifications = sub->notificationsPerPublish;
59417
59418 /* Return if no notifications and no keepalive */
59419 if(notifications == 0) {
59420 ++sub->currentKeepAliveCount;
59421 if(sub->currentKeepAliveCount < sub->maxKeepAliveCount) {
59422 if(pre)
59423 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59424 return true;
59425 }
59426 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub, "Sending a KeepAlive");
59427 }
59428
59429 /* We want to send a response, but cannot. Either because there is no queued
59430 * response or because the Subscription is detached from a Session or because
59431 * the SecureChannel for the Session is closed. */
59432 if(!pre || !sub->session || !sub->session->header.channel) {
59433 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59434 "Want to send a publish response but cannot. "
59435 "The subscription is late.");
59436 UA_Subscription_isLate(sub);
59437 if(pre)
59438 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59439 return true;
59440 }
59441
59442 UA_assert(pre);
59443 UA_assert(sub->session); /* Otherwise pre is NULL */
59444
59445 /* Prepare the response */
59446 UA_PublishResponse *response = &pre->response;
59447 UA_NotificationMessage *message = &response->notificationMessage;
59448 UA_NotificationMessageEntry *retransmission = NULL;
59449#ifdef UA_ENABLE_DIAGNOSTICS
59450 size_t priorDataChangeNotifications = sub->dataChangeNotifications;
59451 size_t priorEventNotifications = sub->eventNotifications;
59452#endif
59453 if(notifications > 0) {
59454 if(server->config.enableRetransmissionQueue) {
59455 /* Allocate the retransmission entry */
59456 retransmission = (UA_NotificationMessageEntry*)
59457 UA_malloc(size: sizeof(UA_NotificationMessageEntry));
59458 if(!retransmission) {
59459 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59460 "Could not allocate memory for retransmission. "
59461 "The subscription is late.");
59462
59463 UA_Subscription_isLate(sub);
59464 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59465 return true;
59466 }
59467 }
59468
59469 /* Prepare the response */
59470 UA_StatusCode retval =
59471 prepareNotificationMessage(server, sub, message, maxNotifications: notifications);
59472 if(retval != UA_STATUSCODE_GOOD) {
59473 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
59474 "Could not prepare the notification message. "
59475 "The subscription is late.");
59476 /* If the retransmission queue is enabled a retransmission message is allocated */
59477 if(retransmission)
59478 UA_free(ptr: retransmission);
59479 UA_Subscription_isLate(sub);
59480 UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */
59481 return true;
59482 }
59483 }
59484
59485 /* <-- The point of no return --> */
59486
59487 /* Set up the response */
59488 response->responseHeader.timestamp = UA_DateTime_now();
59489 response->subscriptionId = sub->subscriptionId;
59490 response->moreNotifications = (sub->notificationQueueSize > 0);
59491 message->publishTime = response->responseHeader.timestamp;
59492
59493 /* Set sequence number to message. Started at 1 which is given during
59494 * creating a new subscription. The 1 is required for initial publish
59495 * response with or without an monitored item. */
59496 message->sequenceNumber = sub->nextSequenceNumber;
59497
59498 if(notifications > 0) {
59499 /* If the retransmission queue is enabled a retransmission message is
59500 * allocated */
59501 if(retransmission) {
59502 /* Put the notification message into the retransmission queue. This
59503 * needs to be done here, so that the message itself is included in
59504 * the available sequence numbers for acknowledgement. */
59505 retransmission->message = response->notificationMessage;
59506 UA_Subscription_addRetransmissionMessage(server, sub, entry: retransmission);
59507 }
59508 /* Only if a notification was created, the sequence number must be
59509 * increased. For a keepalive the sequence number can be reused. */
59510 sub->nextSequenceNumber =
59511 UA_Subscription_nextSequenceNumber(sequenceNumber: sub->nextSequenceNumber);
59512 }
59513
59514 /* Get the available sequence numbers from the retransmission queue */
59515 UA_assert(sub->retransmissionQueueSize <= UA_MAX_RETRANSMISSIONQUEUESIZE);
59516 UA_UInt32 seqNumbers[UA_MAX_RETRANSMISSIONQUEUESIZE];
59517 response->availableSequenceNumbers = seqNumbers;
59518 response->availableSequenceNumbersSize = sub->retransmissionQueueSize;
59519 size_t i = 0;
59520 UA_NotificationMessageEntry *nme;
59521 TAILQ_FOREACH(nme, &sub->retransmissionQueue, listEntry) {
59522 response->availableSequenceNumbers[i] = nme->message.sequenceNumber;
59523 ++i;
59524 }
59525 UA_assert(i == sub->retransmissionQueueSize);
59526
59527 /* Send the response */
59528 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59529 "Sending out a publish response with %" PRIu32
59530 " notifications", notifications);
59531 sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId,
59532 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59533
59534 /* Reset the Subscription state to NORMAL. But only if all notifications
59535 * have been sent out. Otherwise keep the Subscription in the LATE state. So
59536 * we immediately answer incoming Publish requests.
59537 *
59538 * (We also check that session->responseQueueSize > 0 in Service_Publish. To
59539 * avoid answering Publish requests out of order. As we additionally may
59540 * schedule an immediate next publishOnce if UA_Subscription_publishOnce
59541 * returns "not done".) */
59542 if(sub->notificationQueueSize == 0)
59543 sub->state = UA_SUBSCRIPTIONSTATE_NORMAL;
59544
59545 /* Reset the KeepAlive after publishing */
59546 sub->currentKeepAliveCount = 0;
59547
59548 /* Free the response */
59549 if(retransmission)
59550 /* NotificationMessage was moved into retransmission queue */
59551 UA_NotificationMessage_init(p: &response->notificationMessage);
59552 response->availableSequenceNumbers = NULL;
59553 response->availableSequenceNumbersSize = 0;
59554 UA_PublishResponse_clear(p: &pre->response);
59555 UA_free(ptr: pre);
59556
59557 /* Update the diagnostics statistics */
59558#ifdef UA_ENABLE_DIAGNOSTICS
59559 sub->publishRequestCount++;
59560
59561 UA_UInt32 sentDCN = (UA_UInt32)
59562 (priorDataChangeNotifications - sub->dataChangeNotifications);
59563 UA_UInt32 sentEN = (UA_UInt32)(priorEventNotifications - sub->eventNotifications);
59564 sub->dataChangeNotificationsCount += sentDCN;
59565 sub->eventNotificationsCount += sentEN;
59566 sub->notificationsCount += (sentDCN + sentEN);
59567#endif
59568
59569 /* Re-run publishing if notifications are remaining */
59570 return (sub->notificationQueueSize == 0);
59571}
59572
59573/* Repeat the main publishing callback until all notifications are sent out or
59574 * we have to stop */
59575void
59576UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) {
59577 UA_Boolean done = false;
59578 do {
59579 done = UA_Subscription_publishOnce(server, sub);
59580 } while(!done);
59581}
59582
59583void
59584UA_Subscription_sampleAndPublish(UA_Server *server, UA_Subscription *sub) {
59585 UA_LOCK_ASSERT(&server->serviceMutex, 1);
59586 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59587 "Sample and Publish Callback");
59588 UA_assert(sub);
59589
59590 /* Sample the MonitoredItems with sampling interval <0 (which implies
59591 * sampling in the same interval as the subscription) */
59592 UA_MonitoredItem *mon;
59593 LIST_FOREACH(mon, &sub->samplingMonitoredItems, sampling.samplingListEntry) {
59594 monitoredItem_sampleCallback(server, monitoredItem: mon);
59595 }
59596
59597 /* Publish the queued notifications */
59598 UA_Subscription_publish(server, sub);
59599}
59600
59601UA_Boolean
59602UA_Session_reachedPublishReqLimit(UA_Server *server, UA_Session *session) {
59603 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
59604 "Reached number of publish request limit");
59605
59606 /* Dequeue a response */
59607 UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(session);
59608
59609 /* Cannot publish without a response */
59610 if(!pre) {
59611 UA_LOG_FATAL_SESSION(&server->config.logger, session,
59612 "No publish requests available");
59613 return false;
59614 }
59615
59616 /* <-- The point of no return --> */
59617
59618 UA_PublishResponse *response = &pre->response;
59619 UA_NotificationMessage *message = &response->notificationMessage;
59620
59621 /* Set up the response. Note that this response has no related subscription id */
59622 response->responseHeader.timestamp = UA_DateTime_now();
59623 response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS;
59624 response->subscriptionId = 0;
59625 response->moreNotifications = false;
59626 message->publishTime = response->responseHeader.timestamp;
59627 message->sequenceNumber = 0;
59628 response->availableSequenceNumbersSize = 0;
59629
59630 /* Send the response */
59631 UA_LOG_DEBUG_SESSION(&server->config.logger, session,
59632 "Sending out a publish response triggered by too many publish requests");
59633 sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId,
59634 response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
59635
59636 /* Free the response */
59637 UA_Array_delete(p: response->results, size: response->resultsSize, type: &UA_TYPES[UA_TYPES_UINT32]);
59638 UA_free(ptr: pre); /* no need for UA_PublishResponse_clear */
59639
59640 return true;
59641}
59642
59643UA_StatusCode
59644Subscription_registerPublishCallback(UA_Server *server, UA_Subscription *sub) {
59645 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59646 "Register subscription publishing callback");
59647 UA_LOCK_ASSERT(&server->serviceMutex, 1);
59648
59649 if(sub->publishCallbackId > 0)
59650 return UA_STATUSCODE_GOOD;
59651
59652 UA_StatusCode retval =
59653 addRepeatedCallback(server, callback: (UA_ServerCallback)publishCallback,
59654 data: sub, interval_ms: sub->publishingInterval, callbackId: &sub->publishCallbackId);
59655 if(retval != UA_STATUSCODE_GOOD)
59656 return retval;
59657
59658 UA_assert(sub->publishCallbackId > 0);
59659 return UA_STATUSCODE_GOOD;
59660}
59661
59662void
59663Subscription_unregisterPublishCallback(UA_Server *server, UA_Subscription *sub) {
59664 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59665 "Unregister subscription publishing callback");
59666
59667 if(sub->publishCallbackId == 0)
59668 return;
59669
59670 removeCallback(server, callbackId: sub->publishCallbackId);
59671 sub->publishCallbackId = 0;
59672}
59673
59674#endif /* UA_ENABLE_SUBSCRIPTIONS */
59675
59676/**** amalgamated original file "/src/server/ua_subscription_monitoreditem.c" ****/
59677
59678/* This Source Code Form is subject to the terms of the Mozilla Public
59679 * License, v. 2.0. If a copy of the MPL was not distributed with this
59680 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
59681 *
59682 * Copyright 2017-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
59683 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
59684 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
59685 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
59686 * Copyright 2018 (c) Fabian Arndt, Root-Core
59687 * Copyright 2020-2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
59688 */
59689
59690
59691#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
59692
59693/****************/
59694/* Notification */
59695/****************/
59696
59697#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59698
59699static const UA_NodeId eventQueueOverflowEventType =
59700 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE}};
59701
59702/* The specification states in Part 4 5.12.1.5 that an EventQueueOverflowEvent
59703 * "is generated when the first Event has to be discarded [...] without
59704 * discarding any other event". So only generate one for all deleted events. */
59705static UA_StatusCode
59706createEventOverflowNotification(UA_Server *server, UA_Subscription *sub,
59707 UA_MonitoredItem *mon) {
59708 /* Avoid creating two adjacent overflow events */
59709 UA_Notification *indicator = NULL;
59710 if(mon->parameters.discardOldest) {
59711 indicator = TAILQ_FIRST(&mon->queue);
59712 UA_assert(indicator); /* must exist */
59713 if(indicator->isOverflowEvent)
59714 return UA_STATUSCODE_GOOD;
59715 } else {
59716 indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
59717 UA_assert(indicator); /* must exist */
59718 /* Skip the last element. It is the recently added notification that
59719 * shall be kept. We know it is not an OverflowEvent. */
59720 UA_Notification *before = TAILQ_PREV(indicator, NotificationQueue, localEntry);
59721 if(before && before->isOverflowEvent)
59722 return UA_STATUSCODE_GOOD;
59723 }
59724
59725 /* A Notification is inserted into the queue which includes only the
59726 * NodeId of the OverflowEventType. */
59727
59728 /* Allocate the notification */
59729 UA_Notification *overflowNotification = UA_Notification_new();
59730 if(!overflowNotification)
59731 return UA_STATUSCODE_BADOUTOFMEMORY;
59732
59733 /* Set the notification fields */
59734 overflowNotification->isOverflowEvent = true;
59735 overflowNotification->mon = mon;
59736 overflowNotification->data.event.clientHandle = mon->parameters.clientHandle;
59737 overflowNotification->data.event.eventFields = UA_Variant_new();
59738 if(!overflowNotification->data.event.eventFields) {
59739 UA_free(ptr: overflowNotification);
59740 return UA_STATUSCODE_BADOUTOFMEMORY;
59741 }
59742 overflowNotification->data.event.eventFieldsSize = 1;
59743 UA_StatusCode retval =
59744 UA_Variant_setScalarCopy(v: overflowNotification->data.event.eventFields,
59745 p: &eventQueueOverflowEventType, type: &UA_TYPES[UA_TYPES_NODEID]);
59746 if(retval != UA_STATUSCODE_GOOD) {
59747 UA_Notification_delete(n: overflowNotification);
59748 return retval;
59749 }
59750
59751 /* Insert before the removed notification. This is either first in the
59752 * queue (if the oldest notification was removed) or before the new event
59753 * that remains the last element of the queue.
59754 *
59755 * Ensure that the following is consistent with UA_Notification_enqueueMon
59756 * and UA_Notification_enqueueSub! */
59757 TAILQ_INSERT_BEFORE(indicator, overflowNotification, localEntry);
59758 ++mon->eventOverflows;
59759 ++mon->queueSize;
59760
59761 /* Test for consistency */
59762 UA_assert(mon->queueSize >= mon->eventOverflows);
59763 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
59764
59765 if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
59766 /* Insert just before the indicator */
59767 TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
59768 } else {
59769 /* The indicator was not reporting or not added yet. */
59770 if(!mon->parameters.discardOldest) {
59771 /* Add last to the per-Subscription queue */
59772 TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
59773 overflowNotification, globalEntry);
59774 } else {
59775 /* Find the oldest reported element. Add before that. */
59776 while(indicator) {
59777 indicator = TAILQ_PREV(indicator, NotificationQueue, localEntry);
59778 if(!indicator) {
59779 TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue,
59780 overflowNotification, globalEntry);
59781 break;
59782 }
59783 if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
59784 TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry);
59785 break;
59786 }
59787 }
59788 }
59789 }
59790
59791 ++sub->notificationQueueSize;
59792 ++sub->eventNotifications;
59793
59794 /* Update the diagnostics statistics */
59795#ifdef UA_ENABLE_DIAGNOSTICS
59796 sub->eventQueueOverFlowCount++;
59797#endif
59798
59799 return UA_STATUSCODE_GOOD;
59800}
59801
59802#endif
59803
59804/* Set the InfoBits that a datachange notification was removed */
59805static void
59806setOverflowInfoBits(UA_MonitoredItem *mon) {
59807 /* Only for queues with more than one element */
59808 if(mon->parameters.queueSize == 1)
59809 return;
59810
59811 UA_Notification *indicator = NULL;
59812 if(mon->parameters.discardOldest) {
59813 indicator = TAILQ_FIRST(&mon->queue);
59814 } else {
59815 indicator = TAILQ_LAST(&mon->queue, NotificationQueue);
59816 }
59817 UA_assert(indicator); /* must exist */
59818
59819 indicator->data.dataChange.value.hasStatus = true;
59820 indicator->data.dataChange.value.status |=
59821 (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
59822}
59823
59824/* Remove the InfoBits when the queueSize was reduced to 1 */
59825void
59826UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon) {
59827 /* Don't consider queue size > 1 and Event MonitoredItems */
59828 if(mon->parameters.queueSize > 1 ||
59829 mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
59830 return;
59831
59832 /* Get the first notification */
59833 UA_Notification *n = TAILQ_FIRST(&mon->queue);
59834 if(!n)
59835 return;
59836
59837 /* Assertion that at most one notification is in the queue */
59838 UA_assert(n == TAILQ_LAST(&mon->queue, NotificationQueue));
59839
59840 /* Remve the Infobits */
59841 n->data.dataChange.value.status &= ~(UA_StatusCode)
59842 (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW);
59843}
59844
59845UA_Notification *
59846UA_Notification_new(void) {
59847 UA_Notification *n = (UA_Notification*)UA_calloc(nmemb: 1, size: sizeof(UA_Notification));
59848 if(n) {
59849 /* Set the sentinel for a notification that is not enqueued */
59850 TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59851 TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
59852 }
59853 return n;
59854}
59855
59856static void UA_Notification_dequeueMon(UA_Notification *n);
59857static void UA_Notification_enqueueSub(UA_Notification *n);
59858static void UA_Notification_dequeueSub(UA_Notification *n);
59859
59860void
59861UA_Notification_delete(UA_Notification *n) {
59862 UA_assert(n != UA_SUBSCRIPTION_QUEUE_SENTINEL);
59863 if(n->mon) {
59864 UA_Notification_dequeueMon(n);
59865 UA_Notification_dequeueSub(n);
59866 switch(n->mon->itemToMonitor.attributeId) {
59867#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59868 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59869 UA_EventFieldList_clear(p: &n->data.event);
59870 UA_EventFilterResult_clear(p: &n->result);
59871 break;
59872#endif
59873 default:
59874 UA_MonitoredItemNotification_clear(p: &n->data.dataChange);
59875 break;
59876 }
59877 }
59878 UA_free(ptr: n);
59879}
59880
59881/* Add to the MonitoredItem queue, update all counters and then handle overflow */
59882static void
59883UA_Notification_enqueueMon(UA_Server *server, UA_Notification *n) {
59884 UA_MonitoredItem *mon = n->mon;
59885 UA_assert(mon);
59886 UA_assert(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL);
59887
59888 /* Add to the MonitoredItem */
59889 TAILQ_INSERT_TAIL(&mon->queue, n, localEntry);
59890 ++mon->queueSize;
59891
59892#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59893 if(n->isOverflowEvent)
59894 ++mon->eventOverflows;
59895#endif
59896
59897 /* Test for consistency */
59898 UA_assert(mon->queueSize >= mon->eventOverflows);
59899 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
59900
59901 /* Ensure enough space is available in the MonitoredItem. Do this only after
59902 * adding the new Notification. */
59903 UA_MonitoredItem_ensureQueueSpace(server, mon);
59904
59905 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
59906 "MonitoredItem %" PRIi32 " | "
59907 "Notification enqueued (Queue size %lu / %lu)",
59908 mon->monitoredItemId,
59909 (long unsigned)mon->queueSize,
59910 (long unsigned)mon->parameters.queueSize);
59911}
59912
59913void
59914UA_Notification_enqueueSub(UA_Notification *n) {
59915 UA_MonitoredItem *mon = n->mon;
59916 UA_assert(mon);
59917
59918 UA_Subscription *sub = mon->subscription;
59919 UA_assert(sub);
59920
59921 if(TAILQ_NEXT(n, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
59922 return;
59923
59924 /* Add to the subscription if reporting is enabled */
59925 TAILQ_INSERT_TAIL(&sub->notificationQueue, n, globalEntry);
59926 ++sub->notificationQueueSize;
59927
59928 switch(mon->itemToMonitor.attributeId) {
59929#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
59930 case UA_ATTRIBUTEID_EVENTNOTIFIER:
59931 ++sub->eventNotifications;
59932 break;
59933#endif
59934 default:
59935 ++sub->dataChangeNotifications;
59936 break;
59937 }
59938}
59939
59940void
59941UA_Notification_enqueueAndTrigger(UA_Server *server, UA_Notification *n) {
59942 UA_MonitoredItem *mon = n->mon;
59943 UA_Subscription *sub = mon->subscription;
59944 UA_assert(sub); /* This function is never called for local MonitoredItems */
59945
59946 /* If reporting or (sampled+triggered), enqueue into the Subscription first
59947 * and then into the MonitoredItem. UA_MonitoredItem_ensureQueueSpace
59948 * (called within UA_Notification_enqueueMon) assumes the notification is
59949 * already in the Subscription's publishing queue. */
59950 if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING ||
59951 (mon->monitoringMode == UA_MONITORINGMODE_SAMPLING &&
59952 mon->triggeredUntil > UA_DateTime_nowMonotonic())) {
59953 UA_Notification_enqueueSub(n);
59954 mon->triggeredUntil = UA_INT64_MIN;
59955 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, mon->subscription,
59956 "Notification enqueued (Queue size %lu)",
59957 (long unsigned)mon->subscription->notificationQueueSize);
59958 }
59959
59960 /* Insert into the MonitoredItem. This checks the queue size and
59961 * handles overflow. */
59962 UA_Notification_enqueueMon(server, n);
59963
59964 for(size_t i = mon->triggeringLinksSize - 1; i < mon->triggeringLinksSize; i--) {
59965 /* Get the triggered MonitoredItem. Remove the link if the MI doesn't exist. */
59966 UA_MonitoredItem *triggeredMon =
59967 UA_Subscription_getMonitoredItem(sub, monitoredItemId: mon->triggeringLinks[i]);
59968 if(!triggeredMon) {
59969 UA_MonitoredItem_removeLink(sub, mon, linkId: mon->triggeringLinks[i]);
59970 continue;
59971 }
59972
59973 /* Only sampling MonitoredItems receive a trigger. Reporting
59974 * MonitoredItems send out Notifications anyway and disabled
59975 * MonitoredItems don't create samples to send. */
59976 if(triggeredMon->monitoringMode != UA_MONITORINGMODE_SAMPLING)
59977 continue;
59978
59979 /* Get the latest sampled Notification from the triggered MonitoredItem.
59980 * Enqueue for publication. */
59981 UA_Notification *n2 = TAILQ_LAST(&triggeredMon->queue, NotificationQueue);
59982 if(n2)
59983 UA_Notification_enqueueSub(n: n2);
59984
59985 /* The next Notification within the publishing interval is going to be
59986 * published as well. (Falsely) assume that the publishing cycle has
59987 * started right now, so that we don't have to loop over MonitoredItems
59988 * to deactivate the triggering after the publishing cycle. */
59989 triggeredMon->triggeredUntil = UA_DateTime_nowMonotonic() +
59990 (UA_DateTime)(sub->publishingInterval * (UA_Double)UA_DATETIME_MSEC);
59991
59992 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
59993 "MonitoredItem %u triggers MonitoredItem %u",
59994 mon->monitoredItemId, triggeredMon->monitoredItemId);
59995 }
59996}
59997
59998/* Remove from the MonitoredItem queue and adjust all counters */
59999static void
60000UA_Notification_dequeueMon(UA_Notification *n) {
60001 UA_MonitoredItem *mon = n->mon;
60002 UA_assert(mon);
60003
60004 if(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
60005 return;
60006
60007 /* Remove from the MonitoredItem queue */
60008#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60009 if(n->isOverflowEvent)
60010 --mon->eventOverflows;
60011#endif
60012
60013 TAILQ_REMOVE(&mon->queue, n, localEntry);
60014 --mon->queueSize;
60015
60016 /* Test for consistency */
60017 UA_assert(mon->queueSize >= mon->eventOverflows);
60018 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
60019
60020 /* Reset the sentintel */
60021 TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
60022}
60023
60024void
60025UA_Notification_dequeueSub(UA_Notification *n) {
60026 if(TAILQ_NEXT(n, globalEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL)
60027 return;
60028
60029 UA_MonitoredItem *mon = n->mon;
60030 UA_assert(mon);
60031 UA_Subscription *sub = mon->subscription;
60032 UA_assert(sub);
60033
60034 switch(mon->itemToMonitor.attributeId) {
60035#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60036 case UA_ATTRIBUTEID_EVENTNOTIFIER:
60037 --sub->eventNotifications;
60038 break;
60039#endif
60040 default:
60041 --sub->dataChangeNotifications;
60042 break;
60043 }
60044
60045 TAILQ_REMOVE(&sub->notificationQueue, n, globalEntry);
60046 --sub->notificationQueueSize;
60047
60048 /* Reset the sentinel */
60049 TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL;
60050}
60051
60052/*****************/
60053/* MonitoredItem */
60054/*****************/
60055
60056void
60057UA_MonitoredItem_init(UA_MonitoredItem *mon) {
60058 memset(s: mon, c: 0, n: sizeof(UA_MonitoredItem));
60059 TAILQ_INIT(&mon->queue);
60060 mon->triggeredUntil = UA_INT64_MIN;
60061}
60062
60063static UA_StatusCode
60064addMonitoredItemBackpointer(UA_Server *server, UA_Session *session,
60065 UA_Node *node, void *data) {
60066 UA_MonitoredItem *mon = (UA_MonitoredItem*)data;
60067 UA_assert(mon != (UA_MonitoredItem*)~0);
60068 mon->sampling.nodeListNext = node->head.monitoredItems;
60069 node->head.monitoredItems = mon;
60070 return UA_STATUSCODE_GOOD;
60071}
60072
60073static UA_StatusCode
60074removeMonitoredItemBackPointer(UA_Server *server, UA_Session *session,
60075 UA_Node *node, void *data) {
60076 if(!node->head.monitoredItems)
60077 return UA_STATUSCODE_GOOD;
60078
60079 /* Edge case that it's the first element */
60080 UA_MonitoredItem *remove = (UA_MonitoredItem*)data;
60081 if(node->head.monitoredItems == remove) {
60082 node->head.monitoredItems = remove->sampling.nodeListNext;
60083 return UA_STATUSCODE_GOOD;
60084 }
60085
60086 UA_MonitoredItem *prev = node->head.monitoredItems;
60087 UA_MonitoredItem *entry = prev->sampling.nodeListNext;
60088 for(; entry != NULL; prev = entry, entry = entry->sampling.nodeListNext) {
60089 if(entry == remove) {
60090 prev->sampling.nodeListNext = entry->sampling.nodeListNext;
60091 break;
60092 }
60093 }
60094
60095 return UA_STATUSCODE_GOOD;
60096}
60097
60098void
60099UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
60100 if(mon->registered)
60101 return;
60102
60103 /* Register in Subscription and Server */
60104 UA_Subscription *sub = mon->subscription;
60105 if(sub) {
60106 mon->monitoredItemId = ++sub->lastMonitoredItemId;
60107 mon->subscription = sub;
60108 sub->monitoredItemsSize++;
60109 LIST_INSERT_HEAD(&sub->monitoredItems, mon, listEntry);
60110 } else {
60111 mon->monitoredItemId = ++server->lastLocalMonitoredItemId;
60112 LIST_INSERT_HEAD(&server->localMonitoredItems, mon, listEntry);
60113 }
60114 server->monitoredItemsSize++;
60115
60116 /* Register the MonitoredItem in userland */
60117 if(server->config.monitoredItemRegisterCallback) {
60118 UA_Session *session = &server->adminSession;
60119 if(sub)
60120 session = sub->session;
60121
60122 void *targetContext = NULL;
60123 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext);
60124 UA_UNLOCK(&server->serviceMutex);
60125 server->config.monitoredItemRegisterCallback(server,
60126 session ? &session->sessionId : NULL,
60127 session ? session->sessionHandle : NULL,
60128 &mon->itemToMonitor.nodeId,
60129 targetContext,
60130 mon->itemToMonitor.attributeId, false);
60131 UA_LOCK(&server->serviceMutex);
60132 }
60133
60134 mon->registered = true;
60135}
60136
60137static void
60138UA_Server_unregisterMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) {
60139 if(!mon->registered)
60140 return;
60141
60142 UA_Subscription *sub = mon->subscription;
60143 UA_LOG_INFO_SUBSCRIPTION(&server->config.logger, sub,
60144 "MonitoredItem %" PRIi32 " | Deleting the MonitoredItem",
60145 mon->monitoredItemId);
60146
60147 /* Deregister MonitoredItem in userland */
60148 if(server->config.monitoredItemRegisterCallback) {
60149 UA_Session *session = &server->adminSession;
60150 if(sub)
60151 session = sub->session;
60152
60153 void *targetContext = NULL;
60154 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext);
60155 UA_UNLOCK(&server->serviceMutex);
60156 server->config.monitoredItemRegisterCallback(server,
60157 session ? &session->sessionId : NULL,
60158 session ? session->sessionHandle : NULL,
60159 &mon->itemToMonitor.nodeId,
60160 targetContext,
60161 mon->itemToMonitor.attributeId, true);
60162 UA_LOCK(&server->serviceMutex);
60163 }
60164
60165 /* Deregister in Subscription and server */
60166 if(sub)
60167 sub->monitoredItemsSize--;
60168 LIST_REMOVE(mon, listEntry); /* Also for LocalMonitoredItems */
60169 server->monitoredItemsSize--;
60170
60171 mon->registered = false;
60172}
60173
60174UA_StatusCode
60175UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon,
60176 UA_MonitoringMode monitoringMode) {
60177 /* Check if the MonitoringMode is valid or not */
60178 if(monitoringMode > UA_MONITORINGMODE_REPORTING)
60179 return UA_STATUSCODE_BADMONITORINGMODEINVALID;
60180
60181 /* Set the MonitoringMode, store the old mode */
60182 UA_MonitoringMode oldMode = mon->monitoringMode;
60183 mon->monitoringMode = monitoringMode;
60184
60185 UA_Notification *notification;
60186 /* Reporting is disabled. This causes all Notifications to be dequeued and
60187 * deleted. Also remove the last samples so that we immediately generate a
60188 * Notification when re-activated. */
60189 if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED) {
60190 UA_Notification *notification_tmp;
60191 UA_MonitoredItem_unregisterSampling(server, mon);
60192 TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
60193 UA_Notification_delete(n: notification);
60194 }
60195 UA_DataValue_clear(p: &mon->lastValue);
60196 return UA_STATUSCODE_GOOD;
60197 }
60198
60199 /* When reporting is enabled, put all notifications that were already
60200 * sampled into the global queue of the subscription. When sampling is
60201 * enabled, remove all notifications from the global queue. !!! This needs
60202 * to be the same operation as in UA_Notification_enqueue !!! */
60203 if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) {
60204 /* Make all notifications reporting. Re-enqueue to ensure they have the
60205 * right order if some notifications are already reported by a trigger
60206 * link. */
60207 TAILQ_FOREACH(notification, &mon->queue, localEntry) {
60208 UA_Notification_dequeueSub(n: notification);
60209 UA_Notification_enqueueSub(n: notification);
60210 }
60211 } else /* mon->monitoringMode == UA_MONITORINGMODE_SAMPLING */ {
60212 /* Make all notifications non-reporting */
60213 TAILQ_FOREACH(notification, &mon->queue, localEntry)
60214 UA_Notification_dequeueSub(n: notification);
60215 }
60216
60217 /* Register the sampling callback with an interval. If registering the
60218 * sampling callback failed, set to disabled. But don't delete the current
60219 * notifications. */
60220 UA_StatusCode res = UA_MonitoredItem_registerSampling(server, mon);
60221 if(res != UA_STATUSCODE_GOOD) {
60222 mon->monitoringMode = UA_MONITORINGMODE_DISABLED;
60223 return res;
60224 }
60225
60226 /* Manually create the first sample if the MonitoredItem was disabled, the
60227 * MonitoredItem is now sampling (or reporting) and it is not an
60228 * Event-MonitoredItem */
60229 if(oldMode == UA_MONITORINGMODE_DISABLED &&
60230 mon->monitoringMode > UA_MONITORINGMODE_DISABLED &&
60231 mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
60232 monitoredItem_sampleCallback(server, monitoredItem: mon);
60233
60234 return UA_STATUSCODE_GOOD;
60235}
60236
60237void
60238UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *mon) {
60239 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60240
60241 /* Remove the sampling callback */
60242 UA_MonitoredItem_unregisterSampling(server, mon);
60243
60244 /* Deregister in Server and Subscription */
60245 if(mon->registered)
60246 UA_Server_unregisterMonitoredItem(server, mon);
60247
60248 /* Remove the TriggeringLinks */
60249 if(mon->triggeringLinksSize > 0) {
60250 UA_free(ptr: mon->triggeringLinks);
60251 mon->triggeringLinks = NULL;
60252 mon->triggeringLinksSize = 0;
60253 }
60254
60255 /* Remove the queued notifications attached to the subscription */
60256 UA_Notification *notification, *notification_tmp;
60257 TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) {
60258 UA_Notification_delete(n: notification);
60259 }
60260
60261 /* Remove the settings */
60262 UA_ReadValueId_clear(p: &mon->itemToMonitor);
60263 UA_MonitoringParameters_clear(p: &mon->parameters);
60264
60265 /* Remove the last samples */
60266 UA_DataValue_clear(p: &mon->lastValue);
60267
60268 /* Add a delayed callback to remove the MonitoredItem when the current jobs
60269 * have completed. This is needed to allow that a local MonitoredItem can
60270 * remove itself in the callback. */
60271 mon->delayedFreePointers.callback = NULL;
60272 mon->delayedFreePointers.application = server;
60273 mon->delayedFreePointers.data = NULL;
60274 mon->delayedFreePointers.nextTime = UA_DateTime_nowMonotonic() + 1;
60275 mon->delayedFreePointers.interval = 0;
60276 UA_Timer_addTimerEntry(t: &server->timer, te: &mon->delayedFreePointers, NULL);
60277}
60278
60279void
60280UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) {
60281 /* There can be only one EventOverflow more than normal entries. Because
60282 * EventOverflows are never adjacent. */
60283 UA_assert(mon->queueSize >= mon->eventOverflows);
60284 UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1);
60285
60286 /* Always attached to a Subscription (no local MonitoredItem) */
60287 UA_Subscription *sub = mon->subscription;
60288 UA_assert(sub);
60289
60290 /* Nothing to do */
60291 if(mon->queueSize - mon->eventOverflows <= mon->parameters.queueSize)
60292 return;
60293
60294 /* Remove notifications until the required queue size is reached */
60295 UA_Boolean reporting = false;
60296 size_t remove = mon->queueSize - mon->eventOverflows - mon->parameters.queueSize;
60297 while(remove > 0) {
60298 /* The minimum queue size (without EventOverflows) is 1. At least two
60299 * notifications that are not EventOverflows are in the queue. */
60300 UA_assert(mon->queueSize - mon->eventOverflows >= 2);
60301
60302 /* Select the next notification to delete. Skip over overflow events. */
60303 UA_Notification *del = NULL;
60304 if(mon->parameters.discardOldest) {
60305 /* Remove the oldest */
60306 del = TAILQ_FIRST(&mon->queue);
60307#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
60308 while(del->isOverflowEvent)
60309 del = TAILQ_NEXT(del, localEntry); /* skip overflow events */
60310#endif
60311 } else {
60312 /* Remove the second newest (to keep the up-to-date notification).
60313 * The last entry is not an OverflowEvent -- we just added it. */
60314 del = TAILQ_LAST(&mon->queue, NotificationQueue);
60315 del = TAILQ_PREV(del, NotificationQueue, localEntry);
60316#if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__)
60317 while(del->isOverflowEvent)
60318 del = TAILQ_PREV(del, NotificationQueue, localEntry); /* skip overflow events */
60319#endif
60320 }
60321
60322 UA_assert(del); /* There must have been one entry that can be deleted */
60323
60324 /* Only create OverflowEvents (and set InfoBits) if the notification
60325 * that is removed is reported */
60326 if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL)
60327 reporting = true;
60328
60329 /* Move the entry after del in the per-MonitoredItem queue right after
60330 * del in the per-Subscription queue. So we don't starve MonitoredItems
60331 * with a high sampling interval in the Subscription queue by always
60332 * removing their first appearance in the per-Subscription queue.
60333 *
60334 * With MonitoringMode == SAMPLING, the Notifications are not (all) in
60335 * the per-Subscription queue. Don't reinsert in that case.
60336 *
60337 * For the reinsertion to work, first insert into the per-Subscription
60338 * queue. */
60339 if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
60340 UA_Notification *after_del = TAILQ_NEXT(del, localEntry);
60341 UA_assert(after_del); /* There must be one remaining element after del */
60342 if(TAILQ_NEXT(after_del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) {
60343 TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry);
60344 TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry);
60345 }
60346 }
60347
60348 remove--;
60349
60350 /* Delete the notification and remove it from the queues */
60351 UA_Notification_delete(n: del);
60352
60353 /* Update the subscription diagnostics statistics */
60354#ifdef UA_ENABLE_DIAGNOSTICS
60355 sub->monitoringQueueOverflowCount++;
60356#endif
60357
60358 /* Assertions to help Clang's scan-analyzer */
60359 UA_assert(del != TAILQ_FIRST(&mon->queue));
60360 UA_assert(del != TAILQ_LAST(&mon->queue, NotificationQueue));
60361 UA_assert(del != TAILQ_PREV(TAILQ_LAST(&mon->queue, NotificationQueue),
60362 NotificationQueue, localEntry));
60363 }
60364
60365 /* Leave an entry to indicate that notifications were removed */
60366 if(reporting) {
60367#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60368 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER)
60369 createEventOverflowNotification(server, sub, mon);
60370 else
60371#endif
60372 setOverflowInfoBits(mon);
60373 }
60374}
60375
60376UA_StatusCode
60377UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon) {
60378 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60379
60380 /* Sampling is already registered */
60381 if(mon->samplingType != UA_MONITOREDITEMSAMPLINGTYPE_NONE)
60382 return UA_STATUSCODE_GOOD;
60383
60384 UA_StatusCode res = UA_STATUSCODE_GOOD;
60385 UA_Subscription *sub = mon->subscription;
60386 if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER ||
60387 mon->parameters.samplingInterval == 0.0) {
60388 /* Add to the linked list in the node */
60389 UA_Session *session = &server->adminSession;
60390 if(sub)
60391 session = sub->session;
60392 res = UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId,
60393 callback: addMonitoredItemBackpointer, data: mon);
60394 if(res == UA_STATUSCODE_GOOD)
60395 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_EVENT;
60396 return res;
60397 } else if(mon->parameters.samplingInterval < 0.0) {
60398 /* Add to the subscription for sampling before every publish */
60399 if(!sub)
60400 return UA_STATUSCODE_BADINTERNALERROR; /* Not possible for local MonitoredItems */
60401 LIST_INSERT_HEAD(&sub->samplingMonitoredItems, mon, sampling.samplingListEntry);
60402 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH;
60403 } else {
60404 /* DataChange MonitoredItems with a positive sampling interval have a
60405 * repeated callback. Other MonitoredItems are attached to the Node in a
60406 * linked list of backpointers. */
60407 res = addRepeatedCallback(server,
60408 callback: (UA_ServerCallback)UA_MonitoredItem_sampleCallback,
60409 data: mon, interval_ms: mon->parameters.samplingInterval,
60410 callbackId: &mon->sampling.callbackId);
60411 if(res == UA_STATUSCODE_GOOD)
60412 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC;
60413 }
60414
60415 return res;
60416}
60417
60418void
60419UA_MonitoredItem_unregisterSampling(UA_Server *server, UA_MonitoredItem *mon) {
60420 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60421
60422 switch(mon->samplingType) {
60423 case UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC:
60424 /* Remove repeated callback */
60425 removeCallback(server, callbackId: mon->sampling.callbackId);
60426 break;
60427
60428 case UA_MONITOREDITEMSAMPLINGTYPE_EVENT: {
60429 /* Added to a node */
60430 UA_Subscription *sub = mon->subscription;
60431 UA_Session *session = &server->adminSession;
60432 if(sub)
60433 session = sub->session;
60434 UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId,
60435 callback: removeMonitoredItemBackPointer, data: mon);
60436 break;
60437 }
60438
60439 case UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH:
60440 /* Added to the subscription */
60441 LIST_REMOVE(mon, sampling.samplingListEntry);
60442 break;
60443
60444 case UA_MONITOREDITEMSAMPLINGTYPE_NONE:
60445 default:
60446 /* Sampling is not registered */
60447 break;
60448 }
60449
60450 mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_NONE;
60451}
60452
60453UA_StatusCode
60454UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
60455 /* Find the index */
60456 size_t i = 0;
60457 for(; i < mon->triggeringLinksSize; i++) {
60458 if(mon->triggeringLinks[i] == linkId)
60459 break;
60460 }
60461
60462 /* Not existing / already removed */
60463 if(i == mon->triggeringLinksSize)
60464 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60465
60466 /* Remove the link */
60467 mon->triggeringLinksSize--;
60468 if(mon->triggeringLinksSize == 0) {
60469 UA_free(ptr: mon->triggeringLinks);
60470 mon->triggeringLinks = NULL;
60471 } else {
60472 mon->triggeringLinks[i] = mon->triggeringLinks[mon->triggeringLinksSize];
60473 UA_UInt32 *tmpLinks = (UA_UInt32*)
60474 UA_realloc(ptr: mon->triggeringLinks, size: mon->triggeringLinksSize * sizeof(UA_UInt32));
60475 if(tmpLinks)
60476 mon->triggeringLinks = tmpLinks;
60477 }
60478
60479 /* Does the target MonitoredItem exist? This is stupid, but the CTT wants us
60480 * to to this. We don't auto-remove links together with the target
60481 * MonitoredItem. Links to removed MonitoredItems are removed when the link
60482 * triggers and the target no longer exists. */
60483 UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId);
60484 if(!mon2)
60485 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60486
60487 return UA_STATUSCODE_GOOD;
60488}
60489
60490UA_StatusCode
60491UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) {
60492 /* Does the target MonitoredItem exist? */
60493 UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId);
60494 if(!mon2)
60495 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
60496
60497 /* Does the link already exist? */
60498 for(size_t i = 0 ; i < mon->triggeringLinksSize; i++) {
60499 if(mon->triggeringLinks[i] == linkId)
60500 return UA_STATUSCODE_GOOD;
60501 }
60502
60503 /* Allocate the memory */
60504 UA_UInt32 *tmpLinkIds = (UA_UInt32*)
60505 UA_realloc(ptr: mon->triggeringLinks, size: (mon->triggeringLinksSize + 1) * sizeof(UA_UInt32));
60506 if(!tmpLinkIds)
60507 return UA_STATUSCODE_BADOUTOFMEMORY;
60508 mon->triggeringLinks = tmpLinkIds;
60509
60510 /* Add the link */
60511 mon->triggeringLinks[mon->triggeringLinksSize] = linkId;
60512 mon->triggeringLinksSize++;
60513 return UA_STATUSCODE_GOOD;
60514}
60515
60516#endif /* UA_ENABLE_SUBSCRIPTIONS */
60517
60518/**** amalgamated original file "/src/server/ua_subscription_datachange.c" ****/
60519
60520/* This Source Code Form is subject to the terms of the Mozilla Public
60521 * License, v. 2.0. If a copy of the MPL was not distributed with this
60522 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
60523 *
60524 * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
60525 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
60526 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
60527 * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA
60528 * Copyright 2018 (c) Fabian Arndt, Root-Core
60529 */
60530
60531
60532#ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */
60533
60534/* Detect value changes outside the deadband */
60535#define UA_DETECT_DEADBAND(TYPE) do { \
60536 TYPE v1 = *(const TYPE*)data1; \
60537 TYPE v2 = *(const TYPE*)data2; \
60538 TYPE diff = (v1 > v2) ? (TYPE)(v1 - v2) : (TYPE)(v2 - v1); \
60539 return ((UA_Double)diff > deadband); \
60540} while(false);
60541
60542static UA_Boolean
60543detectScalarDeadBand(const void *data1, const void *data2,
60544 const UA_DataType *type, const UA_Double deadband) {
60545 if(type->typeKind == UA_DATATYPEKIND_SBYTE) {
60546 UA_DETECT_DEADBAND(UA_SByte);
60547 } else if(type->typeKind == UA_DATATYPEKIND_BYTE) {
60548 UA_DETECT_DEADBAND(UA_Byte);
60549 } else if(type->typeKind == UA_DATATYPEKIND_INT16) {
60550 UA_DETECT_DEADBAND(UA_Int16);
60551 } else if(type->typeKind == UA_DATATYPEKIND_UINT16) {
60552 UA_DETECT_DEADBAND(UA_UInt16);
60553 } else if(type->typeKind == UA_DATATYPEKIND_INT32) {
60554 UA_DETECT_DEADBAND(UA_Int32);
60555 } else if(type->typeKind == UA_DATATYPEKIND_UINT32) {
60556 UA_DETECT_DEADBAND(UA_UInt32);
60557 } else if(type->typeKind == UA_DATATYPEKIND_INT64) {
60558 UA_DETECT_DEADBAND(UA_Int64);
60559 } else if(type->typeKind == UA_DATATYPEKIND_UINT64) {
60560 UA_DETECT_DEADBAND(UA_UInt64);
60561 } else if(type->typeKind == UA_DATATYPEKIND_FLOAT) {
60562 UA_DETECT_DEADBAND(UA_Float);
60563 } else if(type->typeKind == UA_DATATYPEKIND_DOUBLE) {
60564 UA_DETECT_DEADBAND(UA_Double);
60565 } else {
60566 return false; /* Not a known numerical type */
60567 }
60568}
60569
60570static UA_Boolean
60571detectVariantDeadband(const UA_Variant *value, const UA_Variant *oldValue,
60572 const UA_Double deadbandValue) {
60573 if(value->arrayLength != oldValue->arrayLength)
60574 return true;
60575 if(value->type != oldValue->type)
60576 return true;
60577 size_t length = 1;
60578 if(!UA_Variant_isScalar(v: value))
60579 length = value->arrayLength;
60580 uintptr_t data = (uintptr_t)value->data;
60581 uintptr_t oldData = (uintptr_t)oldValue->data;
60582 UA_UInt32 memSize = value->type->memSize;
60583 for(size_t i = 0; i < length; ++i) {
60584 if(detectScalarDeadBand(data1: (const void*)data, data2: (const void*)oldData,
60585 type: value->type, deadband: deadbandValue))
60586 return true;
60587 data += memSize;
60588 oldData += memSize;
60589 }
60590 return false;
60591}
60592
60593static UA_Boolean
60594detectValueChange(UA_Server *server, UA_MonitoredItem *mon,
60595 const UA_DataValue *value) {
60596 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60597
60598 /* Status changes are always reported */
60599 if(value->hasStatus != mon->lastValue.hasStatus ||
60600 value->status != mon->lastValue.status) {
60601 return true;
60602 }
60603
60604 /* Default trigger is Status + Value */
60605 UA_DataChangeTrigger trigger = UA_DATACHANGETRIGGER_STATUSVALUE;
60606
60607 /* Use the configured trigger */
60608 const UA_DataChangeFilter *dcf = NULL;
60609 const UA_ExtensionObject *filter = &mon->parameters.filter;
60610 if(filter->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) {
60611 dcf = (UA_DataChangeFilter*)filter->content.decoded.data;
60612 trigger = dcf->trigger;
60613 }
60614
60615 /* The status was already tested above */
60616 if(trigger == UA_DATACHANGETRIGGER_STATUS)
60617 return false;
60618
60619 UA_assert(trigger == UA_DATACHANGETRIGGER_STATUSVALUE ||
60620 trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP);
60621
60622 /* Test absolute deadband */
60623 if(dcf && dcf->deadbandType == UA_DEADBANDTYPE_ABSOLUTE &&
60624 value->value.type != NULL && UA_DataType_isNumeric(type: value->value.type))
60625 return detectVariantDeadband(value: &value->value, oldValue: &mon->lastValue.value,
60626 deadbandValue: dcf->deadbandValue);
60627
60628 /* Compare the source timestamp if the trigger requires that */
60629 if(trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) {
60630 if(value->hasSourceTimestamp != mon->lastValue.hasSourceTimestamp)
60631 return true;
60632 if(value->hasSourceTimestamp &&
60633 value->sourceTimestamp != mon->lastValue.sourceTimestamp)
60634 return true;
60635 }
60636
60637 /* Has the value changed? */
60638 if(value->hasValue != mon->lastValue.hasValue)
60639 return true;
60640 return (UA_order(p1: &value->value, p2: &mon->lastValue.value,
60641 type: &UA_TYPES[UA_TYPES_VARIANT]) != UA_ORDER_EQ);
60642}
60643
60644UA_StatusCode
60645UA_MonitoredItem_createDataChangeNotification(UA_Server *server, UA_Subscription *sub,
60646 UA_MonitoredItem *mon,
60647 const UA_DataValue *value) {
60648 /* Allocate a new notification */
60649 UA_Notification *newNotification = UA_Notification_new();
60650 if(!newNotification)
60651 return UA_STATUSCODE_BADOUTOFMEMORY;
60652
60653 /* Prepare the notification */
60654 newNotification->mon = mon;
60655 newNotification->data.dataChange.clientHandle = mon->parameters.clientHandle;
60656 UA_StatusCode retval = UA_DataValue_copy(src: value, dst: &newNotification->data.dataChange.value);
60657 if(retval != UA_STATUSCODE_GOOD) {
60658 UA_free(ptr: newNotification);
60659 return retval;
60660 }
60661
60662 /* Enqueue the notification */
60663 UA_assert(sub);
60664 UA_Notification_enqueueAndTrigger(server, n: newNotification);
60665 return UA_STATUSCODE_GOOD;
60666}
60667
60668/* Moves the value to the MonitoredItem if successful */
60669UA_StatusCode
60670sampleCallbackWithValue(UA_Server *server, UA_Subscription *sub,
60671 UA_MonitoredItem *mon, UA_DataValue *value) {
60672 UA_assert(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
60673
60674 /* Has the value changed (with the filters applied)? */
60675 UA_Boolean changed = detectValueChange(server, mon, value);
60676 if(!changed) {
60677 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
60678 "MonitoredItem %" PRIi32 " | "
60679 "The value has not changed", mon->monitoredItemId);
60680 UA_DataValue_clear(p: value);
60681 return UA_STATUSCODE_GOOD;
60682 }
60683
60684 /* The MonitoredItem is attached to a subscription (not server-local).
60685 * Prepare a notification and enqueue it. */
60686 if(sub) {
60687 UA_StatusCode retval =
60688 UA_MonitoredItem_createDataChangeNotification(server, sub, mon, value);
60689 if(retval != UA_STATUSCODE_GOOD)
60690 return retval;
60691 }
60692
60693 /* <-- Point of no return --> */
60694
60695 /* Move/store the value for filter comparison and TransferSubscription */
60696 UA_DataValue_clear(p: &mon->lastValue);
60697 mon->lastValue = *value;
60698
60699 /* Call the local callback if the MonitoredItem is not attached to a
60700 * subscription. Do this at the very end. Because the callback might delete
60701 * the subscription. */
60702 if(!sub) {
60703 UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) mon;
60704 void *nodeContext = NULL;
60705 getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &nodeContext);
60706 UA_UNLOCK(&server->serviceMutex);
60707 localMon->callback.dataChangeCallback(server,
60708 mon->monitoredItemId, localMon->context,
60709 &mon->itemToMonitor.nodeId, nodeContext,
60710 mon->itemToMonitor.attributeId, value);
60711 UA_LOCK(&server->serviceMutex);
60712 }
60713
60714 return UA_STATUSCODE_GOOD;
60715}
60716
60717void
60718UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
60719 UA_LOCK(&server->serviceMutex);
60720 monitoredItem_sampleCallback(server, monitoredItem);
60721 UA_UNLOCK(&server->serviceMutex);
60722}
60723
60724void
60725monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *monitoredItem) {
60726 UA_LOCK_ASSERT(&server->serviceMutex, 1);
60727
60728 UA_Subscription *sub = monitoredItem->subscription;
60729 UA_Session *session = &server->adminSession;
60730 if(sub)
60731 session = sub->session;
60732
60733 UA_LOG_DEBUG_SUBSCRIPTION(&server->config.logger, sub,
60734 "MonitoredItem %" PRIi32 " | "
60735 "Sample callback called", monitoredItem->monitoredItemId);
60736
60737 UA_assert(monitoredItem->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER);
60738
60739 /* Sample the value. The sample can still point into the node. */
60740 UA_DataValue value = UA_Server_readWithSession(server, session,
60741 item: &monitoredItem->itemToMonitor,
60742 timestampsToReturn: monitoredItem->timestampsToReturn);
60743
60744 /* Operate on the sample. The sample is consumed when the status is good. */
60745 UA_StatusCode res = sampleCallbackWithValue(server, sub, mon: monitoredItem, value: &value);
60746 if(res != UA_STATUSCODE_GOOD) {
60747 UA_DataValue_clear(p: &value);
60748 UA_LOG_WARNING_SUBSCRIPTION(&server->config.logger, sub,
60749 "MonitoredItem %" PRIi32 " | "
60750 "Sampling returned the statuscode %s",
60751 monitoredItem->monitoredItemId,
60752 UA_StatusCode_name(res));
60753 }
60754}
60755
60756#endif /* UA_ENABLE_SUBSCRIPTIONS */
60757
60758/**** amalgamated original file "/src/server/ua_subscription_events.c" ****/
60759
60760/* This Source Code Form is subject to the terms of the Mozilla Public
60761 * License, v. 2.0. If a copy of the MPL was not distributed with this
60762 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
60763 *
60764 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
60765 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
60766 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
60767 */
60768
60769
60770#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
60771
60772/* We use a 16-Byte ByteString as an identifier */
60773UA_StatusCode
60774UA_Event_generateEventId(UA_ByteString *generatedId) {
60775 /* EventId is a ByteString, which is basically just a string
60776 * We will use a 16-Byte ByteString as an identifier */
60777 UA_StatusCode res = UA_ByteString_allocBuffer(bs: generatedId, length: 16 * sizeof(UA_Byte));
60778 if(res != UA_STATUSCODE_GOOD)
60779 return res;
60780 UA_UInt32 *ids = (UA_UInt32*)generatedId->data;
60781 ids[0] = UA_UInt32_random();
60782 ids[1] = UA_UInt32_random();
60783 ids[2] = UA_UInt32_random();
60784 ids[3] = UA_UInt32_random();
60785 return UA_STATUSCODE_GOOD;
60786}
60787
60788UA_StatusCode
60789UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType,
60790 UA_NodeId *outNodeId) {
60791 UA_LOCK(&server->serviceMutex);
60792 if(!outNodeId) {
60793 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60794 msg: "outNodeId must not be NULL. The event's NodeId must be returned "
60795 "so it can be triggered.");
60796 UA_UNLOCK(&server->serviceMutex);
60797 return UA_STATUSCODE_BADINVALIDARGUMENT;
60798 }
60799
60800 /* Make sure the eventType is a subtype of BaseEventType */
60801 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
60802 if(!isNodeInTree_singleRef(server, leafNode: &eventType, nodeToFind: &baseEventTypeId,
60803 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
60804 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60805 msg: "Event type must be a subtype of BaseEventType!");
60806 UA_UNLOCK(&server->serviceMutex);
60807 return UA_STATUSCODE_BADINVALIDARGUMENT;
60808 }
60809
60810 /* Create an ObjectNode which represents the event */
60811 UA_QualifiedName name;
60812 /* set a dummy name. This is not used. */
60813 name = UA_QUALIFIEDNAME(nsIndex: 0,chars: "E");
60814 UA_NodeId newNodeId = UA_NODEID_NULL;
60815 UA_ObjectAttributes oAttr = UA_ObjectAttributes_default;
60816 UA_StatusCode retval = addNode(server, nodeClass: UA_NODECLASS_OBJECT,
60817 requestedNewNodeId: &UA_NODEID_NULL, /* Set a random unused NodeId */
60818 parentNodeId: &UA_NODEID_NULL, /* No parent */
60819 referenceTypeId: &UA_NODEID_NULL, /* No parent reference */
60820 browseName: name, /* an event does not have a name */
60821 typeDefinition: &eventType, /* the type of the event */
60822 attr: (const UA_NodeAttributes*)&oAttr, /* default attributes are fine */
60823 attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],
60824 NULL, /* no node context */
60825 outNewNodeId: &newNodeId);
60826 if(retval != UA_STATUSCODE_GOOD) {
60827 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
60828 msg: "Adding event failed. StatusCode %s", UA_StatusCode_name(code: retval));
60829 UA_UNLOCK(&server->serviceMutex);
60830 return retval;
60831 }
60832
60833 /* Find the eventType variable */
60834 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType");
60835 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: newNodeId, browsePathSize: 1, browsePath: &name);
60836 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60837 retval = bpr.statusCode;
60838 UA_BrowsePathResult_clear(p: &bpr);
60839 deleteNode(server, nodeId: newNodeId, true);
60840 UA_NodeId_clear(p: &newNodeId);
60841 UA_UNLOCK(&server->serviceMutex);
60842 return retval;
60843 }
60844
60845 /* Set the EventType */
60846 UA_Variant value;
60847 UA_Variant_init(p: &value);
60848 UA_Variant_setScalar(v: &value, p: (void*)(uintptr_t)&eventType, type: &UA_TYPES[UA_TYPES_NODEID]);
60849 retval = writeValueAttribute(server, session: &server->adminSession,
60850 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60851 UA_BrowsePathResult_clear(p: &bpr);
60852 if(retval != UA_STATUSCODE_GOOD) {
60853 deleteNode(server, nodeId: newNodeId, true);
60854 UA_NodeId_clear(p: &newNodeId);
60855 UA_UNLOCK(&server->serviceMutex);
60856 return retval;
60857 }
60858
60859 *outNodeId = newNodeId;
60860 UA_UNLOCK(&server->serviceMutex);
60861 return UA_STATUSCODE_GOOD;
60862}
60863
60864static UA_StatusCode
60865eventSetStandardFields(UA_Server *server, const UA_NodeId *event,
60866 const UA_NodeId *origin, UA_ByteString *outEventId) {
60867 /* Set the SourceNode */
60868 UA_StatusCode retval;
60869 UA_QualifiedName name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "SourceNode");
60870 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60871 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60872 retval = bpr.statusCode;
60873 UA_BrowsePathResult_clear(p: &bpr);
60874 return retval;
60875 }
60876 UA_Variant value;
60877 UA_Variant_init(p: &value);
60878 UA_Variant_setScalarCopy(v: &value, p: origin, type: &UA_TYPES[UA_TYPES_NODEID]);
60879 retval = writeValueAttribute(server, session: &server->adminSession,
60880 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60881 UA_Variant_clear(p: &value);
60882 UA_BrowsePathResult_clear(p: &bpr);
60883 if(retval != UA_STATUSCODE_GOOD)
60884 return retval;
60885
60886 /* Set the ReceiveTime */
60887 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "ReceiveTime");
60888 bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60889 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60890 retval = bpr.statusCode;
60891 UA_BrowsePathResult_clear(p: &bpr);
60892 return retval;
60893 }
60894 UA_DateTime rcvTime = UA_DateTime_now();
60895 UA_Variant_setScalar(v: &value, p: &rcvTime, type: &UA_TYPES[UA_TYPES_DATETIME]);
60896 retval = writeValueAttribute(server, session: &server->adminSession,
60897 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60898 UA_BrowsePathResult_clear(p: &bpr);
60899 if(retval != UA_STATUSCODE_GOOD)
60900 return retval;
60901
60902 /* Set the EventId */
60903 UA_ByteString eventId = UA_BYTESTRING_NULL;
60904 retval = UA_Event_generateEventId(generatedId: &eventId);
60905 if(retval != UA_STATUSCODE_GOOD)
60906 return retval;
60907 name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventId");
60908 bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name);
60909 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
60910 retval = bpr.statusCode;
60911 UA_ByteString_clear(p: &eventId);
60912 UA_BrowsePathResult_clear(p: &bpr);
60913 return retval;
60914 }
60915 UA_Variant_init(p: &value);
60916 UA_Variant_setScalar(v: &value, p: &eventId, type: &UA_TYPES[UA_TYPES_BYTESTRING]);
60917 retval = writeValueAttribute(server, session: &server->adminSession,
60918 nodeId: &bpr.targets[0].targetId.nodeId, value: &value);
60919 UA_BrowsePathResult_clear(p: &bpr);
60920 if(retval != UA_STATUSCODE_GOOD) {
60921 UA_ByteString_clear(p: &eventId);
60922 return retval;
60923 }
60924
60925 /* Return the EventId */
60926 if(outEventId)
60927 *outEventId = eventId;
60928 else
60929 UA_ByteString_clear(p: &eventId);
60930
60931 return UA_STATUSCODE_GOOD;
60932}
60933
60934/* Filters an event according to the filter specified by mon and then adds it to
60935 * mons notification queue */
60936UA_StatusCode
60937UA_Event_addEventToMonitoredItem(UA_Server *server, const UA_NodeId *event,
60938 UA_MonitoredItem *mon) {
60939 UA_Notification *notification = UA_Notification_new();
60940 if(!notification)
60941 return UA_STATUSCODE_BADOUTOFMEMORY;
60942
60943 if(mon->parameters.filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER])
60944 return UA_STATUSCODE_BADFILTERNOTALLOWED;
60945 UA_EventFilter *eventFilter = (UA_EventFilter*)
60946 mon->parameters.filter.content.decoded.data;
60947
60948 /* The MonitoredItem must be attached to a Subscription. This code path is
60949 * not taken for local MonitoredItems (once they are enabled for Events). */
60950 UA_Subscription *sub = mon->subscription;
60951 UA_assert(sub);
60952
60953 UA_Session *session = sub->session;
60954 UA_StatusCode retval = filterEvent(server, session, eventNode: event,
60955 filter: eventFilter, efl: &notification->data.event,
60956 result: &notification->result);
60957 if(retval != UA_STATUSCODE_GOOD) {
60958 UA_Notification_delete(n: notification);
60959 if(retval == UA_STATUSCODE_BADNOMATCH)
60960 return UA_STATUSCODE_GOOD;
60961 return retval;
60962 }
60963
60964 notification->data.event.clientHandle = mon->parameters.clientHandle;
60965 notification->mon = mon;
60966
60967 UA_Notification_enqueueAndTrigger(server, n: notification);
60968 return UA_STATUSCODE_GOOD;
60969}
60970
60971#ifdef UA_ENABLE_HISTORIZING
60972static void
60973setHistoricalEvent(UA_Server *server, const UA_NodeId *origin,
60974 const UA_NodeId *emitNodeId, const UA_NodeId *eventNodeId) {
60975 UA_Variant historicalEventFilterValue;
60976 UA_Variant_init(p: &historicalEventFilterValue);
60977
60978 /* A HistoricalEventNode that has event history available will provide this property */
60979 UA_StatusCode retval =
60980 readObjectProperty(server, objectId: *emitNodeId,
60981 propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "HistoricalEventFilter"),
60982 value: &historicalEventFilterValue);
60983 if(retval != UA_STATUSCODE_GOOD) {
60984 /* Do not vex users with no match errors */
60985 if(retval != UA_STATUSCODE_BADNOMATCH)
60986 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60987 msg: "Cannot read the HistoricalEventFilter property of a "
60988 "listening node. StatusCode %s",
60989 UA_StatusCode_name(code: retval));
60990 return;
60991 }
60992
60993 /* If found then check if HistoricalEventFilter property has a valid value */
60994 if(UA_Variant_isEmpty(v: &historicalEventFilterValue) ||
60995 !UA_Variant_isScalar(v: &historicalEventFilterValue) ||
60996 historicalEventFilterValue.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) {
60997 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
60998 msg: "HistoricalEventFilter property of a listening node "
60999 "does not have a valid value");
61000 UA_Variant_clear(p: &historicalEventFilterValue);
61001 return;
61002 }
61003
61004 /* Finally, if found and valid then filter */
61005 UA_EventFilter *filter = (UA_EventFilter*) historicalEventFilterValue.data;
61006 UA_EventFieldList efl;
61007 UA_EventFilterResult result;
61008 retval = filterEvent(server, session: &server->adminSession,
61009 eventNode: eventNodeId, filter, efl: &efl, result: &result);
61010 if(retval == UA_STATUSCODE_GOOD)
61011 server->config.historyDatabase.setEvent(server, server->config.historyDatabase.context,
61012 origin, emitNodeId, filter, &efl);
61013 UA_EventFilterResult_clear(p: &result);
61014 UA_Variant_clear(p: &historicalEventFilterValue);
61015 UA_EventFieldList_clear(p: &efl);
61016}
61017#endif
61018
61019static const UA_NodeId objectsFolderId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_OBJECTSFOLDER}};
61020#define EMIT_REFS_ROOT_COUNT 4
61021static const UA_NodeId emitReferencesRoots[EMIT_REFS_ROOT_COUNT] =
61022 {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}},
61023 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}},
61024 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASEVENTSOURCE}},
61025 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASNOTIFIER}}};
61026
61027static const UA_NodeId isInFolderReferences[2] =
61028 {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}},
61029 {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}};
61030
61031UA_StatusCode
61032triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
61033 const UA_NodeId origin, UA_ByteString *outEventId,
61034 const UA_Boolean deleteEventNode) {
61035 UA_LOCK_ASSERT(&server->serviceMutex, 1);
61036
61037 UA_LOG_NODEID_DEBUG(&origin,
61038 UA_LOG_DEBUG(&server->config.logger, UA_LOGCATEGORY_SERVER,
61039 "Events: An event is triggered on node %.*s",
61040 (int)nodeIdStr.length, nodeIdStr.data));
61041
61042#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
61043 UA_Boolean isCallerAC = false;
61044 if(isConditionOrBranch(server, &eventNodeId, &origin, &isCallerAC)) {
61045 if(!isCallerAC) {
61046 UA_LOG_WARNING(&server->config.logger, UA_LOGCATEGORY_SERVER,
61047 "Condition Events: Please use A&C API to trigger Condition Events 0x%08X",
61048 UA_STATUSCODE_BADINVALIDARGUMENT);
61049 return UA_STATUSCODE_BADINVALIDARGUMENT;
61050 }
61051 }
61052#endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */
61053
61054 /* Check that the origin node exists */
61055 const UA_Node *originNode = UA_NODESTORE_GET(server, &origin);
61056 if(!originNode) {
61057 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
61058 msg: "Origin node for event does not exist.");
61059 return UA_STATUSCODE_BADNOTFOUND;
61060 }
61061 UA_NODESTORE_RELEASE(server, originNode);
61062
61063 /* Make sure the origin is in the ObjectsFolder (TODO: or in the ViewsFolder) */
61064 /* Only use Organizes and HasComponent to check if we are below the ObjectsFolder */
61065 UA_StatusCode retval;
61066 UA_ReferenceTypeSet refTypes;
61067 UA_ReferenceTypeSet_init(set: &refTypes);
61068 for(int i = 0; i < 2; ++i) {
61069 UA_ReferenceTypeSet tmpRefTypes;
61070 retval = referenceTypeIndices(server, refType: &isInFolderReferences[i], indices: &tmpRefTypes, true);
61071 if(retval != UA_STATUSCODE_GOOD) {
61072 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61073 msg: "Events: Could not create the list of references and their subtypes "
61074 "with StatusCode %s", UA_StatusCode_name(code: retval));
61075 }
61076 refTypes = UA_ReferenceTypeSet_union(setA: refTypes, setB: tmpRefTypes);
61077 }
61078
61079 if(!isNodeInTree(server, leafNode: &origin, nodeToFind: &objectsFolderId, relevantRefs: &refTypes)) {
61080 UA_LOG_ERROR(logger: &server->config.logger, category: UA_LOGCATEGORY_USERLAND,
61081 msg: "Node for event must be in ObjectsFolder!");
61082 return UA_STATUSCODE_BADINVALIDARGUMENT;
61083 }
61084
61085 /* Update the standard fields of the event */
61086 retval = eventSetStandardFields(server, event: &eventNodeId, origin: &origin, outEventId);
61087 if(retval != UA_STATUSCODE_GOOD) {
61088 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61089 msg: "Events: Could not set the standard event fields with StatusCode %s",
61090 UA_StatusCode_name(code: retval));
61091 return retval;
61092 }
61093
61094 /* List of nodes that emit the node. Events propagate upwards (bubble up) in
61095 * the node hierarchy. */
61096 UA_ExpandedNodeId *emitNodes = NULL;
61097 size_t emitNodesSize = 0;
61098
61099 /* Add the server node to the list of nodes from which the event is emitted.
61100 * The server node emits all events.
61101 *
61102 * Part 3, 7.17: In particular, the root notifier of a Server, the Server
61103 * Object defined in Part 5, is always capable of supplying all Events from
61104 * a Server and as such has implied HasEventSource References to every event
61105 * source in a Server. */
61106 UA_NodeId emitStartNodes[2];
61107 emitStartNodes[0] = origin;
61108 emitStartNodes[1] = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER);
61109
61110 /* Get all ReferenceTypes over which the events propagate */
61111 UA_ReferenceTypeSet emitRefTypes;
61112 UA_ReferenceTypeSet_init(set: &emitRefTypes);
61113 for(size_t i = 0; i < EMIT_REFS_ROOT_COUNT; i++) {
61114 UA_ReferenceTypeSet tmpRefTypes;
61115 retval = referenceTypeIndices(server, refType: &emitReferencesRoots[i], indices: &tmpRefTypes, true);
61116 if(retval != UA_STATUSCODE_GOOD) {
61117 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61118 msg: "Events: Could not create the list of references for event "
61119 "propagation with StatusCode %s", UA_StatusCode_name(code: retval));
61120 goto cleanup;
61121 }
61122 emitRefTypes = UA_ReferenceTypeSet_union(setA: emitRefTypes, setB: tmpRefTypes);
61123 }
61124
61125 /* Get the list of nodes in the hierarchy that emits the event. */
61126 retval = browseRecursive(server, startNodesSize: 2, startNodes: emitStartNodes, browseDirection: UA_BROWSEDIRECTION_INVERSE,
61127 refTypes: &emitRefTypes, nodeClassMask: UA_NODECLASS_UNSPECIFIED, true,
61128 resultsSize: &emitNodesSize, results: &emitNodes);
61129 if(retval != UA_STATUSCODE_GOOD) {
61130 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61131 msg: "Events: Could not create the list of nodes listening on the "
61132 "event with StatusCode %s", UA_StatusCode_name(code: retval));
61133 goto cleanup;
61134 }
61135
61136 /* Add the event to the listening MonitoredItems at each relevant node */
61137 for(size_t i = 0; i < emitNodesSize; i++) {
61138 /* Get the node */
61139 const UA_Node *node = UA_NODESTORE_GET(server, &emitNodes[i].nodeId);
61140 if(!node)
61141 continue;
61142
61143 /* Only consider objects */
61144 if(node->head.nodeClass != UA_NODECLASS_OBJECT) {
61145 UA_NODESTORE_RELEASE(server, node);
61146 continue;
61147 }
61148
61149 /* Add event to monitoreditems */
61150 UA_MonitoredItem *mon = node->head.monitoredItems;
61151 for(; mon != NULL; mon = mon->sampling.nodeListNext) {
61152 /* Is this an Event-MonitoredItem? */
61153 if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER)
61154 continue;
61155 retval = UA_Event_addEventToMonitoredItem(server, event: &eventNodeId, mon);
61156 if(retval != UA_STATUSCODE_GOOD) {
61157 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61158 msg: "Events: Could not add the event to a listening "
61159 "node with StatusCode %s", UA_StatusCode_name(code: retval));
61160 retval = UA_STATUSCODE_GOOD; /* Only log problems with individual emit nodes */
61161 }
61162 }
61163
61164 UA_NODESTORE_RELEASE(server, node);
61165
61166 /* Add event entry in the historical database */
61167#ifdef UA_ENABLE_HISTORIZING
61168 if(server->config.historyDatabase.setEvent)
61169 setHistoricalEvent(server, origin: &origin, emitNodeId: &emitNodes[i].nodeId, eventNodeId: &eventNodeId);
61170#endif
61171 }
61172
61173 /* Delete the node representation of the event */
61174 if(deleteEventNode) {
61175 retval = deleteNode(server, nodeId: eventNodeId, true);
61176 if(retval != UA_STATUSCODE_GOOD) {
61177 UA_LOG_WARNING(logger: &server->config.logger, category: UA_LOGCATEGORY_SERVER,
61178 msg: "Attempt to remove event using deleteNode failed. StatusCode %s",
61179 UA_StatusCode_name(code: retval));
61180 }
61181 }
61182
61183 cleanup:
61184 UA_Array_delete(p: emitNodes, size: emitNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
61185 return retval;
61186}
61187
61188UA_StatusCode
61189UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId,
61190 const UA_NodeId origin, UA_ByteString *outEventId,
61191 const UA_Boolean deleteEventNode) {
61192 UA_LOCK(&server->serviceMutex);
61193 UA_StatusCode res =
61194 triggerEvent(server, eventNodeId, origin, outEventId, deleteEventNode);
61195 UA_UNLOCK(&server->serviceMutex);
61196 return res;
61197}
61198#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
61199
61200/**** amalgamated original file "/src/server/ua_subscription_events_filter.c" ****/
61201
61202/* This Source Code Form is subject to the terms of the Mozilla Public
61203 * License, v. 2.0. If a copy of the MPL was not distributed with this
61204 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
61205 *
61206 * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH
61207 * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
61208 * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner)
61209 */
61210
61211
61212#ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
61213
61214typedef struct {
61215 UA_Server *server;
61216 UA_Session *session;
61217 const UA_NodeId *eventNode;
61218 const UA_ContentFilter *contentFilter;
61219 UA_ContentFilterResult *contentFilterResult;
61220 UA_Variant *valueResult;
61221 UA_UInt16 index;
61222} UA_FilterOperatorContext;
61223
61224static UA_StatusCode
61225evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx);
61226
61227/* Resolves a variant of type string or boolean into a corresponding status code */
61228static UA_StatusCode
61229resolveBoolean(UA_Variant operand) {
61230 UA_String value;
61231 value = UA_STRING(chars: "True");
61232 if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
61233 (UA_String_equal(s1: (UA_String *)operand.data, s2: &value))) ||
61234 ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
61235 (*(UA_Boolean *)operand.data == UA_TRUE))) {
61236 return UA_STATUSCODE_GOOD;
61237 }
61238 value = UA_STRING(chars: "False");
61239 if(((operand.type == &UA_TYPES[UA_TYPES_STRING]) &&
61240 (UA_String_equal(s1: (UA_String *)operand.data, s2: &value))) ||
61241 ((operand.type == &UA_TYPES[UA_TYPES_BOOLEAN]) &&
61242 (*(UA_Boolean *)operand.data == UA_FALSE))) {
61243 return UA_STATUSCODE_BADNOMATCH;
61244 }
61245
61246 /* If the operand can't be resolved, an error is returned */
61247 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61248}
61249
61250/* Part 4: 7.4.4.5 SimpleAttributeOperand
61251 * The clause can point to any attribute of nodes. Either a child of the event
61252 * node and also the event type. */
61253static UA_StatusCode
61254resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session,
61255 const UA_NodeId *origin,
61256 const UA_SimpleAttributeOperand *sao,
61257 UA_Variant *value) {
61258 /* Prepare the ReadValueId */
61259 UA_ReadValueId rvi;
61260 UA_ReadValueId_init(p: &rvi);
61261 rvi.indexRange = sao->indexRange;
61262 rvi.attributeId = sao->attributeId;
61263
61264 UA_DataValue v;
61265
61266 if(sao->browsePathSize == 0) {
61267 /* If this list (browsePath) is empty, the Node is the instance of the
61268 * TypeDefinition. (Part 4, 7.4.4.5) */
61269 rvi.nodeId = *origin;
61270
61271 /* A Condition is an indirection. Look up the target node. */
61272 /* TODO: check for Branches! One Condition could have multiple Branches */
61273 UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
61274 if(UA_NodeId_equal(n1: &sao->typeDefinitionId, n2: &conditionTypeId)) {
61275#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
61276 UA_StatusCode res = UA_getConditionId(server, origin, &rvi.nodeId);
61277 if(res != UA_STATUSCODE_GOOD)
61278 return res;
61279#else
61280 return UA_STATUSCODE_BADNOTSUPPORTED;
61281#endif
61282 }
61283
61284 v = UA_Server_readWithSession(server, session, item: &rvi,
61285 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
61286 } else {
61287 /* Resolve the browse path, starting from the event-source (and not the
61288 * typeDefinitionId). */
61289 UA_BrowsePathResult bpr =
61290 browseSimplifiedBrowsePath(server, origin: *origin,
61291 browsePathSize: sao->browsePathSize, browsePath: sao->browsePath);
61292 if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD)
61293 bpr.statusCode = UA_STATUSCODE_BADNOTFOUND;
61294 if(bpr.statusCode != UA_STATUSCODE_GOOD) {
61295 UA_StatusCode res = bpr.statusCode;
61296 UA_BrowsePathResult_clear(p: &bpr);
61297 return res;
61298 }
61299
61300 /* Use the first match */
61301 rvi.nodeId = bpr.targets[0].targetId.nodeId;
61302 v = UA_Server_readWithSession(server, session, item: &rvi,
61303 timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER);
61304 UA_BrowsePathResult_clear(p: &bpr);
61305 }
61306
61307 /* Move the result to the output */
61308 if(v.status == UA_STATUSCODE_GOOD && v.hasValue)
61309 *value = v.value;
61310 else
61311 UA_Variant_clear(p: &v.value);
61312 return v.status;
61313}
61314
61315/* Resolve operands to variants according to the operand type.
61316 * Part 4: 7.17.3 Table 142 specifies the allowed types. */
61317static UA_Variant
61318resolveOperand(UA_FilterOperatorContext *ctx, UA_UInt16 nr) {
61319 UA_StatusCode res;
61320 UA_Variant variant;
61321 UA_Variant_init(p: &variant);
61322 UA_ExtensionObject *op = &ctx->contentFilter->elements[ctx->index].filterOperands[nr];
61323 if(op->content.decoded.type == &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]) {
61324 /* SimpleAttributeOperand */
61325 res = resolveSimpleAttributeOperand(server: ctx->server, session: ctx->session, origin: ctx->eventNode,
61326 sao: (UA_SimpleAttributeOperand *)op->content.decoded.data,
61327 value: &variant);
61328 } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
61329 /* LiteralOperand */
61330 variant = ((UA_LiteralOperand *)op->content.decoded.data)->value;
61331 res = UA_STATUSCODE_GOOD;
61332 } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
61333 /* ElementOperand */
61334 UA_UInt16 oldIndex = ctx->index;
61335 ctx->index = (UA_UInt16)((UA_ElementOperand *)op->content.decoded.data)->index;
61336 res = evaluateWhereClauseContentFilter(ctx);
61337 variant = ctx->valueResult[ctx->index];
61338 ctx->index = oldIndex; /* restore the old index */
61339 } else {
61340 res = UA_STATUSCODE_BADFILTEROPERANDINVALID;
61341 }
61342
61343 if(res != UA_STATUSCODE_GOOD && res != UA_STATUSCODE_BADNOMATCH) {
61344 variant.type = NULL;
61345 ctx->contentFilterResult->elementResults[ctx->index].operandStatusCodes[nr] = res;
61346 }
61347
61348 return variant;
61349}
61350
61351static UA_StatusCode
61352ofTypeOperator(UA_FilterOperatorContext *ctx) {
61353 UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
61354 UA_Boolean result = false;
61355 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61356 if(pElement->filterOperandsSize != 1)
61357 return UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
61358 if(pElement->filterOperands[0].content.decoded.type !=
61359 &UA_TYPES[UA_TYPES_LITERALOPERAND])
61360 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61361
61362 UA_LiteralOperand *literalOperand =
61363 (UA_LiteralOperand *) pElement->filterOperands[0].content.decoded.data;
61364 if(!UA_Variant_isScalar(v: &literalOperand->value))
61365 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61366
61367 if(literalOperand->value.type != &UA_TYPES[UA_TYPES_NODEID] || literalOperand->value.data == NULL)
61368 return UA_STATUSCODE_BADEVENTFILTERINVALID;
61369
61370 UA_NodeId *literalOperandNodeId = (UA_NodeId *) literalOperand->value.data;
61371 UA_Variant typeNodeIdVariant;
61372 UA_Variant_init(p: &typeNodeIdVariant);
61373 UA_StatusCode readStatusCode =
61374 readObjectProperty(server: ctx->server, objectId: *ctx->eventNode,
61375 propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType"), value: &typeNodeIdVariant);
61376 if(readStatusCode != UA_STATUSCODE_GOOD)
61377 return readStatusCode;
61378
61379 if(!UA_Variant_isScalar(v: &typeNodeIdVariant) ||
61380 typeNodeIdVariant.type != &UA_TYPES[UA_TYPES_NODEID] ||
61381 typeNodeIdVariant.data == NULL) {
61382 UA_LOG_ERROR(logger: &ctx->server->config.logger, category: UA_LOGCATEGORY_SERVER,
61383 msg: "EventType has an invalid type.");
61384 UA_Variant_clear(p: &typeNodeIdVariant);
61385 return UA_STATUSCODE_BADINTERNALERROR;
61386 }
61387 /* check if the eventtype-nodeid is equal to the given oftype argument */
61388 result = UA_NodeId_equal(n1: (UA_NodeId*) typeNodeIdVariant.data, n2: literalOperandNodeId);
61389 /* check if the eventtype-nodeid is a subtype of the given oftype argument */
61390 if(!result)
61391 result = isNodeInTree_singleRef(server: ctx->server,
61392 leafNode: (UA_NodeId*) typeNodeIdVariant.data,
61393 nodeToFind: literalOperandNodeId,
61394 UA_REFERENCETYPEINDEX_HASSUBTYPE);
61395 UA_Variant_clear(p: &typeNodeIdVariant);
61396 if(!result)
61397 return UA_STATUSCODE_BADNOMATCH;
61398 return UA_STATUSCODE_GOOD;
61399}
61400
61401static UA_StatusCode
61402andOperator(UA_FilterOperatorContext *ctx) {
61403 UA_StatusCode firstBoolean_and = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61404 if(firstBoolean_and == UA_STATUSCODE_BADNOMATCH) {
61405 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61406 return UA_STATUSCODE_BADNOMATCH;
61407 }
61408 /* Evaluation of second operand */
61409 UA_StatusCode secondBoolean = resolveBoolean(operand: resolveOperand(ctx, nr: 1));
61410 /* Filteroperator AND */
61411 if(secondBoolean == UA_STATUSCODE_BADNOMATCH) {
61412 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61413 return UA_STATUSCODE_BADNOMATCH;
61414 }
61415 if((firstBoolean_and == UA_STATUSCODE_GOOD) &&
61416 (secondBoolean == UA_STATUSCODE_GOOD)) {
61417 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61418 return UA_STATUSCODE_GOOD;
61419 }
61420 return UA_STATUSCODE_BADFILTERELEMENTINVALID;
61421}
61422
61423static UA_StatusCode
61424orOperator(UA_FilterOperatorContext *ctx) {
61425 UA_StatusCode firstBoolean_or = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61426 if(firstBoolean_or == UA_STATUSCODE_GOOD) {
61427 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61428 return UA_STATUSCODE_GOOD;
61429 }
61430 /* Evaluation of second operand */
61431 UA_StatusCode secondBoolean = resolveBoolean(operand: resolveOperand(ctx, nr: 1));
61432 if(secondBoolean == UA_STATUSCODE_GOOD) {
61433 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61434 return UA_STATUSCODE_GOOD;
61435 }
61436 if((firstBoolean_or == UA_STATUSCODE_BADNOMATCH) &&
61437 (secondBoolean == UA_STATUSCODE_BADNOMATCH)) {
61438 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61439 return UA_STATUSCODE_BADNOMATCH;
61440 }
61441 return UA_STATUSCODE_BADFILTERELEMENTINVALID;
61442}
61443
61444static UA_Boolean
61445isNumericUnsigned(UA_UInt32 dataTypeKind){
61446 if(dataTypeKind == UA_DATATYPEKIND_UINT64 ||
61447 dataTypeKind == UA_DATATYPEKIND_UINT32 ||
61448 dataTypeKind == UA_DATATYPEKIND_UINT16 ||
61449 dataTypeKind == UA_DATATYPEKIND_BYTE)
61450 return true;
61451 return false;
61452}
61453
61454static UA_Boolean
61455isNumericSigned(UA_UInt32 dataTypeKind){
61456 if(dataTypeKind == UA_DATATYPEKIND_INT64 ||
61457 dataTypeKind == UA_DATATYPEKIND_INT32 ||
61458 dataTypeKind == UA_DATATYPEKIND_INT16 ||
61459 dataTypeKind == UA_DATATYPEKIND_SBYTE)
61460 return true;
61461 return false;
61462}
61463
61464static UA_Boolean
61465isFloatingPoint(UA_UInt32 dataTypeKind){
61466 if(dataTypeKind == UA_DATATYPEKIND_FLOAT ||
61467 dataTypeKind == UA_DATATYPEKIND_DOUBLE)
61468 return true;
61469 return false;
61470}
61471
61472static UA_Boolean
61473isStringType(UA_UInt32 dataTypeKind){
61474 if(dataTypeKind == UA_DATATYPEKIND_STRING ||
61475 dataTypeKind == UA_DATATYPEKIND_BYTESTRING)
61476 return true;
61477 return false;
61478}
61479
61480static UA_StatusCode
61481implicitNumericVariantTransformation(UA_Variant *variant, void *data){
61482 if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
61483 *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
61484 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61485 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
61486 *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
61487 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61488 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
61489 *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
61490 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61491 } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
61492 *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
61493 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61494 } else if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
61495 *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
61496 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61497 } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
61498 *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
61499 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61500 } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
61501 *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
61502 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61503 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61504 *(UA_Int64 *)data = *(UA_SByte *)variant->data;
61505 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61506 } else if(variant->type == &UA_TYPES[UA_TYPES_DOUBLE]){
61507 *(UA_Double *)data = *(UA_Double *)variant->data;
61508 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_DOUBLE]);
61509 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61510 *(UA_Double *)data = *(UA_Float *)variant->data;
61511 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_DOUBLE]);
61512 } else {
61513 return UA_STATUSCODE_BADTYPEMISMATCH;
61514 }
61515 return UA_STATUSCODE_GOOD;
61516}
61517
61518static UA_StatusCode
61519implicitNumericVariantTransformationUnsingedToSigned(UA_Variant *variant, void *data){
61520 if(variant->type == &UA_TYPES[UA_TYPES_UINT64]){
61521 if(*(UA_UInt64 *)variant->data > UA_INT64_MAX)
61522 return UA_STATUSCODE_BADTYPEMISMATCH;
61523 *(UA_Int64 *)data = *(UA_Int64 *)variant->data;
61524 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61525 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT32]){
61526 *(UA_Int64 *)data = *(UA_Int32 *)variant->data;
61527 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61528 } else if(variant->type == &UA_TYPES[UA_TYPES_UINT16]){
61529 *(UA_Int64 *)data = *(UA_Int16 *)variant->data;
61530 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61531 } else if(variant->type == &UA_TYPES[UA_TYPES_BYTE]){
61532 *(UA_Int64 *)data = *(UA_Byte *)variant->data;
61533 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_INT64]);
61534 } else {
61535 return UA_STATUSCODE_BADTYPEMISMATCH;
61536 }
61537 return UA_STATUSCODE_GOOD;
61538}
61539
61540static UA_StatusCode
61541implicitNumericVariantTransformationSignedToUnSigned(UA_Variant *variant, void *data){
61542 if(*(UA_Int64 *)variant->data < 0)
61543 return UA_STATUSCODE_BADTYPEMISMATCH;
61544 if(variant->type == &UA_TYPES[UA_TYPES_INT64]){
61545 *(UA_UInt64 *)data = *(UA_UInt64 *)variant->data;
61546 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61547 } else if(variant->type == &UA_TYPES[UA_TYPES_INT32]){
61548 *(UA_UInt64 *)data = *(UA_UInt32 *)variant->data;
61549 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61550 } else if(variant->type == &UA_TYPES[UA_TYPES_INT16]){
61551 *(UA_UInt64 *)data = *(UA_UInt16 *)variant->data;
61552 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61553 } else if(variant->type == &UA_TYPES[UA_TYPES_SBYTE]){
61554 *(UA_UInt64 *)data = *(UA_Byte *)variant->data;
61555 UA_Variant_setScalar(v: variant, p: data, type: &UA_TYPES[UA_TYPES_UINT64]);
61556 } else {
61557 return UA_STATUSCODE_BADTYPEMISMATCH;
61558 }
61559 return UA_STATUSCODE_GOOD;
61560}
61561
61562/* 0 -> Same Type, 1 -> Implicit Cast, 2 -> Only explicit Cast, -1 -> cast invalid */
61563static UA_SByte convertLookup[21][21] = {
61564 { 0, 1,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
61565 { 2, 0,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1},
61566 {-1,-1, 0,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
61567 {-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
61568 { 2, 2,-1,-1, 0,-1, 2,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
61569 {-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1, 2,-1,-1, 1,-1,-1,-1,-1,-1,-1},
61570 { 2, 2,-1,-1, 1,-1, 0,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1},
61571 {-1,-1, 2,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1},
61572 { 2, 2,-1,-1, 1,-1, 1,-1, 0, 1, 1,-1, 2,-1, 2,-1,-1, 2, 1, 1,-1},
61573 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 0, 1,-1, 2, 2, 2,-1,-1, 2, 2, 1,-1},
61574 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 0,-1, 2, 2, 2,-1,-1, 2, 2, 2,-1},
61575 {-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1, 0,-1,-1, 1,-1,-1,-1,-1,-1,-1},
61576 { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 0,-1, 2,-1,-1, 1, 1, 1,-1},
61577 {-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1, 0,-1,-1,-1, 2, 1, 1,-1},
61578 { 1, 1,-1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,-1, 0, 2, 2, 1, 1, 1,-1},
61579 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 0,-1,-1,-1,-1,-1},
61580 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 0,-1,-1,-1,-1},
61581 { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 2, 1, 2,-1,-1, 0, 1, 1,-1},
61582 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 1, 1,-1, 2, 2, 2,-1,-1, 2, 0, 1,-1},
61583 { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 1,-1, 2, 2, 2,-1,-1, 2, 2, 0,-1},
61584 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0}
61585};
61586
61587/* This array maps the index of the
61588 * standard DataType-Kind order to the
61589 * order of the type convertion array */
61590static UA_Byte dataTypeKindIndex[30] = {
61591 0, 12, 1, 8, 17,
61592 9, 18, 10, 19, 6,
61593 4, 14, 3, 7, 2,
61594 20, 11, 5, 13, 16,
61595 15, 255,255,255,255,
61596 255,255,255,255,255
61597};
61598
61599/* The OPC UA Standard defines in Part 4 several data type casting-rules. (see
61600 * 1.04 part 4 Table 122)
61601 * Return:
61602 * 0 -> same type
61603 * 1 -> types can be casted implicit
61604 * 2 -> types can only be explicitly casted
61605 * -1 -> types can't be casted */
61606static UA_SByte
61607checkTypeCastingOption(const UA_DataType *cast_target, const UA_DataType *cast_source) {
61608 UA_Byte firstOperatorTypeKindIndex = dataTypeKindIndex[cast_target->typeKind];
61609 UA_Byte secondOperatorTypeKindIndex = dataTypeKindIndex[cast_source->typeKind];
61610 if(firstOperatorTypeKindIndex == UA_BYTE_MAX ||
61611 secondOperatorTypeKindIndex == UA_BYTE_MAX)
61612 return -1;
61613
61614 return convertLookup[firstOperatorTypeKindIndex][secondOperatorTypeKindIndex];
61615}
61616
61617/* Compare operation for equal, gt, le, gte, lee
61618 * UA_STATUSCODE_GOOD if the comparison was true
61619 * UA_STATUSCODE_BADNOMATCH if the comparison was false
61620 * UA_STATUSCODE_BADFILTEROPERATORINVALID for invalid operators
61621 * UA_STATUSCODE_BADTYPEMISMATCH if one of the operands was not numeric
61622 * ToDo Array-Casting
61623 */
61624static UA_StatusCode
61625compareOperation(UA_Variant *firstOperand, UA_Variant *secondOperand, UA_FilterOperator op) {
61626 /* get precedence of the operand types */
61627 UA_Int16 firstOperand_precedence = UA_DataType_getPrecedence(type: firstOperand->type);
61628 UA_Int16 secondOperand_precedence = UA_DataType_getPrecedence(type: secondOperand->type);
61629 /* if the types are not equal and one of the precedence-ranks is -1, then there is
61630 no implicit conversion possible and therefore no compare */
61631 if(!UA_NodeId_equal(n1: &firstOperand->type->typeId, n2: &secondOperand->type->typeId) &&
61632 (firstOperand_precedence == -1 || secondOperand_precedence == -1)){
61633 return UA_STATUSCODE_BADTYPEMISMATCH;
61634 }
61635 /* check if the precedence order of the operators is swapped */
61636 UA_Variant *firstCompareOperand = firstOperand;
61637 UA_Variant *secondCompareOperand = secondOperand;
61638 UA_Boolean swapped = false;
61639 if (firstOperand_precedence < secondOperand_precedence){
61640 firstCompareOperand = secondOperand;
61641 secondCompareOperand = firstOperand;
61642 swapped = true;
61643 }
61644 UA_SByte castRule =
61645 checkTypeCastingOption(cast_target: firstCompareOperand->type, cast_source: secondCompareOperand->type);
61646
61647 if(!(castRule == 0 || castRule == 1)){
61648 return UA_STATUSCODE_BADTYPEMISMATCH;
61649 }
61650
61651 /* The operand Data-Types influence the behavior and steps for the comparison.
61652 * We need to check the operand types and store a rule which is used to select
61653 * the right behavior afterwards. */
61654 enum compareHandlingRuleEnum {
61655 UA_TYPES_EQUAL_ORDERED,
61656 UA_TYPES_EQUAL_UNORDERED,
61657 UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED,
61658 UA_TYPES_DIFFERENT_NUMERIC_SIGNED,
61659 UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT,
61660 UA_TYPES_DIFFERENT_TEXT,
61661 UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN,
61662 UA_TYPES_DIFFERENT_COMPARE_EXPLIC,
61663 UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED,
61664 UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED
61665 } compareHandlingRuleEnum;
61666
61667 if(castRule == 0 &&
61668 (UA_DataType_isNumeric(type: firstOperand->type) ||
61669 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_DATETIME ||
61670 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_STRING ||
61671 firstCompareOperand->type->typeKind == (UA_UInt32) UA_DATATYPEKIND_BYTESTRING)){
61672 /* Data-Types with a natural order (allow le, gt, lee, gte) */
61673 compareHandlingRuleEnum = UA_TYPES_EQUAL_ORDERED;
61674 } else if(castRule == 0){
61675 /* Data-Types without a natural order (le, gt, lee, gte are not allowed) */
61676 compareHandlingRuleEnum = UA_TYPES_EQUAL_UNORDERED;
61677 } else if(castRule == 1 &&
61678 isNumericSigned(dataTypeKind: firstOperand->type->typeKind) &&
61679 isNumericSigned(dataTypeKind: secondOperand->type->typeKind)){
61680 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_SIGNED;
61681 } else if(castRule == 1 &&
61682 isNumericUnsigned(dataTypeKind: firstOperand->type->typeKind) &&
61683 isNumericUnsigned(dataTypeKind: secondOperand->type->typeKind)){
61684 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED;
61685 } else if(castRule == 1 &&
61686 isFloatingPoint(dataTypeKind: firstOperand->type->typeKind) &&
61687 isFloatingPoint(dataTypeKind: secondOperand->type->typeKind)){
61688 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT;
61689 } else if(castRule == 1 &&
61690 isStringType(dataTypeKind: firstOperand->type->typeKind)&&
61691 isStringType(dataTypeKind: secondOperand->type->typeKind)){
61692 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_TEXT;
61693 } else if(castRule == 1 &&
61694 isNumericSigned(dataTypeKind: firstOperand->type->typeKind) &&
61695 isNumericUnsigned(dataTypeKind: secondOperand->type->typeKind)){
61696 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED;
61697 } else if(castRule == 1 &&
61698 isNumericSigned(dataTypeKind: secondOperand->type->typeKind) &&
61699 isNumericUnsigned(dataTypeKind: firstOperand->type->typeKind)){
61700 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED;
61701 } else if(castRule == -1 || castRule == 2){
61702 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_EXPLIC;
61703 } else {
61704 compareHandlingRuleEnum = UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN;
61705 }
61706
61707 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN)
61708 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61709
61710 if(swapped){
61711 firstCompareOperand = secondCompareOperand;
61712 secondCompareOperand = firstCompareOperand;
61713 }
61714
61715 if(op == UA_FILTEROPERATOR_EQUALS){
61716 UA_Byte variantContent[16];
61717 memset(s: &variantContent, c: 0, n: sizeof(UA_Byte) * 16);
61718 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
61719 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
61720 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
61721 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61722 implicitNumericVariantTransformation(variant: secondCompareOperand, data: &variantContent[8]);
61723 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
61724 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61725 implicitNumericVariantTransformationUnsingedToSigned(variant: secondCompareOperand, data: &variantContent[8]);
61726 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
61727 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61728 implicitNumericVariantTransformationSignedToUnSigned(variant: secondCompareOperand, data: &variantContent[8]);
61729 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
61730 firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61731 secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61732 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
61733 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC ){
61734 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61735 }
61736 if(UA_order(p1: firstCompareOperand, p2: secondCompareOperand, type: &UA_TYPES[UA_TYPES_VARIANT]) == UA_ORDER_EQ) {
61737 return UA_STATUSCODE_GOOD;
61738 }
61739 } else {
61740 UA_Byte variantContent[16];
61741 memset(s: &variantContent, c: 0, n: sizeof(UA_Byte) * 16);
61742 if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_SIGNED ||
61743 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_UNSIGNED ||
61744 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_NUMERIC_FLOATING_POINT) {
61745 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61746 implicitNumericVariantTransformation(variant: secondCompareOperand, data: &variantContent[8]);
61747 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_SIGNED) {
61748 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61749 implicitNumericVariantTransformationUnsingedToSigned(variant: secondCompareOperand, data: &variantContent[8]);
61750 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_SIGNEDNESS_CAST_TO_UNSIGNED) {
61751 implicitNumericVariantTransformation(variant: firstCompareOperand, data: variantContent);
61752 implicitNumericVariantTransformationSignedToUnSigned(variant: secondCompareOperand, data: &variantContent[8]);
61753 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_TEXT) {
61754 firstCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61755 secondCompareOperand->type = &UA_TYPES[UA_TYPES_STRING];
61756 } else if(compareHandlingRuleEnum == UA_TYPES_EQUAL_UNORDERED) {
61757 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61758 } else if(compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_FORBIDDEN ||
61759 compareHandlingRuleEnum == UA_TYPES_DIFFERENT_COMPARE_EXPLIC) {
61760 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
61761 }
61762 UA_Order gte_result = UA_order(p1: firstCompareOperand, p2: secondCompareOperand,
61763 type: &UA_TYPES[UA_TYPES_VARIANT]);
61764 if(op == UA_FILTEROPERATOR_LESSTHAN) {
61765 if(gte_result == UA_ORDER_LESS) {
61766 return UA_STATUSCODE_GOOD;
61767 }
61768 } else if(op == UA_FILTEROPERATOR_GREATERTHAN) {
61769 if(gte_result == UA_ORDER_MORE) {
61770 return UA_STATUSCODE_GOOD;
61771 }
61772 } else if(op == UA_FILTEROPERATOR_LESSTHANOREQUAL) {
61773 if(gte_result == UA_ORDER_LESS || gte_result == UA_ORDER_EQ) {
61774 return UA_STATUSCODE_GOOD;
61775 }
61776 } else if(op == UA_FILTEROPERATOR_GREATERTHANOREQUAL) {
61777 if(gte_result == UA_ORDER_MORE || gte_result == UA_ORDER_EQ) {
61778 return UA_STATUSCODE_GOOD;
61779 }
61780 }
61781 }
61782 return UA_STATUSCODE_BADNOMATCH;
61783}
61784
61785static UA_StatusCode
61786compareOperator(UA_FilterOperatorContext *ctx) {
61787 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61788 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61789 if(UA_Variant_isEmpty(v: &firstOperand))
61790 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61791 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61792 if(UA_Variant_isEmpty(v: &secondOperand)) {
61793 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61794 }
61795 /* ToDo remove the following restriction: Add support for arrays */
61796 if(!UA_Variant_isScalar(v: &firstOperand) || !UA_Variant_isScalar(v: &secondOperand)){
61797 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61798 }
61799 return compareOperation(firstOperand: &firstOperand, secondOperand: &secondOperand,
61800 op: ctx->contentFilter->elements[ctx->index].filterOperator);
61801}
61802
61803static UA_StatusCode
61804bitwiseOperator(UA_FilterOperatorContext *ctx) {
61805 /* The bitwise operators all have 2 operands which are evaluated equally. */
61806 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61807 if(UA_Variant_isEmpty(v: &firstOperand)) {
61808 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61809 }
61810 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61811 if(UA_Variant_isEmpty(v: &secondOperand)) {
61812 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61813 }
61814
61815 UA_Boolean bitwiseAnd =
61816 ctx->contentFilter->elements[ctx->index].filterOperator == UA_FILTEROPERATOR_BITWISEAND;
61817
61818 /* check if the operators are integers */
61819 if(!UA_DataType_isNumeric(type: firstOperand.type) ||
61820 !UA_DataType_isNumeric(type: secondOperand.type) ||
61821 !UA_Variant_isScalar(v: &firstOperand) ||
61822 !UA_Variant_isScalar(v: &secondOperand) ||
61823 (firstOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
61824 (secondOperand.type == &UA_TYPES[UA_TYPES_DOUBLE]) ||
61825 (secondOperand.type == &UA_TYPES[UA_TYPES_FLOAT]) ||
61826 (firstOperand.type == &UA_TYPES[UA_TYPES_FLOAT])) {
61827 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61828 }
61829
61830 /* check which is the return type (higher precedence == bigger integer)*/
61831 UA_Int16 precedence = UA_DataType_getPrecedence(type: firstOperand.type);
61832 if(precedence > UA_DataType_getPrecedence(type: secondOperand.type)) {
61833 precedence = UA_DataType_getPrecedence(type: secondOperand.type);
61834 }
61835
61836 switch(precedence){
61837 case 3:
61838 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT64];
61839 UA_Int64 result_int64;
61840 if(bitwiseAnd) {
61841 result_int64 = *((UA_Int64 *)firstOperand.data) & *((UA_Int64 *)secondOperand.data);
61842 } else {
61843 result_int64 = *((UA_Int64 *)firstOperand.data) | *((UA_Int64 *)secondOperand.data);
61844 }
61845 UA_Int64_copy(src: &result_int64, dst: (UA_Int64 *) ctx->valueResult[ctx->index].data);
61846 break;
61847 case 4:
61848 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT64];
61849 UA_UInt64 result_uint64s;
61850 if(bitwiseAnd) {
61851 result_uint64s = *((UA_UInt64 *)firstOperand.data) & *((UA_UInt64 *)secondOperand.data);
61852 } else {
61853 result_uint64s = *((UA_UInt64 *)firstOperand.data) | *((UA_UInt64 *)secondOperand.data);
61854 }
61855 UA_UInt64_copy(src: &result_uint64s, dst: (UA_UInt64 *) ctx->valueResult[ctx->index].data);
61856 break;
61857 case 5:
61858 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT32];
61859 UA_Int32 result_int32;
61860 if(bitwiseAnd) {
61861 result_int32 = *((UA_Int32 *)firstOperand.data) & *((UA_Int32 *)secondOperand.data);
61862 } else {
61863 result_int32 = *((UA_Int32 *)firstOperand.data) | *((UA_Int32 *)secondOperand.data);
61864 }
61865 UA_Int32_copy(src: &result_int32, dst: (UA_Int32 *) ctx->valueResult[ctx->index].data);
61866 break;
61867 case 6:
61868 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT32];
61869 UA_UInt32 result_uint32;
61870 if(bitwiseAnd) {
61871 result_uint32 = *((UA_UInt32 *)firstOperand.data) & *((UA_UInt32 *)secondOperand.data);
61872 } else {
61873 result_uint32 = *((UA_UInt32 *)firstOperand.data) | *((UA_UInt32 *)secondOperand.data);
61874 }
61875 UA_UInt32_copy(src: &result_uint32, dst: (UA_UInt32 *) ctx->valueResult[ctx->index].data);
61876 break;
61877 case 8:
61878 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_INT16];
61879 UA_Int16 result_int16;
61880 if(bitwiseAnd) {
61881 result_int16 = *((UA_Int16 *)firstOperand.data) & *((UA_Int16 *)secondOperand.data);
61882 } else {
61883 result_int16 = *((UA_Int16 *)firstOperand.data) | *((UA_Int16 *)secondOperand.data);
61884 }
61885 UA_Int16_copy(src: &result_int16, dst: (UA_Int16 *) ctx->valueResult[ctx->index].data);
61886 break;
61887 case 9:
61888 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_UINT16];
61889 UA_UInt16 result_uint16;
61890 if(bitwiseAnd) {
61891 result_uint16 = *((UA_UInt16 *)firstOperand.data) & *((UA_UInt16 *)secondOperand.data);
61892 } else {
61893 result_uint16 = *((UA_UInt16 *)firstOperand.data) | *((UA_UInt16 *)secondOperand.data);
61894 }
61895 UA_UInt16_copy(src: &result_uint16, dst: (UA_UInt16 *) ctx->valueResult[ctx->index].data);
61896 break;
61897 case 10:
61898 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_SBYTE];
61899 UA_SByte result_sbyte;
61900 if(bitwiseAnd) {
61901 result_sbyte = *((UA_SByte *)firstOperand.data) & *((UA_SByte *)secondOperand.data);
61902 } else {
61903 result_sbyte = *((UA_SByte *)firstOperand.data) | *((UA_SByte *)secondOperand.data);
61904 }
61905 UA_SByte_copy(src: &result_sbyte, dst: (UA_SByte *) ctx->valueResult[ctx->index].data);
61906 break;
61907 case 11:
61908 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BYTE];
61909 UA_Byte result_byte;
61910 if(bitwiseAnd) {
61911 result_byte = *((UA_Byte *)firstOperand.data) & *((UA_Byte *)secondOperand.data);
61912 } else {
61913 result_byte = *((UA_Byte *)firstOperand.data) | *((UA_Byte *)secondOperand.data);
61914 }
61915 UA_Byte_copy(src: &result_byte, dst: (UA_Byte *) ctx->valueResult[ctx->index].data);
61916 break;
61917 default:
61918 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61919 }
61920 return UA_STATUSCODE_GOOD;
61921}
61922
61923static UA_StatusCode
61924betweenOperator(UA_FilterOperatorContext *ctx) {
61925 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61926
61927 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61928 UA_Variant secondOperand = resolveOperand(ctx, nr: 1);
61929 UA_Variant thirdOperand = resolveOperand(ctx, nr: 2);
61930
61931 if((UA_Variant_isEmpty(v: &firstOperand) ||
61932 UA_Variant_isEmpty(v: &secondOperand) ||
61933 UA_Variant_isEmpty(v: &thirdOperand)) ||
61934 (!UA_DataType_isNumeric(type: firstOperand.type) ||
61935 !UA_DataType_isNumeric(type: secondOperand.type) ||
61936 !UA_DataType_isNumeric(type: thirdOperand.type)) ||
61937 (!UA_Variant_isScalar(v: &firstOperand) ||
61938 !UA_Variant_isScalar(v: &secondOperand) ||
61939 !UA_Variant_isScalar(v: &thirdOperand))) {
61940 return UA_STATUSCODE_BADFILTEROPERANDINVALID;
61941 }
61942
61943 /* Between can be evaluated through greaterThanOrEqual and lessThanOrEqual */
61944 if(compareOperation(firstOperand: &firstOperand, secondOperand: &secondOperand, op: UA_FILTEROPERATOR_GREATERTHANOREQUAL) == UA_STATUSCODE_GOOD &&
61945 compareOperation(firstOperand: &firstOperand, secondOperand: &thirdOperand, op: UA_FILTEROPERATOR_LESSTHANOREQUAL) == UA_STATUSCODE_GOOD){
61946 return UA_STATUSCODE_GOOD;
61947 }
61948 return UA_STATUSCODE_BADNOMATCH;
61949}
61950
61951static UA_StatusCode
61952inListOperator(UA_FilterOperatorContext *ctx) {
61953 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61954 UA_Variant firstOperand = resolveOperand(ctx, nr: 0);
61955
61956 if(UA_Variant_isEmpty(v: &firstOperand) ||
61957 !UA_Variant_isScalar(v: &firstOperand)) {
61958 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61959 }
61960
61961 /* Evaluating the list of operands */
61962 for(size_t i = 1; i < ctx->contentFilter->elements[ctx->index].filterOperandsSize; i++) {
61963 /* Resolving the current operand */
61964 UA_Variant currentOperator = resolveOperand(ctx, nr: (UA_UInt16)i);
61965
61966 /* Check if the operand conforms to the operator*/
61967 if(UA_Variant_isEmpty(v: &currentOperator) ||
61968 !UA_Variant_isScalar(v: &currentOperator)) {
61969 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
61970 }
61971 if(compareOperation(firstOperand: &firstOperand, secondOperand: &currentOperator, op: UA_FILTEROPERATOR_EQUALS)) {
61972 return UA_STATUSCODE_GOOD;
61973 }
61974 }
61975 return UA_STATUSCODE_BADNOMATCH;
61976}
61977
61978static UA_StatusCode
61979isNullOperator(UA_FilterOperatorContext *ctx) {
61980 /* Checking if operand is NULL. This is done by reducing the operand to a
61981 * variant and then checking if it is empty. */
61982 UA_Variant operand = resolveOperand(ctx, nr: 0);
61983 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61984 if(!UA_Variant_isEmpty(v: &operand))
61985 return UA_STATUSCODE_BADNOMATCH;
61986 return UA_STATUSCODE_GOOD;
61987}
61988
61989static UA_StatusCode
61990notOperator(UA_FilterOperatorContext *ctx) {
61991 /* Inverting the boolean value of the operand. */
61992 UA_StatusCode res = resolveBoolean(operand: resolveOperand(ctx, nr: 0));
61993 ctx->valueResult[ctx->index].type = &UA_TYPES[UA_TYPES_BOOLEAN];
61994 /* invert result */
61995 if(res == UA_STATUSCODE_GOOD)
61996 return UA_STATUSCODE_BADNOMATCH;
61997 return UA_STATUSCODE_GOOD;
61998}
61999
62000static UA_StatusCode
62001evaluateWhereClauseContentFilter(UA_FilterOperatorContext *ctx) {
62002 UA_LOCK_ASSERT(&ctx->server->serviceMutex, 1);
62003
62004 if(ctx->contentFilter->elements == NULL || ctx->contentFilter->elementsSize == 0) {
62005 /* Nothing to do.*/
62006 return UA_STATUSCODE_GOOD;
62007 }
62008
62009 /* The first element needs to be evaluated, this might be linked to other
62010 * elements, which are evaluated in these cases. See 7.4.1 in Part 4. */
62011 UA_ContentFilterElement *pElement = &ctx->contentFilter->elements[ctx->index];
62012 UA_StatusCode *result = &ctx->contentFilterResult->elementResults[ctx->index].statusCode;
62013 switch(pElement->filterOperator) {
62014 case UA_FILTEROPERATOR_INVIEW:
62015 /* Fallthrough */
62016 case UA_FILTEROPERATOR_RELATEDTO:
62017 /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
62018 return UA_STATUSCODE_BADEVENTFILTERINVALID;
62019 case UA_FILTEROPERATOR_EQUALS:
62020 /* Fallthrough */
62021 case UA_FILTEROPERATOR_GREATERTHAN:
62022 /* Fallthrough */
62023 case UA_FILTEROPERATOR_LESSTHAN:
62024 /* Fallthrough */
62025 case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
62026 /* Fallthrough */
62027 case UA_FILTEROPERATOR_LESSTHANOREQUAL:
62028 *result = compareOperator(ctx);
62029 break;
62030 case UA_FILTEROPERATOR_LIKE:
62031 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
62032 case UA_FILTEROPERATOR_NOT:
62033 *result = notOperator(ctx);
62034 break;
62035 case UA_FILTEROPERATOR_BETWEEN:
62036 *result = betweenOperator(ctx);
62037 break;
62038 case UA_FILTEROPERATOR_INLIST:
62039 /* ToDo currently only numeric types are allowed */
62040 *result = inListOperator(ctx);
62041 break;
62042 case UA_FILTEROPERATOR_ISNULL:
62043 *result = isNullOperator(ctx);
62044 break;
62045 case UA_FILTEROPERATOR_AND:
62046 *result = andOperator(ctx);
62047 break;
62048 case UA_FILTEROPERATOR_OR:
62049 *result = orOperator(ctx);
62050 break;
62051 case UA_FILTEROPERATOR_CAST:
62052 return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
62053 case UA_FILTEROPERATOR_BITWISEAND:
62054 *result = bitwiseOperator(ctx);
62055 break;
62056 case UA_FILTEROPERATOR_BITWISEOR:
62057 *result = bitwiseOperator(ctx);
62058 break;
62059 case UA_FILTEROPERATOR_OFTYPE:
62060 *result = ofTypeOperator(ctx);
62061 break;
62062 default:
62063 return UA_STATUSCODE_BADFILTEROPERATORINVALID;
62064 }
62065
62066 if(ctx->valueResult[ctx->index].type == &UA_TYPES[UA_TYPES_BOOLEAN]) {
62067 UA_Boolean *res = UA_Boolean_new();
62068 if(ctx->contentFilterResult->elementResults[ctx->index].statusCode == UA_STATUSCODE_GOOD)
62069 *res = true;
62070 else
62071 *res = false;
62072 ctx->valueResult[ctx->index].data = res;
62073 }
62074 return ctx->contentFilterResult->elementResults[ctx->index].statusCode;
62075}
62076
62077/* Exposes the filters For unit tests */
62078UA_StatusCode
62079UA_Server_evaluateWhereClauseContentFilter(UA_Server *server, UA_Session *session,
62080 const UA_NodeId *eventNode,
62081 const UA_ContentFilter *contentFilter,
62082 UA_ContentFilterResult *contentFilterResult) {
62083 if(contentFilter->elementsSize == 0)
62084 return UA_STATUSCODE_GOOD;
62085 /* TODO add maximum lenth size to the server config */
62086 if(contentFilter->elementsSize > 256)
62087 return UA_STATUSCODE_BADINVALIDARGUMENT;
62088 UA_Variant valueResult[256];
62089 for(size_t i = 0; i < contentFilter->elementsSize; ++i) {
62090 UA_Variant_init(p: &valueResult[i]);
62091 }
62092
62093 UA_FilterOperatorContext ctx;
62094 ctx.server = server;
62095 ctx.session = session;
62096 ctx.eventNode = eventNode;
62097 ctx.contentFilter = contentFilter;
62098 ctx.contentFilterResult = contentFilterResult;
62099 ctx.valueResult = valueResult;
62100 ctx.index = 0;
62101
62102 UA_StatusCode res = evaluateWhereClauseContentFilter(ctx: &ctx);
62103 for(size_t i = 0; i < ctx.contentFilter->elementsSize; i++) {
62104 if(!UA_Variant_isEmpty(v: &ctx.valueResult[i]))
62105 UA_Variant_clear(p: &ctx.valueResult[i]);
62106 }
62107 return res;
62108}
62109
62110static UA_Boolean
62111isValidEvent(UA_Server *server, const UA_NodeId *validEventParent,
62112 const UA_NodeId *eventId) {
62113 /* find the eventType variableNode */
62114 UA_QualifiedName findName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType");
62115 UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *eventId, browsePathSize: 1, browsePath: &findName);
62116 if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) {
62117 UA_BrowsePathResult_clear(p: &bpr);
62118 return false;
62119 }
62120
62121 /* Get the EventType Property Node */
62122 UA_Variant tOutVariant;
62123 UA_Variant_init(p: &tOutVariant);
62124
62125 /* Read the Value of EventType Property Node (the Value should be a NodeId) */
62126 UA_StatusCode retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId,
62127 attributeId: UA_ATTRIBUTEID_VALUE, v: &tOutVariant);
62128 if(retval != UA_STATUSCODE_GOOD ||
62129 !UA_Variant_hasScalarType(v: &tOutVariant, type: &UA_TYPES[UA_TYPES_NODEID])) {
62130 UA_BrowsePathResult_clear(p: &bpr);
62131 return false;
62132 }
62133
62134 const UA_NodeId *tEventType = (UA_NodeId*)tOutVariant.data;
62135
62136 /* check whether the EventType is a Subtype of CondtionType
62137 * (Part 9 first implementation) */
62138 UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
62139 if(UA_NodeId_equal(n1: validEventParent, n2: &conditionTypeId) &&
62140 isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &conditionTypeId,
62141 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
62142 UA_BrowsePathResult_clear(p: &bpr);
62143 UA_Variant_clear(p: &tOutVariant);
62144 return true;
62145 }
62146
62147 /*EventType is not a Subtype of CondtionType
62148 *(ConditionId Clause won't be present in Events, which are not Conditions)*/
62149 /* check whether Valid Event other than Conditions */
62150 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62151 UA_Boolean isSubtypeOfBaseEvent =
62152 isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &baseEventTypeId,
62153 UA_REFERENCETYPEINDEX_HASSUBTYPE);
62154
62155 UA_BrowsePathResult_clear(p: &bpr);
62156 UA_Variant_clear(p: &tOutVariant);
62157 return isSubtypeOfBaseEvent;
62158}
62159
62160UA_StatusCode
62161filterEvent(UA_Server *server, UA_Session *session,
62162 const UA_NodeId *eventNode, UA_EventFilter *filter,
62163 UA_EventFieldList *efl, UA_EventFilterResult *result) {
62164 if(filter->selectClausesSize == 0)
62165 return UA_STATUSCODE_BADEVENTFILTERINVALID;
62166
62167 UA_EventFieldList_init(p: efl);
62168 efl->eventFields = (UA_Variant *)
62169 UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_VARIANT]);
62170 if(!efl->eventFields)
62171 return UA_STATUSCODE_BADOUTOFMEMORY;
62172 efl->eventFieldsSize = filter->selectClausesSize;
62173
62174 /* empty event filter result */
62175 UA_EventFilterResult_init(p: result);
62176 result->selectClauseResultsSize = filter->selectClausesSize;
62177 result->selectClauseResults = (UA_StatusCode *)
62178 UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62179 if(!result->selectClauseResults) {
62180 UA_EventFieldList_clear(p: efl);
62181 UA_EventFilterResult_clear(p: result);
62182 return UA_STATUSCODE_BADOUTOFMEMORY;
62183 }
62184 /* prepare content filter result structure */
62185 if(filter->whereClause.elementsSize != 0) {
62186 result->whereClauseResult.elementResultsSize = filter->whereClause.elementsSize;
62187 result->whereClauseResult.elementResults = (UA_ContentFilterElementResult *)
62188 UA_Array_new(size: filter->whereClause.elementsSize,
62189 type: &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
62190 if(!result->whereClauseResult.elementResults) {
62191 UA_EventFieldList_clear(p: efl);
62192 UA_EventFilterResult_clear(p: result);
62193 return UA_STATUSCODE_BADOUTOFMEMORY;
62194 }
62195 for(size_t i = 0; i < result->whereClauseResult.elementResultsSize; ++i) {
62196 result->whereClauseResult.elementResults[i].operandStatusCodesSize =
62197 filter->whereClause.elements->filterOperandsSize;
62198 result->whereClauseResult.elementResults[i].operandStatusCodes =
62199 (UA_StatusCode *)UA_Array_new(
62200 size: filter->whereClause.elements->filterOperandsSize,
62201 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62202 if(!result->whereClauseResult.elementResults[i].operandStatusCodes) {
62203 UA_EventFieldList_clear(p: efl);
62204 UA_EventFilterResult_clear(p: result);
62205 return UA_STATUSCODE_BADOUTOFMEMORY;
62206 }
62207 }
62208 }
62209
62210 /* Apply the content (where) filter */
62211 UA_StatusCode res =
62212 UA_Server_evaluateWhereClauseContentFilter(server, session, eventNode,
62213 contentFilter: &filter->whereClause, contentFilterResult: &result->whereClauseResult);
62214 if(res != UA_STATUSCODE_GOOD){
62215 UA_EventFieldList_clear(p: efl);
62216 UA_EventFilterResult_clear(p: result);
62217 return res;
62218 }
62219
62220 /* Apply the select filter */
62221 /* Check if the browsePath is BaseEventType, in which case nothing more
62222 * needs to be checked */
62223 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62224 for(size_t i = 0; i < filter->selectClausesSize; i++) {
62225 if(!UA_NodeId_equal(n1: &filter->selectClauses[i].typeDefinitionId, n2: &baseEventTypeId) &&
62226 !isValidEvent(server, validEventParent: &filter->selectClauses[i].typeDefinitionId, eventId: eventNode)) {
62227 UA_Variant_init(p: &efl->eventFields[i]);
62228 /* EventFilterResult currently isn't being used
62229 notification->result.selectClauseResults[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; */
62230 continue;
62231 }
62232
62233 /* TODO: Put the result into the selectClausResults */
62234 resolveSimpleAttributeOperand(server, session, origin: eventNode,
62235 sao: &filter->selectClauses[i], value: &efl->eventFields[i]);
62236 }
62237
62238 return UA_STATUSCODE_GOOD;
62239}
62240
62241/*****************************************/
62242/* Validation of Filters during Creation */
62243/*****************************************/
62244
62245/* Initial select clause validation. The following checks are currently performed:
62246 * - Check if typedefenitionid or browsepath of any clause is NULL
62247 * - Check if the eventType is a subtype of BaseEventType
62248 * - Check if attributeId is valid
62249 * - Check if browsePath contains null
62250 * - Check if indexRange is defined and if it is parsable
62251 * - Check if attributeId is value */
62252void
62253UA_Event_staticSelectClauseValidation(UA_Server *server,
62254 const UA_EventFilter *eventFilter,
62255 UA_StatusCode *result) {
62256 /* The selectClause only has to be checked, if the size is not zero */
62257 if(eventFilter->selectClausesSize == 0)
62258 return;
62259 for(size_t i = 0; i < eventFilter->selectClausesSize; ++i) {
62260 result[i] = UA_STATUSCODE_GOOD;
62261 /* /typedefenitionid or browsepath of any clause is not NULL ? */
62262 if(UA_NodeId_isNull(p: &eventFilter->selectClauses[i].typeDefinitionId)) {
62263 result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
62264 continue;
62265 }
62266 /*ToDo: Check the following workaround. In UaExpert Event View the selection
62267 * of the Server Object set up 7 select filter entries by default. The last
62268 * element ist from node 2782 (A&C ConditionType). Since the reduced
62269 * information model dos not contain this type, the result has a brows path of
62270 * "null" which results in an error. */
62271 UA_NodeId ac_conditionType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE);
62272 if(UA_NodeId_equal(n1: &eventFilter->selectClauses[i].typeDefinitionId, n2: &ac_conditionType)) {
62273 continue;
62274 }
62275 if(&eventFilter->selectClauses[i].browsePath[0] == NULL) {
62276 result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
62277 continue;
62278 }
62279 /* eventType is a subtype of BaseEventType ? */
62280 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62281 if(!isNodeInTree_singleRef(
62282 server, leafNode: &eventFilter->selectClauses[i].typeDefinitionId,
62283 nodeToFind: &baseEventTypeId, UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
62284 result[i] = UA_STATUSCODE_BADTYPEDEFINITIONINVALID;
62285 continue;
62286 }
62287 /* attributeId is valid ? */
62288 if(!((0 < eventFilter->selectClauses[i].attributeId) &&
62289 (eventFilter->selectClauses[i].attributeId < 28))) {
62290 result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
62291 continue;
62292 }
62293 /* browsePath contains null ? */
62294 for(size_t j = 0; j < eventFilter->selectClauses[i].browsePathSize; ++j) {
62295 if(UA_QualifiedName_isNull(
62296 q: &eventFilter->selectClauses[i].browsePath[j])) {
62297 result[i] = UA_STATUSCODE_BADBROWSENAMEINVALID;
62298 break;
62299 }
62300 }
62301
62302 /* Get the list of Subtypes from current node */
62303 UA_ReferenceTypeSet reftypes_interface =
62304 UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
62305 UA_ExpandedNodeId *chilTypeNodes = NULL;
62306 size_t chilTypeNodesSize = 0;
62307 UA_StatusCode res;
62308 res = browseRecursive(server, startNodesSize: 1, startNodes: &eventFilter->selectClauses[i].typeDefinitionId,
62309 browseDirection: UA_BROWSEDIRECTION_FORWARD, refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_OBJECTTYPE,
62310 true, resultsSize: &chilTypeNodesSize, results: &chilTypeNodes);
62311 if(res!=UA_STATUSCODE_GOOD){
62312 result[i] = UA_STATUSCODE_BADATTRIBUTEIDINVALID;
62313 continue;
62314 }
62315
62316 UA_Boolean subTypeContainField = false;
62317 for (size_t j = 0; j < chilTypeNodesSize; ++j) {
62318 /* browsPath element is defined in path */
62319 UA_BrowsePathResult bpr =
62320 browseSimplifiedBrowsePath(server, origin: chilTypeNodes[j].nodeId,
62321 browsePathSize: eventFilter->selectClauses[i].browsePathSize,
62322 browsePath: eventFilter->selectClauses[i].browsePath);
62323
62324 if(bpr.statusCode != UA_STATUSCODE_GOOD){
62325 UA_BrowsePathResult_clear(p: &bpr);
62326 continue;
62327 }
62328 subTypeContainField = true;
62329 UA_BrowsePathResult_clear(p: &bpr);
62330 }
62331 if(!subTypeContainField)
62332 result[i] = UA_STATUSCODE_BADNODEIDUNKNOWN;
62333
62334 UA_Array_delete(p: chilTypeNodes, size: chilTypeNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]);
62335
62336 if(result[i] != UA_STATUSCODE_GOOD)
62337 continue;
62338 /*indexRange is defined ? */
62339 if(!UA_String_equal(s1: &eventFilter->selectClauses[i].indexRange,
62340 s2: &UA_STRING_NULL)) {
62341 /* indexRange is parsable ? */
62342 UA_NumericRange numericRange = UA_NUMERICRANGE(s: "");
62343 if(UA_NumericRange_parse(range: &numericRange,
62344 str: eventFilter->selectClauses[i].indexRange) !=
62345 UA_STATUSCODE_GOOD) {
62346 result[i] = UA_STATUSCODE_BADINDEXRANGEINVALID;
62347 continue;
62348 }
62349 UA_free(ptr: numericRange.dimensions);
62350 /* attributeId is value ? */
62351 if(eventFilter->selectClauses[i].attributeId != UA_ATTRIBUTEID_VALUE) {
62352 result[i] = UA_STATUSCODE_BADTYPEMISMATCH;
62353 continue;
62354 }
62355 }
62356 }
62357}
62358
62359/* Initial content filter (where clause) check. Current checks:
62360 * - Number of operands for each (supported) operator */
62361UA_StatusCode
62362UA_Event_staticWhereClauseValidation(UA_Server *server,
62363 const UA_ContentFilter *filter,
62364 UA_ContentFilterResult *result) {
62365 UA_ContentFilterResult_init(p: result);
62366 result->elementResultsSize = filter->elementsSize;
62367 if(result->elementResultsSize == 0)
62368 return UA_STATUSCODE_GOOD;
62369 result->elementResults =
62370 (UA_ContentFilterElementResult *)UA_Array_new(
62371 size: result->elementResultsSize,
62372 type: &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]);
62373 if(!result->elementResults)
62374 return UA_STATUSCODE_BADOUTOFMEMORY;
62375 for(size_t i = 0; i < result->elementResultsSize; ++i) {
62376 UA_ContentFilterElementResult *er = &result->elementResults[i];
62377 UA_ContentFilterElement ef = filter->elements[i];
62378 UA_ContentFilterElementResult_init(p: er);
62379 er->operandStatusCodes =
62380 (UA_StatusCode *)UA_Array_new(
62381 size: ef.filterOperandsSize,
62382 type: &UA_TYPES[UA_TYPES_STATUSCODE]);
62383 er->operandStatusCodesSize = ef.filterOperandsSize;
62384
62385 switch(ef.filterOperator) {
62386 case UA_FILTEROPERATOR_INVIEW:
62387 case UA_FILTEROPERATOR_RELATEDTO: {
62388 /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */
62389 er->statusCode =
62390 UA_STATUSCODE_BADEVENTFILTERINVALID;
62391 break;
62392 }
62393 case UA_FILTEROPERATOR_EQUALS:
62394 case UA_FILTEROPERATOR_GREATERTHAN:
62395 case UA_FILTEROPERATOR_LESSTHAN:
62396 case UA_FILTEROPERATOR_GREATERTHANOREQUAL:
62397 case UA_FILTEROPERATOR_LESSTHANOREQUAL:
62398 case UA_FILTEROPERATOR_LIKE:
62399 case UA_FILTEROPERATOR_CAST:
62400 case UA_FILTEROPERATOR_BITWISEAND:
62401 case UA_FILTEROPERATOR_BITWISEOR: {
62402 if(ef.filterOperandsSize != 2) {
62403 er->statusCode =
62404 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62405 break;
62406 }
62407 er->statusCode = UA_STATUSCODE_GOOD;
62408 break;
62409 }
62410 case UA_FILTEROPERATOR_AND:
62411 case UA_FILTEROPERATOR_OR: {
62412 if(ef.filterOperandsSize != 2) {
62413 er->statusCode =
62414 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62415 break;
62416 }
62417 for(size_t j = 0; j < 2; ++j) {
62418 if(ef.filterOperands[j].content.decoded.type !=
62419 &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) {
62420 er->operandStatusCodes[j] =
62421 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62422 er->statusCode =
62423 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62424 break;
62425 }
62426 if(((UA_ElementOperand *)ef.filterOperands[j]
62427 .content.decoded.data)->index > filter->elementsSize - 1) {
62428 er->operandStatusCodes[j] =
62429 UA_STATUSCODE_BADINDEXRANGEINVALID;
62430 er->statusCode =
62431 UA_STATUSCODE_BADINDEXRANGEINVALID;
62432 break;
62433 }
62434 }
62435 er->statusCode = UA_STATUSCODE_GOOD;
62436 break;
62437 }
62438 case UA_FILTEROPERATOR_ISNULL:
62439 case UA_FILTEROPERATOR_NOT: {
62440 if(ef.filterOperandsSize != 1) {
62441 er->statusCode =
62442 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62443 break;
62444 }
62445 er->statusCode = UA_STATUSCODE_GOOD;
62446 break;
62447 }
62448 case UA_FILTEROPERATOR_INLIST: {
62449 if(ef.filterOperandsSize <= 2) {
62450 er->statusCode =
62451 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62452 break;
62453 }
62454 er->statusCode = UA_STATUSCODE_GOOD;
62455 break;
62456 }
62457 case UA_FILTEROPERATOR_BETWEEN: {
62458 if(ef.filterOperandsSize != 3) {
62459 er->statusCode =
62460 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62461 break;
62462 }
62463 er->statusCode = UA_STATUSCODE_GOOD;
62464 break;
62465 }
62466 case UA_FILTEROPERATOR_OFTYPE: {
62467 if(ef.filterOperandsSize != 1) {
62468 er->statusCode =
62469 UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH;
62470 break;
62471 }
62472 er->operandStatusCodesSize = ef.filterOperandsSize;
62473 if(ef.filterOperands[0].content.decoded.type !=
62474 &UA_TYPES[UA_TYPES_LITERALOPERAND]) {
62475 er->statusCode =
62476 UA_STATUSCODE_BADFILTEROPERANDINVALID;
62477 break;
62478 }
62479
62480 const UA_LiteralOperand *lit = (const UA_LiteralOperand *)
62481 ef.filterOperands[0].content.decoded.data;
62482 if(!UA_Variant_hasScalarType(v: &lit->value, type: &UA_TYPES[UA_TYPES_NODEID])) {
62483 er->statusCode = UA_STATUSCODE_BADFILTEROPERANDINVALID;
62484 break;
62485 }
62486 const UA_NodeId *ofTypeId = (const UA_NodeId*)lit->value.data;
62487
62488 /* Make sure the &pOperand->nodeId is a subtype of BaseEventType */
62489 UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE);
62490 if(!isNodeInTree_singleRef(server, leafNode: ofTypeId, nodeToFind: &baseEventTypeId,
62491 UA_REFERENCETYPEINDEX_HASSUBTYPE)) {
62492 er->statusCode = UA_STATUSCODE_BADNODEIDINVALID;
62493 break;
62494 }
62495 er->statusCode = UA_STATUSCODE_GOOD;
62496 break;
62497 }
62498 default:
62499 er->statusCode =
62500 UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED;
62501 break;
62502 }
62503 }
62504 return UA_STATUSCODE_GOOD;
62505}
62506
62507#endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */
62508
62509/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.h" ****/
62510
62511/* This Source Code Form is subject to the terms of the Mozilla Public
62512 * License, v. 2.0. If a copy of the MPL was not distributed with this
62513 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62514 *
62515 * Copyright 2020 (c) Wind River Systems, Inc.
62516 * Copyright 2020 (c) basysKom GmbH
62517 *
62518 */
62519
62520
62521
62522#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62523
62524#include <openssl/x509.h>
62525#include <openssl/evp.h>
62526
62527_UA_BEGIN_DECLS
62528
62529void saveDataToFile(const char *fileName, const UA_ByteString *str);
62530void UA_Openssl_Init(void);
62531
62532UA_StatusCode
62533UA_copyCertificate(UA_ByteString *dst, const UA_ByteString *src);
62534
62535UA_StatusCode
62536UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(const UA_ByteString *msg,
62537 X509 *publicKeyX509,
62538 const UA_ByteString *signature);
62539UA_StatusCode
62540UA_Openssl_X509_GetCertificateThumbprint(const UA_ByteString *certficate,
62541 UA_ByteString *pThumbprint,
62542 bool bThumbPrint);
62543UA_StatusCode
62544UA_Openssl_RSA_Oaep_Decrypt(UA_ByteString *data,
62545 EVP_PKEY *privateKey);
62546UA_StatusCode
62547UA_Openssl_RSA_OAEP_Encrypt(UA_ByteString *data, /* The data that is encrypted.
62548 The encrypted data will overwrite
62549 the data that was supplied. */
62550 size_t paddingSize, X509 *publicX509);
62551
62552UA_StatusCode
62553UA_Openssl_Random_Key_PSHA256_Derive(const UA_ByteString *secret,
62554 const UA_ByteString *seed,
62555 UA_ByteString *out);
62556
62557UA_StatusCode
62558UA_Openssl_RSA_Public_GetKeyLength(X509 *publicKeyX509, UA_Int32 *keyLen);
62559
62560UA_StatusCode
62561UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(const UA_ByteString *data,
62562 EVP_PKEY *privateKey,
62563 UA_ByteString *outSignature);
62564
62565UA_StatusCode
62566UA_OpenSSL_HMAC_SHA256_Verify(const UA_ByteString *message,
62567 const UA_ByteString *key,
62568 const UA_ByteString *signature);
62569
62570UA_StatusCode
62571UA_OpenSSL_HMAC_SHA256_Sign(const UA_ByteString *message,
62572 const UA_ByteString *key,
62573 UA_ByteString *signature);
62574
62575UA_StatusCode
62576UA_OpenSSL_AES_256_CBC_Decrypt(const UA_ByteString *iv,
62577 const UA_ByteString *key,
62578 UA_ByteString *data /* [in/out]*/);
62579
62580UA_StatusCode
62581UA_OpenSSL_AES_256_CBC_Encrypt(const UA_ByteString *iv,
62582 const UA_ByteString *key,
62583 UA_ByteString *data /* [in/out]*/);
62584
62585UA_StatusCode
62586UA_OpenSSL_X509_compare(const UA_ByteString *cert, const X509 *b);
62587
62588UA_StatusCode
62589UA_Openssl_RSA_Private_GetKeyLength(EVP_PKEY *privateKey,
62590 UA_Int32 *keyLen) ;
62591
62592UA_StatusCode
62593UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify(const UA_ByteString *msg,
62594 X509 *publicKeyX509,
62595 const UA_ByteString *signature);
62596
62597UA_StatusCode
62598UA_Openssl_RSA_PKCS1_V15_SHA1_Sign(const UA_ByteString *message,
62599 EVP_PKEY *privateKey,
62600 UA_ByteString *outSignature);
62601UA_StatusCode
62602UA_Openssl_Random_Key_PSHA1_Derive(const UA_ByteString *secret,
62603 const UA_ByteString *seed,
62604 UA_ByteString *out);
62605UA_StatusCode
62606UA_OpenSSL_HMAC_SHA1_Verify(const UA_ByteString *message,
62607 const UA_ByteString *key,
62608 const UA_ByteString *signature);
62609
62610UA_StatusCode
62611UA_OpenSSL_HMAC_SHA1_Sign(const UA_ByteString *message,
62612 const UA_ByteString *key,
62613 UA_ByteString *signature);
62614
62615UA_StatusCode
62616UA_Openssl_RSA_PKCS1_V15_Decrypt(UA_ByteString *data,
62617 EVP_PKEY *privateKey);
62618
62619UA_StatusCode
62620UA_Openssl_RSA_PKCS1_V15_Encrypt(UA_ByteString *data,
62621 size_t paddingSize,
62622 X509 *publicX509);
62623
62624UA_StatusCode
62625UA_OpenSSL_AES_128_CBC_Decrypt(const UA_ByteString *iv,
62626 const UA_ByteString *key,
62627 UA_ByteString *data /* [in/out]*/);
62628
62629UA_StatusCode
62630UA_OpenSSL_AES_128_CBC_Encrypt(const UA_ByteString *iv,
62631 const UA_ByteString *key,
62632 UA_ByteString *data /* [in/out]*/);
62633
62634EVP_PKEY *
62635UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey);
62636
62637X509 *
62638UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate);
62639
62640X509 *
62641UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate);
62642
62643X509 *
62644UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate);
62645
62646UA_StatusCode
62647UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target);
62648
62649_UA_END_DECLS
62650
62651#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
62652
62653
62654/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_version_abstraction.h" ****/
62655
62656/* This Source Code Form is subject to the terms of the Mozilla Public
62657 * License, v. 2.0. If a copy of the MPL was not distributed with this
62658 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62659 *
62660 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
62661 *
62662 */
62663
62664
62665#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62666
62667#include <openssl/x509.h>
62668
62669#if !defined(OPENSSL_VERSION_NUMBER)
62670#error "OPENSSL_VERSION_NUMBER is not defined."
62671#endif
62672
62673#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
62674#define X509_STORE_CTX_set0_trusted_stack(STORE_CTX, CTX_SKTRUSTED) X509_STORE_CTX_trusted_stack(STORE_CTX, CTX_SKTRUSTED)
62675#endif
62676
62677#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62678#define X509_STORE_CTX_get_check_issued(STORE_CTX) STORE_CTX->check_issued
62679#endif
62680
62681#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62682#define get_pkey_rsa(evp) ((evp)->pkey.rsa)
62683#else
62684#define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp)
62685#endif
62686
62687#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER)
62688#define X509_get0_subject_key_id(PX509_CERT) (const ASN1_OCTET_STRING *)X509_get_ext_d2i(PX509_CERT, NID_subject_key_identifier, NULL, NULL);
62689#endif
62690
62691#endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
62692
62693/**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.c" ****/
62694
62695/* This Source Code Form is subject to the terms of the Mozilla Public
62696 * License, v. 2.0. If a copy of the MPL was not distributed with this
62697 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
62698 *
62699 * Copyright 2020 (c) Wind River Systems, Inc.
62700 * Copyright 2020 (c) basysKom GmbH
62701 * Copyright 2022 (c) Wind River Systems, Inc.
62702 */
62703
62704/*
62705modification history
62706--------------------
6270701feb20,lan written
62708*/
62709
62710
62711#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
62712
62713#include <openssl/rsa.h>
62714#include <openssl/evp.h>
62715#include <openssl/err.h>
62716#include <openssl/sha.h>
62717#include <openssl/x509.h>
62718#include <openssl/hmac.h>
62719#include <openssl/aes.h>
62720#include <openssl/pem.h>
62721
62722
62723#define SHA1_DIGEST_LENGTH 20 /* 160 bits */
62724#define RSA_DECRYPT_BUFFER_LENGTH 2048 /* bytes */
62725
62726
62727/** P_SHA256 Context */
62728typedef struct UA_Openssl_P_SHA256_Ctx_ {
62729 size_t seedLen;
62730 size_t secretLen;
62731 UA_Byte A[32]; /* 32 bytes of SHA256 output */
62732 /*
62733 char seed[seedLen];
62734 char secret[secretLen]; */
62735} UA_Openssl_P_SHA256_Ctx;
62736
62737#define UA_Openssl_P_SHA256_SEED(ctx) ((ctx)->A+32)
62738#define UA_Openssl_P_SHA256_SECRET(ctx) ((ctx)->A+32+(ctx)->seedLen)
62739
62740/** P_SHA1 Context */
62741typedef struct UA_Openssl_P_SHA1_Ctx_ {
62742 size_t seedLen;
62743 size_t secretLen;
62744 UA_Byte A[SHA1_DIGEST_LENGTH]; /* 20 bytes of SHA1 output */
62745 /*
62746 char seed[seedLen];
62747 char secret[secretLen]; */
62748} UA_Openssl_P_SHA1_Ctx;
62749
62750#define UA_Openssl_P_SHA1_SEED(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH)
62751#define UA_Openssl_P_SHA1_SECRET(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH +(ctx)->seedLen)
62752
62753void
62754UA_Openssl_Init (void) {
62755 /* VxWorks7 has initialized the openssl. */
62756#ifndef __VXWORKS__
62757 static UA_Int16 bInit = 0;
62758 if (bInit == 1)
62759 return;
62760#if defined(OPENSSL_API_COMPAT) && (OPENSSL_API_COMPAT < 0x10100000L)
62761 /* only needed, if OpenSSL < V1.1 */
62762 OpenSSL_add_all_algorithms ();
62763 ERR_load_crypto_strings ();
62764#endif
62765 bInit = 1;
62766#endif
62767}
62768
62769static int UA_OpenSSL_RSA_Key_Size (EVP_PKEY * key){
62770#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
62771 return EVP_PKEY_get_size (pkey: key);
62772#else
62773 return RSA_size (get_pkey_rsa(key));
62774#endif
62775}
62776
62777/* UA_copyCertificate - allocalte the buffer, copy the certificate and
62778 * add a NULL to the end
62779 */
62780
62781UA_StatusCode
62782UA_copyCertificate (UA_ByteString * dst,
62783 const UA_ByteString * src) {
62784 UA_StatusCode retval = UA_ByteString_allocBuffer (bs: dst, length: src->length + 1);
62785 if (retval != UA_STATUSCODE_GOOD)
62786 return retval;
62787 (void) memcpy (dest: dst->data, src: src->data, n: src->length);
62788 dst->data[dst->length - 1] = '\0';
62789 dst->length--;
62790
62791 return UA_STATUSCODE_GOOD;
62792}
62793
62794static UA_StatusCode
62795UA_OpenSSL_RSA_Public_Verify (const UA_ByteString * message,
62796 const EVP_MD * evpMd,
62797 X509 * publicKeyX509,
62798 UA_Int16 padding,
62799 const UA_ByteString * signature
62800 ) {
62801 EVP_MD_CTX * mdctx = NULL;
62802 int opensslRet;
62803 EVP_PKEY_CTX * evpKeyCtx;
62804 EVP_PKEY * evpPublicKey = NULL;
62805 UA_StatusCode ret;
62806
62807 mdctx = EVP_MD_CTX_create ();
62808 if (mdctx == NULL) {
62809 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62810 goto errout;
62811 }
62812 evpPublicKey = X509_get_pubkey (x: publicKeyX509);
62813 if (evpPublicKey == NULL) {
62814 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62815 goto errout;
62816 }
62817
62818 opensslRet = EVP_DigestVerifyInit (ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, NULL,
62819 pkey: evpPublicKey);
62820 if (opensslRet != 1) {
62821 ret = UA_STATUSCODE_BADINTERNALERROR;
62822 goto errout;
62823 }
62824 EVP_PKEY_CTX_set_rsa_padding (ctx: evpKeyCtx, pad_mode: padding);
62825 opensslRet = EVP_DigestVerifyUpdate (ctx: mdctx, data: message->data, dsize: message->length);
62826 if (opensslRet != 1) {
62827 ret = UA_STATUSCODE_BADINTERNALERROR;
62828 goto errout;
62829 }
62830 opensslRet = EVP_DigestVerifyFinal(ctx: mdctx, sig: signature->data, siglen: signature->length);
62831 if (opensslRet != 1) {
62832 ret = UA_STATUSCODE_BADINTERNALERROR;
62833 goto errout;
62834 }
62835
62836 ret = UA_STATUSCODE_GOOD;
62837errout:
62838 if (evpPublicKey != NULL) {
62839 EVP_PKEY_free (pkey: evpPublicKey);
62840 }
62841 if (mdctx != NULL) {
62842 EVP_MD_CTX_destroy (mdctx);
62843 }
62844 return ret;
62845}
62846
62847UA_StatusCode
62848UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (const UA_ByteString * msg,
62849 X509 * publicKeyX509,
62850 const UA_ByteString * signature
62851 ) {
62852 return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha256(), publicKeyX509,
62853 NID_sha256, signature);
62854}
62855
62856/* Get certificate thumbprint, and allocate the buffer. */
62857
62858UA_StatusCode
62859UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate,
62860 UA_ByteString * pThumbprint,
62861 bool bThumbPrint) {
62862 if (bThumbPrint) {
62863 pThumbprint->length = SHA_DIGEST_LENGTH;
62864 UA_StatusCode ret = UA_ByteString_allocBuffer (bs: pThumbprint, length: pThumbprint->length);
62865 if (ret != UA_STATUSCODE_GOOD) {
62866 return ret;
62867 }
62868 }
62869 else {
62870 if (pThumbprint->length != SHA_DIGEST_LENGTH) {
62871 return UA_STATUSCODE_BADINTERNALERROR;
62872 }
62873 }
62874 X509 * x509Certificate = UA_OpenSSL_LoadCertificate(certificate: certficate);
62875
62876 if (x509Certificate == NULL) {
62877 if (bThumbPrint) {
62878 UA_ByteString_clear (p: pThumbprint);
62879 }
62880 return UA_STATUSCODE_BADINTERNALERROR;
62881 }
62882
62883 if (X509_digest (data: x509Certificate, type: EVP_sha1(), md: pThumbprint->data, NULL)
62884 != 1) {
62885 if (bThumbPrint) {
62886 UA_ByteString_clear (p: pThumbprint);
62887 }
62888 return UA_STATUSCODE_BADINTERNALERROR;
62889 }
62890 X509_free(a: x509Certificate);
62891
62892 return UA_STATUSCODE_GOOD;
62893}
62894
62895static UA_StatusCode
62896UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data,
62897 EVP_PKEY * privateKey,
62898 UA_Int16 padding) {
62899 if (data == NULL || privateKey == NULL) {
62900 return UA_STATUSCODE_BADINVALIDARGUMENT;
62901 }
62902
62903 if (privateKey == NULL) {
62904 return UA_STATUSCODE_BADINVALIDARGUMENT;
62905 }
62906
62907 size_t keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: privateKey);
62908 size_t cipherOffset = 0;
62909 size_t outOffset = 0;
62910 unsigned char buf[RSA_DECRYPT_BUFFER_LENGTH];
62911 size_t decryptedBytes;
62912 EVP_PKEY_CTX * ctx;
62913 int opensslRet;
62914
62915 ctx = EVP_PKEY_CTX_new (pkey: privateKey, NULL);
62916 if (ctx == NULL) {
62917 return UA_STATUSCODE_BADOUTOFMEMORY;
62918 }
62919 opensslRet = EVP_PKEY_decrypt_init (ctx);
62920 if (opensslRet != 1)
62921 {
62922 EVP_PKEY_CTX_free (ctx);
62923 return UA_STATUSCODE_BADINTERNALERROR;
62924 }
62925 opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding);
62926 if (opensslRet != 1) {
62927 EVP_PKEY_CTX_free (ctx);
62928 return UA_STATUSCODE_BADINTERNALERROR;
62929 }
62930
62931 while (cipherOffset < data->length) {
62932 decryptedBytes = RSA_DECRYPT_BUFFER_LENGTH;
62933 opensslRet = EVP_PKEY_decrypt (ctx,
62934 out: buf, /* where to decrypt */
62935 outlen: &decryptedBytes,
62936 in: data->data + cipherOffset, /* what to decrypt */
62937 inlen: keySize
62938 );
62939 if (opensslRet != 1) {
62940 EVP_PKEY_CTX_free (ctx);
62941 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
62942 }
62943 (void) memcpy(dest: data->data + outOffset, src: buf, n: decryptedBytes);
62944 cipherOffset += (size_t) keySize;
62945 outOffset += decryptedBytes;
62946 }
62947 data->length = outOffset;
62948 EVP_PKEY_CTX_free (ctx);
62949
62950 return UA_STATUSCODE_GOOD;
62951}
62952
62953UA_StatusCode
62954UA_Openssl_RSA_Oaep_Decrypt (UA_ByteString * data,
62955 EVP_PKEY * privateKey) {
62956 return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
62957 RSA_PKCS1_OAEP_PADDING);
62958}
62959
62960static UA_StatusCode
62961UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message,
62962 X509 * publicX509,
62963 UA_Int16 padding,
62964 size_t paddingSize,
62965 UA_ByteString * encrypted) {
62966 EVP_PKEY_CTX * ctx = NULL;
62967 EVP_PKEY * evpPublicKey = NULL;
62968 int opensslRet;
62969 UA_StatusCode ret;
62970 size_t encryptedTextLen = 0;
62971 size_t dataPos = 0;
62972 size_t encryptedPos = 0;
62973 size_t bytesToEncrypt = 0;
62974 size_t encryptedBlockSize = 0;
62975 size_t keySize = 0;
62976
62977 evpPublicKey = X509_get_pubkey (x: publicX509);
62978 if (evpPublicKey == NULL) {
62979 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62980 goto errout;
62981 }
62982 ctx = EVP_PKEY_CTX_new (pkey: evpPublicKey, NULL);
62983 if (ctx == NULL) {
62984 ret = UA_STATUSCODE_BADOUTOFMEMORY;
62985 goto errout;
62986 }
62987 opensslRet = EVP_PKEY_encrypt_init (ctx);
62988 if (opensslRet != 1) {
62989 ret = UA_STATUSCODE_BADINTERNALERROR;
62990 goto errout;
62991 }
62992 opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding);
62993 if (opensslRet != 1) {
62994 ret = UA_STATUSCODE_BADINTERNALERROR;
62995 goto errout;
62996 }
62997
62998 /* get the encrypted block size */
62999
63000 keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: evpPublicKey);
63001 if (keySize == 0) {
63002 ret = UA_STATUSCODE_BADINTERNALERROR;
63003 goto errout;
63004 }
63005
63006 switch (padding) {
63007 case RSA_PKCS1_OAEP_PADDING:
63008 case RSA_PKCS1_PADDING:
63009 if (keySize <= paddingSize) {
63010 ret = UA_STATUSCODE_BADINTERNALERROR;
63011 goto errout;
63012 }
63013 encryptedBlockSize = keySize - paddingSize;
63014 break;
63015 default:
63016 ret = UA_STATUSCODE_BADNOTSUPPORTED;
63017 goto errout;
63018 break;
63019 }
63020
63021 /* encrypt in reverse order so that [data] may alias [encrypted] */
63022
63023 dataPos = message->length;
63024 encryptedPos = ((dataPos - 1) / encryptedBlockSize + 1) * keySize;
63025 bytesToEncrypt = (dataPos - 1) % encryptedBlockSize + 1;
63026 encryptedTextLen = encryptedPos;
63027
63028 while (dataPos > 0) {
63029 size_t outlen = keySize;
63030 encryptedPos -= keySize;
63031 dataPos -= bytesToEncrypt;
63032 opensslRet = EVP_PKEY_encrypt (ctx, out: encrypted->data + encryptedPos, outlen: &outlen,
63033 in: message->data + dataPos, inlen: bytesToEncrypt);
63034
63035 if (opensslRet != 1) {
63036 ret = UA_STATUSCODE_BADINTERNALERROR;
63037 goto errout;
63038 }
63039 bytesToEncrypt = encryptedBlockSize;
63040 }
63041 encrypted->length = encryptedTextLen;
63042
63043 ret = UA_STATUSCODE_GOOD;
63044errout:
63045 if (evpPublicKey != NULL) {
63046 EVP_PKEY_free (pkey: evpPublicKey);
63047 }
63048 if (ctx != NULL) {
63049 EVP_PKEY_CTX_free (ctx);
63050 }
63051 return ret;
63052}
63053
63054UA_StatusCode
63055UA_Openssl_RSA_OAEP_Encrypt (UA_ByteString * data,
63056 size_t paddingSize,
63057 X509 * publicX509) {
63058 UA_ByteString message;
63059 UA_StatusCode ret;
63060
63061 ret = UA_ByteString_copy (src: data, dst: &message);
63062 if (ret != UA_STATUSCODE_GOOD) {
63063 return ret;
63064 }
63065 ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509,
63066 RSA_PKCS1_OAEP_PADDING,
63067 paddingSize,
63068 encrypted: data);
63069 UA_ByteString_clear (p: &message);
63070 return ret;
63071}
63072
63073static UA_Openssl_P_SHA256_Ctx *
63074P_SHA256_Ctx_Create (const UA_ByteString * secret,
63075 const UA_ByteString * seed) {
63076 size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA256_Ctx) + secret->length +
63077 seed->length;
63078 UA_Openssl_P_SHA256_Ctx * ctx = (UA_Openssl_P_SHA256_Ctx *) UA_malloc (size: size);
63079 if (ctx == NULL) {
63080 return NULL;
63081 }
63082 ctx->secretLen = secret->length;
63083 ctx->seedLen = seed->length;
63084 (void) memcpy (UA_Openssl_P_SHA256_SEED(ctx), src: seed->data, n: seed->length);
63085 (void) memcpy (UA_Openssl_P_SHA256_SECRET(ctx), src: secret->data, n: secret->length);
63086 /* A(0) = seed
63087 A(n) = HMAC_HASH(secret, A(n-1)) */
63088
63089 if (HMAC (evp_md: EVP_sha256(), key: secret->data, key_len: (int) secret->length, data: seed->data,
63090 data_len: seed->length, md: ctx->A, NULL) == NULL) {
63091 UA_free (ptr: ctx);
63092 return NULL;
63093 }
63094
63095 return ctx;
63096}
63097
63098static UA_StatusCode
63099P_SHA256_Hash_Generate (UA_Openssl_P_SHA256_Ctx * ctx,
63100 UA_Byte * pHas
63101 ) {
63102 /* Calculate P_SHA256(n) = HMAC_SHA256(secret, A(n)+seed) */
63103 if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen,
63104 data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) {
63105 return UA_STATUSCODE_BADINTERNALERROR;
63106 }
63107
63108 /* Calculate A(n) = HMAC_SHA256(secret, A(n-1)) */
63109 if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen,
63110 data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) {
63111 return UA_STATUSCODE_BADINTERNALERROR;
63112 }
63113 return UA_STATUSCODE_GOOD;
63114}
63115
63116UA_StatusCode
63117UA_Openssl_Random_Key_PSHA256_Derive (const UA_ByteString * secret,
63118 const UA_ByteString * seed,
63119 UA_ByteString * out) {
63120 size_t keyLen = out->length;
63121 size_t iter = keyLen/32 + ((keyLen%32)?1:0);
63122 size_t bufferLen = iter * 32;
63123 size_t i;
63124 UA_StatusCode st;
63125
63126 UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen);
63127 if (pBuffer == NULL) {
63128 return UA_STATUSCODE_BADOUTOFMEMORY;
63129 }
63130
63131 UA_Openssl_P_SHA256_Ctx * ctx = P_SHA256_Ctx_Create (secret, seed);
63132 if (ctx == NULL) {
63133 UA_free (ptr: pBuffer);
63134 return UA_STATUSCODE_BADOUTOFMEMORY;
63135 }
63136
63137 for (i = 0; i < iter; i++) {
63138 st = P_SHA256_Hash_Generate (ctx, pHas: pBuffer + (i * 32));
63139 if (st != UA_STATUSCODE_GOOD) {
63140 UA_free (ptr: pBuffer);
63141 UA_free (ptr: ctx);
63142 return st;
63143 }
63144 }
63145
63146 (void) memcpy (dest: out->data, src: pBuffer, n: keyLen);
63147 UA_free (ptr: pBuffer);
63148 UA_free (ptr: ctx);
63149 return UA_STATUSCODE_GOOD;
63150}
63151
63152/* return the key bytes */
63153UA_StatusCode
63154UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509,
63155 UA_Int32 * keyLen) {
63156 EVP_PKEY * evpKey = X509_get_pubkey (x: publicKeyX509);
63157 if (evpKey == NULL) {
63158 return UA_STATUSCODE_BADINTERNALERROR;
63159 }
63160 *keyLen = UA_OpenSSL_RSA_Key_Size (key: evpKey);
63161
63162 EVP_PKEY_free (pkey: evpKey);
63163
63164 return UA_STATUSCODE_GOOD;
63165}
63166
63167UA_StatusCode
63168UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey,
63169 UA_Int32 * keyLen) {
63170 if (privateKey == NULL) {
63171 return UA_STATUSCODE_BADINVALIDARGUMENT;
63172 }
63173 *keyLen = UA_OpenSSL_RSA_Key_Size (key: privateKey);
63174
63175 return UA_STATUSCODE_GOOD;
63176}
63177
63178static UA_StatusCode
63179UA_Openssl_RSA_Private_Sign (const UA_ByteString * message,
63180 EVP_PKEY * privateKey,
63181 const EVP_MD * evpMd,
63182 UA_Int16 padding,
63183 UA_ByteString * outSignature) {
63184 EVP_MD_CTX * mdctx = NULL;
63185 int opensslRet;
63186 EVP_PKEY_CTX * evpKeyCtx;
63187 UA_StatusCode ret;
63188
63189 mdctx = EVP_MD_CTX_create ();
63190 if (mdctx == NULL) {
63191 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63192 goto errout;
63193 }
63194
63195 if (privateKey == NULL) {
63196 return UA_STATUSCODE_BADINVALIDARGUMENT;
63197 }
63198 opensslRet = EVP_DigestSignInit (ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, NULL, pkey: privateKey);
63199 if (opensslRet != 1) {
63200 ret = UA_STATUSCODE_BADINTERNALERROR;
63201 goto errout;
63202 }
63203 EVP_PKEY_CTX_set_rsa_padding (ctx: evpKeyCtx, pad_mode: padding);
63204
63205 opensslRet = EVP_DigestSignUpdate (ctx: mdctx, data: message->data, dsize: message->length);
63206 if (opensslRet != 1) {
63207 ret = UA_STATUSCODE_BADINTERNALERROR;
63208 goto errout;
63209 }
63210 opensslRet = EVP_DigestSignFinal (ctx: mdctx, sigret: outSignature->data, siglen: &outSignature->length);
63211 if (opensslRet != 1) {
63212 ret = UA_STATUSCODE_BADINTERNALERROR;
63213 goto errout;
63214 }
63215
63216 ret = UA_STATUSCODE_GOOD;
63217errout:
63218 if (mdctx != NULL) {
63219 EVP_MD_CTX_destroy (mdctx);
63220 }
63221 return ret;
63222}
63223
63224UA_StatusCode
63225UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (const UA_ByteString * message,
63226 EVP_PKEY * privateKey,
63227 UA_ByteString * outSignature) {
63228 return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha256(),
63229 NID_sha256, outSignature);
63230}
63231
63232UA_StatusCode
63233UA_OpenSSL_HMAC_SHA256_Verify (const UA_ByteString * message,
63234 const UA_ByteString * key,
63235 const UA_ByteString * signature
63236 ) {
63237 unsigned char buf[SHA256_DIGEST_LENGTH] = {0};
63238 UA_ByteString mac = {SHA256_DIGEST_LENGTH, buf};
63239
63240 if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length,
63241 md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) {
63242 return UA_STATUSCODE_BADINTERNALERROR;
63243 }
63244 if (UA_ByteString_equal (string1: signature, string2: &mac)) {
63245 return UA_STATUSCODE_GOOD;
63246 }
63247 else {
63248 return UA_STATUSCODE_BADINTERNALERROR;
63249 }
63250}
63251
63252UA_StatusCode
63253UA_OpenSSL_HMAC_SHA256_Sign (const UA_ByteString * message,
63254 const UA_ByteString * key,
63255 UA_ByteString * signature
63256 ) {
63257 if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data,
63258 data_len: message->length,
63259 md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) {
63260 return UA_STATUSCODE_BADINTERNALERROR;
63261 }
63262 return UA_STATUSCODE_GOOD;
63263}
63264
63265static UA_StatusCode
63266UA_OpenSSL_Decrypt (const UA_ByteString * iv,
63267 const UA_ByteString * key,
63268 const EVP_CIPHER * cipherAlg,
63269 UA_ByteString * data /* [in/out]*/) {
63270 UA_ByteString ivCopy = {0, NULL};
63271 UA_ByteString cipherTxt = {0, NULL};
63272 EVP_CIPHER_CTX * ctx = NULL;
63273 UA_StatusCode ret;
63274 int opensslRet;
63275 int outLen;
63276 int tmpLen;
63277
63278 /* copy the IV because the AES_cbc_encrypt function overwrites it. */
63279
63280 ret = UA_ByteString_copy (src: iv, dst: &ivCopy);
63281 if (ret != UA_STATUSCODE_GOOD) {
63282 goto errout;
63283 }
63284
63285 ret = UA_ByteString_copy (src: data, dst: &cipherTxt);
63286 if (ret != UA_STATUSCODE_GOOD) {
63287 goto errout;
63288 }
63289
63290 ctx = EVP_CIPHER_CTX_new ();
63291 if (ctx == NULL) {
63292 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63293 goto errout;
63294 }
63295
63296 /* call EVP_* to decrypt */
63297
63298 opensslRet = EVP_DecryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data);
63299 if (opensslRet != 1) {
63300 ret = UA_STATUSCODE_BADINTERNALERROR;
63301 goto errout;
63302 }
63303 /* EVP_DecryptFinal() will return an error code if padding is enabled
63304 * and the final block is not correctly formatted.
63305 */
63306 EVP_CIPHER_CTX_set_padding (c: ctx, pad: 0);
63307 opensslRet = EVP_DecryptUpdate (ctx, out: data->data, outl: &outLen,
63308 in: cipherTxt.data, inl: (int) cipherTxt.length);
63309 if (opensslRet != 1) {
63310 ret = UA_STATUSCODE_BADINTERNALERROR;
63311 goto errout;
63312 }
63313 opensslRet = EVP_DecryptFinal_ex (ctx, outm: data->data + outLen, outl: &tmpLen);
63314 if (opensslRet != 1) {
63315 ret = UA_STATUSCODE_BADINTERNALERROR;
63316 goto errout;
63317 }
63318 outLen += tmpLen;
63319 data->length = (size_t) outLen;
63320 ret = UA_STATUSCODE_GOOD;
63321
63322errout:
63323 UA_ByteString_clear (p: &ivCopy);
63324 UA_ByteString_clear (p: &cipherTxt);
63325 if (ctx != NULL) {
63326 EVP_CIPHER_CTX_free(c: ctx);
63327 }
63328 return ret;
63329}
63330
63331static UA_StatusCode
63332UA_OpenSSL_Encrypt (const UA_ByteString * iv,
63333 const UA_ByteString * key,
63334 const EVP_CIPHER * cipherAlg,
63335 UA_ByteString * data /* [in/out]*/
63336 ) {
63337
63338 UA_ByteString ivCopy = {0, NULL};
63339 UA_ByteString plainTxt = {0, NULL};
63340 EVP_CIPHER_CTX * ctx = NULL;
63341 UA_StatusCode ret;
63342 int opensslRet;
63343 int outLen;
63344 int tmpLen;
63345
63346 /* copy the IV because the AES_cbc_encrypt function overwrites it. */
63347
63348 ret = UA_ByteString_copy (src: iv, dst: &ivCopy);
63349 if (ret != UA_STATUSCODE_GOOD) {
63350 goto errout;
63351 }
63352
63353 ret = UA_ByteString_copy (src: data, dst: &plainTxt);
63354 if (ret != UA_STATUSCODE_GOOD) {
63355 goto errout;
63356 }
63357
63358 ctx = EVP_CIPHER_CTX_new ();
63359 if (ctx == NULL) {
63360 ret = UA_STATUSCODE_BADOUTOFMEMORY;
63361 goto errout;
63362 }
63363
63364 /* call EVP_* to encrypt */
63365
63366 opensslRet = EVP_EncryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data);
63367 if (opensslRet != 1) {
63368 ret = UA_STATUSCODE_BADINTERNALERROR;
63369 goto errout;
63370 }
63371
63372 /* Disable padding. Padding is done in the stack before calling encryption.
63373 * Ensure that we have a multiple of the block size */
63374 if(data->length % (size_t)EVP_CIPHER_CTX_block_size(ctx)) {
63375 ret = UA_STATUSCODE_BADINTERNALERROR;
63376 goto errout;
63377 }
63378 opensslRet = EVP_CIPHER_CTX_set_padding(c: ctx, pad: 0);
63379 if (opensslRet != 1) {
63380 ret = UA_STATUSCODE_BADINTERNALERROR;
63381 goto errout;
63382 }
63383
63384 /* Encrypt the data */
63385 opensslRet = EVP_EncryptUpdate (ctx, out: data->data, outl: &outLen,
63386 in: plainTxt.data, inl: (int) plainTxt.length);
63387 if (opensslRet != 1) {
63388 ret = UA_STATUSCODE_BADINTERNALERROR;
63389 goto errout;
63390 }
63391
63392 /* Encrypt-final does nothing as padding is disabled */
63393 opensslRet = EVP_EncryptFinal_ex(ctx, out: data->data + outLen, outl: &tmpLen);
63394 if (opensslRet != 1) {
63395 ret = UA_STATUSCODE_BADINTERNALERROR;
63396 goto errout;
63397 }
63398 outLen += tmpLen;
63399 data->length = (size_t) outLen;
63400 ret = UA_STATUSCODE_GOOD;
63401
63402errout:
63403 UA_ByteString_clear (p: &ivCopy);
63404 UA_ByteString_clear (p: &plainTxt);
63405 if (ctx != NULL) {
63406 EVP_CIPHER_CTX_free(c: ctx);
63407 }
63408 return ret;
63409}
63410
63411UA_StatusCode
63412UA_OpenSSL_AES_256_CBC_Decrypt (const UA_ByteString * iv,
63413 const UA_ByteString * key,
63414 UA_ByteString * data /* [in/out]*/
63415 ) {
63416 return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data);
63417}
63418
63419UA_StatusCode
63420UA_OpenSSL_AES_256_CBC_Encrypt (const UA_ByteString * iv,
63421 const UA_ByteString * key,
63422 UA_ByteString * data /* [in/out]*/
63423 ) {
63424 return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data);
63425}
63426
63427UA_StatusCode
63428UA_OpenSSL_X509_compare (const UA_ByteString * cert,
63429 const X509 * bcert) {
63430 X509 * acert = UA_OpenSSL_LoadCertificate(certificate: cert);
63431 if (acert == NULL) {
63432 return UA_STATUSCODE_BADCERTIFICATEINVALID;
63433 }
63434 int opensslRet = X509_cmp (a: acert, b: bcert);
63435 X509_free (a: acert);
63436
63437 if (opensslRet == 0)
63438 return UA_STATUSCODE_GOOD;
63439 return UA_STATUSCODE_UNCERTAINSUBNORMAL;
63440}
63441
63442UA_StatusCode
63443UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (const UA_ByteString * msg,
63444 X509 * publicKeyX509,
63445 const UA_ByteString * signature) {
63446 return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha1(), publicKeyX509,
63447 NID_sha1, signature);
63448}
63449
63450UA_StatusCode
63451UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (const UA_ByteString * message,
63452 EVP_PKEY * privateKey,
63453 UA_ByteString * outSignature) {
63454 return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha1(),
63455 NID_sha1, outSignature);
63456}
63457
63458static UA_Openssl_P_SHA1_Ctx *
63459P_SHA1_Ctx_Create (const UA_ByteString * secret,
63460 const UA_ByteString * seed) {
63461 size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA1_Ctx) + secret->length +
63462 seed->length;
63463 UA_Openssl_P_SHA1_Ctx * ctx = (UA_Openssl_P_SHA1_Ctx *) UA_malloc (size: size);
63464 if (ctx == NULL) {
63465 return NULL;
63466 }
63467
63468 ctx->secretLen = secret->length;
63469 ctx->seedLen = seed->length;
63470 (void) memcpy (UA_Openssl_P_SHA1_SEED(ctx), src: seed->data, n: seed->length);
63471 (void) memcpy (UA_Openssl_P_SHA1_SECRET(ctx), src: secret->data, n: secret->length);
63472 /* A(0) = seed
63473 A(n) = HMAC_HASH(secret, A(n-1)) */
63474
63475 if (HMAC (evp_md: EVP_sha1(), key: secret->data, key_len: (int) secret->length, data: seed->data,
63476 data_len: seed->length, md: ctx->A, NULL) == NULL) {
63477 UA_free (ptr: ctx);
63478 return NULL;
63479 }
63480
63481 return ctx;
63482}
63483
63484static UA_StatusCode
63485P_SHA1_Hash_Generate (UA_Openssl_P_SHA1_Ctx * ctx,
63486 UA_Byte * pHas
63487 ) {
63488 /* Calculate P_SHA1(n) = HMAC_SHA1(secret, A(n)+seed) */
63489 if (HMAC (evp_md: EVP_sha1 (), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen,
63490 data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) {
63491 return UA_STATUSCODE_BADINTERNALERROR;
63492 }
63493
63494 /* Calculate A(n) = HMAC_SHA1(secret, A(n-1)) */
63495 if (HMAC (evp_md: EVP_sha1(), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen,
63496 data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) {
63497 return UA_STATUSCODE_BADINTERNALERROR;
63498 }
63499 return UA_STATUSCODE_GOOD;
63500}
63501
63502UA_StatusCode
63503UA_Openssl_Random_Key_PSHA1_Derive (const UA_ByteString * secret,
63504 const UA_ByteString * seed,
63505 UA_ByteString * out) {
63506 size_t keyLen = out->length;
63507 size_t iter = keyLen / SHA1_DIGEST_LENGTH + ((keyLen % SHA1_DIGEST_LENGTH)?1:0);
63508 size_t bufferLen = iter * SHA1_DIGEST_LENGTH;
63509 UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen);
63510 if (pBuffer == NULL) {
63511 return UA_STATUSCODE_BADOUTOFMEMORY;
63512 }
63513
63514 UA_Openssl_P_SHA1_Ctx * ctx = P_SHA1_Ctx_Create (secret, seed);
63515 if (ctx == NULL) {
63516 UA_free (ptr: pBuffer);
63517 return UA_STATUSCODE_BADOUTOFMEMORY;
63518 }
63519
63520 size_t i;
63521 UA_StatusCode st;
63522
63523 for (i = 0; i < iter; i++) {
63524 st = P_SHA1_Hash_Generate (ctx, pHas: pBuffer + (i * SHA1_DIGEST_LENGTH));
63525 if (st != UA_STATUSCODE_GOOD) {
63526 UA_free (ptr: pBuffer);
63527 UA_free (ptr: ctx);
63528 return st;
63529 }
63530 }
63531
63532 (void) memcpy (dest: out->data, src: pBuffer, n: keyLen);
63533 UA_free (ptr: pBuffer);
63534 UA_free (ptr: ctx);
63535
63536 return UA_STATUSCODE_GOOD;
63537}
63538
63539UA_StatusCode
63540UA_OpenSSL_HMAC_SHA1_Verify (const UA_ByteString * message,
63541 const UA_ByteString * key,
63542 const UA_ByteString * signature
63543 ) {
63544 unsigned char buf[SHA1_DIGEST_LENGTH] = {0};
63545 UA_ByteString mac = {SHA1_DIGEST_LENGTH, buf};
63546
63547 if(HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length,
63548 md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) {
63549 return UA_STATUSCODE_BADINTERNALERROR;
63550 }
63551 if (UA_ByteString_equal (string1: signature, string2: &mac)) {
63552 return UA_STATUSCODE_GOOD;
63553 }
63554 else {
63555 return UA_STATUSCODE_BADINTERNALERROR;
63556 }
63557}
63558
63559UA_StatusCode
63560UA_OpenSSL_HMAC_SHA1_Sign (const UA_ByteString * message,
63561 const UA_ByteString * key,
63562 UA_ByteString * signature
63563 ) {
63564 if (HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data,
63565 data_len: message->length,
63566 md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) {
63567 return UA_STATUSCODE_BADINTERNALERROR;
63568 }
63569 return UA_STATUSCODE_GOOD;
63570}
63571
63572UA_StatusCode
63573UA_Openssl_RSA_PKCS1_V15_Decrypt (UA_ByteString * data,
63574 EVP_PKEY * privateKey) {
63575 return UA_Openssl_RSA_Private_Decrypt (data, privateKey,
63576 RSA_PKCS1_PADDING);
63577}
63578
63579UA_StatusCode
63580UA_Openssl_RSA_PKCS1_V15_Encrypt (UA_ByteString * data,
63581 size_t paddingSize,
63582 X509 * publicX509) {
63583 UA_ByteString message;
63584 UA_StatusCode ret = UA_ByteString_copy (src: data, dst: &message);
63585 if (ret != UA_STATUSCODE_GOOD) {
63586 return ret;
63587 }
63588 ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509,
63589 RSA_PKCS1_PADDING,
63590 paddingSize,
63591 encrypted: data);
63592 UA_ByteString_clear (p: &message);
63593 return ret;
63594}
63595
63596UA_StatusCode
63597UA_OpenSSL_AES_128_CBC_Decrypt (const UA_ByteString * iv,
63598 const UA_ByteString * key,
63599 UA_ByteString * data /* [in/out]*/
63600 ) {
63601 return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data);
63602}
63603
63604UA_StatusCode
63605UA_OpenSSL_AES_128_CBC_Encrypt (const UA_ByteString * iv,
63606 const UA_ByteString * key,
63607 UA_ByteString * data /* [in/out]*/
63608 ) {
63609 return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data);
63610}
63611
63612EVP_PKEY *
63613UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey) {
63614 const unsigned char * pkData = privateKey->data;
63615 long len = (long) privateKey->length;
63616 if(len == 0)
63617 return NULL;
63618
63619 EVP_PKEY *result = NULL;
63620
63621 if (len > 1 && pkData[0] == 0x30 && pkData[1] == 0x82) { // Magic number for DER encoded keys
63622 result = d2i_PrivateKey(EVP_PKEY_RSA, NULL,
63623 pp: &pkData, length: len);
63624 } else {
63625 BIO *bio = NULL;
63626 bio = BIO_new_mem_buf(buf: (void *) privateKey->data, len: (int) privateKey->length);
63627 result = PEM_read_bio_PrivateKey(out: bio, NULL, NULL, NULL);
63628 BIO_free(a: bio);
63629 }
63630
63631 return result;
63632}
63633
63634X509 *
63635UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate) {
63636 X509 * result = NULL;
63637 const unsigned char *pData = certificate->data;
63638
63639 if (certificate->length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
63640 result = UA_OpenSSL_LoadDerCertificate(certificate);
63641 } else {
63642 result = UA_OpenSSL_LoadPemCertificate(certificate);
63643 }
63644
63645 return result;
63646}
63647
63648X509 *
63649UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate) {
63650 const unsigned char *pData = certificate->data;
63651 return d2i_X509(NULL, in: &pData, len: (long) certificate->length);
63652}
63653
63654X509 *
63655UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate) {
63656 X509 * result = NULL;
63657
63658 BIO* bio = NULL;
63659 bio = BIO_new_mem_buf(buf: (void *) certificate->data, len: (int) certificate->length);
63660 result = PEM_read_bio_X509(out: bio, NULL, NULL, NULL);
63661 BIO_free(a: bio);
63662
63663 return result;
63664}
63665
63666UA_StatusCode
63667UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target) {
63668 X509 *cert = UA_OpenSSL_LoadCertificate(certificate);
63669
63670 if (!cert) {
63671 UA_ByteString_init(p: target);
63672 return UA_STATUSCODE_BADINVALIDARGUMENT;
63673 }
63674
63675 unsigned char *derData = NULL;
63676 int length = i2d_X509(a: cert, out: &derData);
63677 X509_free(a: cert);
63678
63679 if (length > 0) {
63680 UA_ByteString temp;
63681 temp.length = (size_t) length;
63682 temp.data = derData;
63683 UA_ByteString_copy(src: &temp, dst: target);
63684 OPENSSL_free(derData);
63685 return UA_STATUSCODE_GOOD;
63686 } else {
63687 UA_ByteString_init(p: target);
63688 }
63689
63690 return UA_STATUSCODE_BADINVALIDARGUMENT;
63691}
63692
63693#endif
63694
63695/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic128rsa15.c" ****/
63696
63697/* This Source Code Form is subject to the terms of the Mozilla Public
63698 * License, v. 2.0. If a copy of the MPL was not distributed with this
63699 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
63700 *
63701 * Copyright 2020 (c) Wind River Systems, Inc.
63702 * Copyright 2020 (c) basysKom GmbH
63703 */
63704
63705
63706#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
63707
63708
63709#include <openssl/x509.h>
63710#include <openssl/rand.h>
63711#include <openssl/evp.h>
63712
63713#define UA_SHA1_LENGTH 20
63714#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
63715#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH 16
63716#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
63717#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
63718#define UA_SHA1_LENGTH 20
63719
63720typedef struct {
63721 EVP_PKEY * localPrivateKey;
63722 UA_ByteString localCertThumbprint;
63723 const UA_Logger * logger;
63724} Policy_Context_Basic128Rsa15;
63725
63726typedef struct {
63727 UA_ByteString localSymSigningKey;
63728 UA_ByteString localSymEncryptingKey;
63729 UA_ByteString localSymIv;
63730 UA_ByteString remoteSymSigningKey;
63731 UA_ByteString remoteSymEncryptingKey;
63732 UA_ByteString remoteSymIv;
63733
63734 Policy_Context_Basic128Rsa15 * policyContext;
63735 UA_ByteString remoteCertificate;
63736 X509 * remoteCertificateX509;
63737} Channel_Context_Basic128Rsa15;
63738
63739static UA_StatusCode
63740UA_Policy_Basic128Rsa15_New_Context (UA_SecurityPolicy * securityPolicy,
63741 const UA_ByteString localPrivateKey,
63742 const UA_Logger * logger) {
63743 Policy_Context_Basic128Rsa15 * context = (Policy_Context_Basic128Rsa15 *)
63744 UA_malloc (size: sizeof (Policy_Context_Basic128Rsa15));
63745 if (context == NULL) {
63746 return UA_STATUSCODE_BADOUTOFMEMORY;
63747 }
63748
63749 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
63750
63751 if (!context->localPrivateKey) {
63752 UA_free(ptr: context);
63753 return UA_STATUSCODE_BADINVALIDARGUMENT;
63754 }
63755
63756 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
63757 certficate: &securityPolicy->localCertificate,
63758 pThumbprint: &context->localCertThumbprint, true
63759 );
63760 if (retval != UA_STATUSCODE_GOOD) {
63761 EVP_PKEY_free(pkey: context->localPrivateKey);
63762 UA_free (ptr: context);
63763 return retval;
63764 }
63765
63766 context->logger = logger;
63767 securityPolicy->policyContext = context;
63768
63769 return UA_STATUSCODE_GOOD;
63770}
63771
63772static void
63773UA_Policy_Basic128Rsa15_Clear_Context (UA_SecurityPolicy *policy) {
63774 if (policy == NULL) {
63775 return;
63776 }
63777 UA_ByteString_clear(p: &policy->localCertificate);
63778
63779 Policy_Context_Basic128Rsa15 * ctx = (Policy_Context_Basic128Rsa15 *) policy->policyContext;
63780 if (ctx == NULL) {
63781 return;
63782 }
63783
63784 /* delete all allocated members in the context */
63785
63786 EVP_PKEY_free(pkey: ctx->localPrivateKey);
63787 UA_ByteString_clear(p: &ctx->localCertThumbprint);
63788 UA_free (ptr: ctx);
63789
63790 return;
63791}
63792
63793/* create the channel context */
63794
63795static UA_StatusCode
63796UA_ChannelModule_Basic128Rsa15_New_Context (const UA_SecurityPolicy * securityPolicy,
63797 const UA_ByteString * remoteCertificate,
63798 void ** channelContext) {
63799 if (securityPolicy == NULL || remoteCertificate == NULL ||
63800 channelContext == NULL) {
63801 return UA_STATUSCODE_BADINTERNALERROR;
63802 }
63803 Channel_Context_Basic128Rsa15 * context = (Channel_Context_Basic128Rsa15 *)
63804 UA_malloc (size: sizeof (Channel_Context_Basic128Rsa15));
63805 if (context == NULL) {
63806 return UA_STATUSCODE_BADOUTOFMEMORY;
63807 }
63808
63809 UA_ByteString_init(p: &context->localSymSigningKey);
63810 UA_ByteString_init(p: &context->localSymEncryptingKey);
63811 UA_ByteString_init(p: &context->localSymIv);
63812 UA_ByteString_init(p: &context->remoteSymSigningKey);
63813 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
63814 UA_ByteString_init(p: &context->remoteSymIv);
63815
63816 UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate,
63817 src: remoteCertificate);
63818 if (retval != UA_STATUSCODE_GOOD) {
63819 UA_free (ptr: context);
63820 return retval;
63821 }
63822
63823 /* decode to X509 */
63824 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
63825 if (context->remoteCertificateX509 == NULL) {
63826 UA_ByteString_clear (p: &context->remoteCertificate);
63827 UA_free (ptr: context);
63828 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
63829 }
63830
63831 context->policyContext = (Policy_Context_Basic128Rsa15 *)
63832 (securityPolicy->policyContext);
63833
63834 *channelContext = context;
63835
63836 UA_LOG_INFO (logger: securityPolicy->logger,
63837 category: UA_LOGCATEGORY_SECURITYPOLICY,
63838 msg: "The Basic128Rsa15 security policy channel with openssl is created.");
63839
63840 return UA_STATUSCODE_GOOD;
63841}
63842
63843/* delete the channel context */
63844
63845static void
63846UA_ChannelModule_Basic128Rsa15_Delete_Context (void * channelContext) {
63847 if (channelContext != NULL) {
63848 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *)
63849 channelContext;
63850 X509_free (a: cc->remoteCertificateX509);
63851 UA_ByteString_clear (p: &cc->remoteCertificate);
63852 UA_ByteString_clear (p: &cc->localSymSigningKey);
63853 UA_ByteString_clear (p: &cc->localSymEncryptingKey);
63854 UA_ByteString_clear (p: &cc->localSymIv);
63855 UA_ByteString_clear (p: &cc->remoteSymSigningKey);
63856 UA_ByteString_clear (p: &cc->remoteSymEncryptingKey);
63857 UA_ByteString_clear (p: &cc->remoteSymIv);
63858 UA_LOG_INFO (logger: cc->policyContext->logger,
63859 category: UA_LOGCATEGORY_SECURITYPOLICY,
63860 msg: "The Basic128Rsa15 security policy channel with openssl is deleted.");
63861
63862 UA_free (ptr: cc);
63863 }
63864}
63865
63866static UA_StatusCode
63867UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey (void * channelContext,
63868 const UA_ByteString * key) {
63869 if (key == NULL || channelContext == NULL) {
63870 return UA_STATUSCODE_BADINVALIDARGUMENT;
63871 }
63872
63873 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63874 UA_ByteString_clear(p: &cc->localSymSigningKey);
63875 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
63876}
63877
63878static UA_StatusCode
63879UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey (void * channelContext,
63880 const UA_ByteString * key) {
63881 if (key == NULL || channelContext == NULL) {
63882 return UA_STATUSCODE_BADINVALIDARGUMENT;
63883 }
63884
63885 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63886 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
63887 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
63888}
63889
63890static UA_StatusCode
63891UA_ChannelModule_Basic128Rsa15_setLocalSymIv (void * channelContext,
63892 const UA_ByteString * iv) {
63893 if (iv == NULL || channelContext == NULL) {
63894 return UA_STATUSCODE_BADINVALIDARGUMENT;
63895 }
63896
63897 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63898 UA_ByteString_clear(p: &cc->localSymIv);
63899 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
63900}
63901
63902static UA_StatusCode
63903UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey (void * channelContext,
63904 const UA_ByteString * key) {
63905 if (key == NULL || channelContext == NULL) {
63906 return UA_STATUSCODE_BADINVALIDARGUMENT;
63907 }
63908
63909 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63910 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
63911 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
63912}
63913
63914static UA_StatusCode
63915UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey (void * channelContext,
63916 const UA_ByteString * key) {
63917 if (key == NULL || channelContext == NULL) {
63918 return UA_STATUSCODE_BADINVALIDARGUMENT;
63919 }
63920
63921 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63922 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
63923 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
63924}
63925
63926static UA_StatusCode
63927UA_ChannelModule_Basic128Rsa15_setRemoteSymIv (void * channelContext,
63928 const UA_ByteString * key) {
63929 if (key == NULL || channelContext == NULL) {
63930 return UA_STATUSCODE_BADINVALIDARGUMENT;
63931 }
63932
63933 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
63934 UA_ByteString_clear(p: &cc->remoteSymIv);
63935 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
63936}
63937
63938static UA_StatusCode
63939UA_ChannelModule_Basic128Rsa15_compareCertificate (const void * channelContext,
63940 const UA_ByteString * certificate) {
63941 if(channelContext == NULL || certificate == NULL) {
63942 return UA_STATUSCODE_BADINVALIDARGUMENT;
63943 }
63944
63945 const Channel_Context_Basic128Rsa15 * cc =
63946 (const Channel_Context_Basic128Rsa15 *) channelContext;
63947 return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509);
63948}
63949
63950static UA_StatusCode
63951UA_Asy_Basic128Rsa15_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
63952 const UA_ByteString * certificateThumbprint) {
63953 if (securityPolicy == NULL || certificateThumbprint == NULL) {
63954 return UA_STATUSCODE_BADINVALIDARGUMENT;
63955 }
63956 Policy_Context_Basic128Rsa15 *pc = (Policy_Context_Basic128Rsa15 *)
63957 securityPolicy->policyContext;
63958 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint)) {
63959 return UA_STATUSCODE_BADCERTIFICATEINVALID;
63960 }
63961 return UA_STATUSCODE_GOOD;
63962}
63963
63964/* Generates a thumbprint for the specified certificate */
63965
63966static UA_StatusCode
63967UA_Asy_Basic128Rsa15_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
63968 const UA_ByteString * certificate,
63969 UA_ByteString * thumbprint) {
63970 return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate,
63971 pThumbprint: thumbprint, false);
63972}
63973
63974static size_t
63975UA_AsySig_Basic128Rsa15_getRemoteSignatureSize (const void * channelContext) {
63976 if (channelContext == NULL) {
63977 return UA_STATUSCODE_BADINVALIDARGUMENT;
63978 }
63979
63980 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63981 UA_Int32 keyLen = 0;
63982 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
63983 return (size_t) keyLen;
63984}
63985
63986static size_t
63987UA_AsySig_Basic128Rsa15_getLocalSignatureSize (const void * channelContext) {
63988 if (channelContext == NULL) {
63989 return UA_STATUSCODE_BADINVALIDARGUMENT;
63990 }
63991
63992 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
63993 Policy_Context_Basic128Rsa15 * pc = (Policy_Context_Basic128Rsa15 *) cc->policyContext;
63994 UA_Int32 keyLen = 0;
63995 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
63996
63997 return (size_t) keyLen;
63998}
63999
64000static UA_StatusCode
64001UA_AsySig_Basic128Rsa15_Verify (void * channelContext,
64002 const UA_ByteString * message,
64003 const UA_ByteString * signature) {
64004 if (message == NULL || signature == NULL ||
64005 channelContext == NULL) {
64006 return UA_STATUSCODE_BADINVALIDARGUMENT;
64007 }
64008
64009 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64010 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message,
64011 publicKeyX509: cc->remoteCertificateX509, signature);
64012
64013 return retval;
64014}
64015
64016static UA_StatusCode
64017UA_AsySig_Basic128Rsa15_Sign (void * channelContext,
64018 const UA_ByteString * message,
64019 UA_ByteString * signature) {
64020 if (channelContext == NULL || message == NULL || signature == NULL) {
64021 return UA_STATUSCODE_BADINVALIDARGUMENT;
64022 }
64023
64024 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
64025 Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
64026 return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey, outSignature: signature);
64027}
64028
64029static size_t
64030UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize (const void *channelContext) {
64031 if (channelContext == NULL) {
64032 return UA_STATUSCODE_BADINVALIDARGUMENT;
64033 }
64034
64035 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
64036 UA_Int32 keyLen = 0;
64037 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64038 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
64039}
64040
64041static size_t
64042UA_AsymEn_Basic128Rsa15_getRemoteBlockSize (const void *channelContext) {
64043 if (channelContext == NULL) {
64044 return UA_STATUSCODE_BADINVALIDARGUMENT;
64045 }
64046
64047 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
64048 UA_Int32 keyLen = 0;
64049 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64050 return (size_t) keyLen;
64051}
64052
64053static size_t
64054UA_AsymEn_Basic128Rsa15_getRemoteKeyLength (const void *channelContext) {
64055 if (channelContext == NULL)
64056 return UA_STATUSCODE_BADINVALIDARGUMENT;
64057
64058 const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
64059 UA_Int32 keyLen = 0;
64060 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64061 return (size_t) keyLen * 8;
64062}
64063
64064static size_t
64065UA_AsymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
64066 if (channelContext == NULL)
64067 return UA_STATUSCODE_BADINVALIDARGUMENT;
64068
64069 const Channel_Context_Basic128Rsa15 *cc = (const Channel_Context_Basic128Rsa15 *) channelContext;
64070 Policy_Context_Basic128Rsa15 *pc = cc->policyContext;
64071 UA_Int32 keyLen = 0;
64072 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
64073 return (size_t) keyLen * 8;
64074}
64075
64076static UA_StatusCode
64077UA_AsymEn_Basic128Rsa15_Decrypt (void * channelContext,
64078 UA_ByteString * data) {
64079 if (channelContext == NULL || data == NULL) {
64080 return UA_STATUSCODE_BADINVALIDARGUMENT;
64081 }
64082
64083 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64084 UA_StatusCode ret = UA_Openssl_RSA_PKCS1_V15_Decrypt (data,
64085 privateKey: cc->policyContext->localPrivateKey);
64086 return ret;
64087}
64088
64089static UA_StatusCode
64090UA_AsymEn_Basic128Rsa15_Encrypt (void * channelContext,
64091 UA_ByteString * data) {
64092 if (channelContext == NULL || data == NULL)
64093 return UA_STATUSCODE_BADINVALIDARGUMENT;
64094
64095 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64096 return UA_Openssl_RSA_PKCS1_V15_Encrypt (data,
64097 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN,
64098 publicX509: cc->remoteCertificateX509);
64099}
64100
64101static UA_StatusCode
64102UA_Sym_Basic128Rsa15_generateNonce(void *policyContext,
64103 UA_ByteString *out) {
64104 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
64105 if (rc != 1) {
64106 return UA_STATUSCODE_BADUNEXPECTEDERROR;
64107 }
64108 return UA_STATUSCODE_GOOD;
64109}
64110
64111static UA_StatusCode
64112UA_Sym_Basic128Rsa15_generateKey(void *policyContext,
64113 const UA_ByteString *secret,
64114 const UA_ByteString *seed,
64115 UA_ByteString *out) {
64116 return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
64117}
64118
64119static size_t
64120UA_SymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) {
64121 /* 16 bytes 128 bits */
64122 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
64123}
64124
64125static size_t
64126UA_SymEn_Basic128Rsa15_getBlockSize (const void *channelContext) {
64127 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
64128}
64129
64130static size_t
64131UA_SymEn_Basic128Rsa15_getRemoteKeyLength (const void * channelContext) {
64132 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH;
64133}
64134
64135static UA_StatusCode
64136UA_SymEn_Basic128Rsa15_Encrypt (void *channelContext,
64137 UA_ByteString *data) {
64138 if(channelContext == NULL || data == NULL)
64139 return UA_STATUSCODE_BADINVALIDARGUMENT;
64140
64141 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64142 return UA_OpenSSL_AES_128_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
64143}
64144
64145static UA_StatusCode
64146UA_SymEn_Basic128Rsa15_Decrypt (void * channelContext,
64147 UA_ByteString * data) {
64148 if(channelContext == NULL || data == NULL)
64149 return UA_STATUSCODE_BADINVALIDARGUMENT;
64150 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64151 return UA_OpenSSL_AES_128_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data);
64152}
64153
64154static size_t
64155UA_SymSig_Basic128Rsa15_getKeyLength (const void *channelContext) {
64156 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
64157}
64158
64159static size_t
64160UA_SymSig_Basic128Rsa15_getSignatureSize (const void *channelContext) {
64161 return UA_SHA1_LENGTH;
64162}
64163
64164static UA_StatusCode
64165UA_SymSig_Basic128Rsa15_Verify (void * channelContext,
64166 const UA_ByteString * message,
64167 const UA_ByteString * signature) {
64168 if (channelContext == NULL || message == NULL || signature == NULL)
64169 return UA_STATUSCODE_BADINVALIDARGUMENT;
64170
64171 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64172 return UA_OpenSSL_HMAC_SHA1_Verify (message,
64173 key: &cc->remoteSymSigningKey,
64174 signature);
64175}
64176
64177static UA_StatusCode
64178UA_SymSig_Basic128Rsa15_Sign (void * channelContext,
64179 const UA_ByteString * message,
64180 UA_ByteString * signature) {
64181 if (channelContext == NULL || message == NULL || signature == NULL)
64182 return UA_STATUSCODE_BADINVALIDARGUMENT;
64183
64184 Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext;
64185 return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature);
64186}
64187
64188/* the main entry of Basic128Rsa15 */
64189
64190UA_StatusCode
64191UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy,
64192 const UA_ByteString localCertificate,
64193 const UA_ByteString localPrivateKey,
64194 const UA_Logger * logger) {
64195
64196 UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
64197 UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
64198 UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
64199 UA_StatusCode retval;
64200
64201 UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64202 msg: "The Basic128Rsa15 security policy with openssl is added.");
64203
64204 UA_Openssl_Init ();
64205 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
64206 policy->logger = logger;
64207 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
64208
64209 /* set ChannelModule context */
64210
64211 channelModule->newContext = UA_ChannelModule_Basic128Rsa15_New_Context;
64212 channelModule->deleteContext = UA_ChannelModule_Basic128Rsa15_Delete_Context;
64213
64214 channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey;
64215 channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey;
64216 channelModule->setLocalSymIv = UA_ChannelModule_Basic128Rsa15_setLocalSymIv;
64217 channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey;
64218 channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey;
64219 channelModule->setRemoteSymIv = UA_ChannelModule_Basic128Rsa15_setRemoteSymIv;
64220 channelModule->compareCertificate = UA_ChannelModule_Basic128Rsa15_compareCertificate;
64221
64222 retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
64223
64224 if (retval != UA_STATUSCODE_GOOD)
64225 return retval;
64226
64227 /* asymmetricModule */
64228
64229 asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic128Rsa15_compareCertificateThumbprint;
64230 asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic128Rsa15_makeCertificateThumbprint;
64231
64232 /* AsymmetricModule - signature algorithm */
64233
64234 UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
64235 &asymmetricModule->cryptoModule.signatureAlgorithm;
64236 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
64237 asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic128Rsa15_getRemoteSignatureSize;
64238 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic128Rsa15_getLocalSignatureSize;
64239 asySigAlgorithm->getLocalKeyLength = NULL;
64240 asySigAlgorithm->getRemoteKeyLength = NULL;
64241 asySigAlgorithm->verify = UA_AsySig_Basic128Rsa15_Verify;
64242 asySigAlgorithm->sign = UA_AsySig_Basic128Rsa15_Sign;
64243
64244 /* AsymmetricModule encryption algorithm */
64245
64246 UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
64247 &asymmetricModule->cryptoModule.encryptionAlgorithm;
64248 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-1_5\0");
64249 asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize;
64250 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic128Rsa15_getRemoteBlockSize;
64251 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic128Rsa15_getRemoteKeyLength;
64252 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic128Rsa15_getLocalKeyLength;
64253 asymEncryAlg->decrypt = UA_AsymEn_Basic128Rsa15_Decrypt;
64254 asymEncryAlg->encrypt = UA_AsymEn_Basic128Rsa15_Encrypt;
64255
64256 /* SymmetricModule */
64257
64258 symmetricModule->secureChannelNonceLength = 16; /* 128 bits*/
64259 symmetricModule->generateNonce = UA_Sym_Basic128Rsa15_generateNonce;
64260 symmetricModule->generateKey = UA_Sym_Basic128Rsa15_generateKey;
64261
64262 /* Symmetric encryption Algorithm */
64263
64264 UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
64265 &symmetricModule->cryptoModule.encryptionAlgorithm;
64266 symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
64267 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic128Rsa15_getLocalKeyLength;
64268 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic128Rsa15_getRemoteKeyLength;
64269 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
64270 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize;
64271 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic128Rsa15_Decrypt;
64272 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic128Rsa15_Encrypt;
64273
64274 /* Symmetric signature Algorithm */
64275
64276 UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
64277 &symmetricModule->cryptoModule.signatureAlgorithm;
64278 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
64279 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
64280 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength;
64281 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
64282 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize;
64283
64284 symSignatureAlgorithm->verify = UA_SymSig_Basic128Rsa15_Verify;
64285 symSignatureAlgorithm->sign = UA_SymSig_Basic128Rsa15_Sign;
64286
64287 /* set the policy context */
64288
64289 retval = UA_Policy_Basic128Rsa15_New_Context (securityPolicy: policy, localPrivateKey, logger);
64290 if (retval != UA_STATUSCODE_GOOD) {
64291 UA_ByteString_clear (p: &policy->localCertificate);
64292 return retval;
64293 }
64294 policy->clear = UA_Policy_Basic128Rsa15_Clear_Context;
64295
64296 /* Use the same signature algorithm as the asymmetric component for
64297 certificate signing (see standard) */
64298 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
64299
64300 return UA_STATUSCODE_GOOD;
64301}
64302
64303#endif
64304
64305/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256.c" ****/
64306
64307/* This Source Code Form is subject to the terms of the Mozilla Public
64308 * License, v. 2.0. If a copy of the MPL was not distributed with this
64309 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
64310 *
64311 * Copyright 2020 (c) Wind River Systems, Inc.
64312 * Copyright 2020 (c) basysKom GmbH
64313 */
64314
64315
64316#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
64317
64318
64319#include <openssl/x509.h>
64320#include <openssl/rand.h>
64321
64322#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
64323#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH 32
64324#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
64325#define UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH 24
64326#define UA_SHA1_LENGTH 20
64327
64328typedef struct {
64329 EVP_PKEY * localPrivateKey;
64330 UA_ByteString localCertThumbprint;
64331 const UA_Logger * logger;
64332} Policy_Context_Basic256;
64333
64334typedef struct {
64335 UA_ByteString localSymSigningKey;
64336 UA_ByteString localSymEncryptingKey;
64337 UA_ByteString localSymIv;
64338 UA_ByteString remoteSymSigningKey;
64339 UA_ByteString remoteSymEncryptingKey;
64340 UA_ByteString remoteSymIv;
64341
64342 Policy_Context_Basic256 * policyContext;
64343 UA_ByteString remoteCertificate;
64344 X509 * remoteCertificateX509;
64345} Channel_Context_Basic256;
64346
64347static UA_StatusCode
64348UA_Policy_Basic256_New_Context (UA_SecurityPolicy * securityPolicy,
64349 const UA_ByteString localPrivateKey,
64350 const UA_Logger * logger) {
64351 Policy_Context_Basic256 * context = (Policy_Context_Basic256 *)
64352 UA_malloc (size: sizeof (Policy_Context_Basic256));
64353 if (context == NULL) {
64354 return UA_STATUSCODE_BADOUTOFMEMORY;
64355 }
64356
64357 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
64358
64359 if (!context->localPrivateKey) {
64360 UA_free (ptr: context);
64361 return UA_STATUSCODE_BADINVALIDARGUMENT;
64362 }
64363
64364 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint (
64365 certficate: &securityPolicy->localCertificate,
64366 pThumbprint: &context->localCertThumbprint, true
64367 );
64368 if (retval != UA_STATUSCODE_GOOD) {
64369 EVP_PKEY_free(pkey: context->localPrivateKey);
64370 UA_free (ptr: context);
64371 return retval;
64372 }
64373
64374 context->logger = logger;
64375 securityPolicy->policyContext = context;
64376
64377 return UA_STATUSCODE_GOOD;
64378}
64379
64380static void
64381UA_Policy_Basic256_Clear_Context (UA_SecurityPolicy *policy) {
64382 if (policy == NULL) {
64383 return;
64384 }
64385 UA_ByteString_clear(p: &policy->localCertificate);
64386
64387 Policy_Context_Basic256 * ctx = (Policy_Context_Basic256 *) policy->policyContext;
64388 if (ctx == NULL) {
64389 return;
64390 }
64391
64392 /* delete all allocated members in the context */
64393
64394 EVP_PKEY_free(pkey: ctx->localPrivateKey);
64395 UA_ByteString_clear(p: &ctx->localCertThumbprint);
64396 UA_free (ptr: ctx);
64397
64398 return;
64399}
64400
64401/* create the channel context */
64402
64403static UA_StatusCode
64404UA_ChannelModule_Basic256_New_Context (const UA_SecurityPolicy * securityPolicy,
64405 const UA_ByteString * remoteCertificate,
64406 void ** channelContext) {
64407 if (securityPolicy == NULL || remoteCertificate == NULL ||
64408 channelContext == NULL) {
64409 return UA_STATUSCODE_BADINTERNALERROR;
64410 }
64411 Channel_Context_Basic256 * context = (Channel_Context_Basic256 *)
64412 UA_malloc (size: sizeof (Channel_Context_Basic256));
64413 if (context == NULL) {
64414 return UA_STATUSCODE_BADOUTOFMEMORY;
64415 }
64416
64417 UA_ByteString_init(p: &context->localSymSigningKey);
64418 UA_ByteString_init(p: &context->localSymEncryptingKey);
64419 UA_ByteString_init(p: &context->localSymIv);
64420 UA_ByteString_init(p: &context->remoteSymSigningKey);
64421 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
64422 UA_ByteString_init(p: &context->remoteSymIv);
64423
64424 UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate,
64425 src: remoteCertificate);
64426 if (retval != UA_STATUSCODE_GOOD) {
64427 UA_free (ptr: context);
64428 return retval;
64429 }
64430
64431 /* decode to X509 */
64432 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
64433 if (context->remoteCertificateX509 == NULL) {
64434 UA_ByteString_clear (p: &context->remoteCertificate);
64435 UA_free (ptr: context);
64436 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
64437 }
64438
64439 context->policyContext = (Policy_Context_Basic256 *)
64440 (securityPolicy->policyContext);
64441
64442 *channelContext = context;
64443
64444 UA_LOG_INFO (logger: securityPolicy->logger,
64445 category: UA_LOGCATEGORY_SECURITYPOLICY,
64446 msg: "The basic256 security policy channel with openssl is created.");
64447
64448 return UA_STATUSCODE_GOOD;
64449}
64450
64451/* delete the channel context */
64452
64453static void
64454UA_ChannelModule_Basic256_Delete_Context (void * channelContext) {
64455 if (channelContext != NULL) {
64456 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *)
64457 channelContext;
64458 X509_free (a: cc->remoteCertificateX509);
64459 UA_ByteString_clear (p: &cc->remoteCertificate);
64460 UA_ByteString_clear (p: &cc->localSymSigningKey);
64461 UA_ByteString_clear (p: &cc->localSymEncryptingKey);
64462 UA_ByteString_clear (p: &cc->localSymIv);
64463 UA_ByteString_clear (p: &cc->remoteSymSigningKey);
64464 UA_ByteString_clear (p: &cc->remoteSymEncryptingKey);
64465 UA_ByteString_clear (p: &cc->remoteSymIv);
64466 UA_LOG_INFO (logger: cc->policyContext->logger,
64467 category: UA_LOGCATEGORY_SECURITYPOLICY,
64468 msg: "The basic256 security policy channel with openssl is deleted.");
64469
64470 UA_free (ptr: cc);
64471 }
64472}
64473
64474/* Compares the supplied certificate with the certificate
64475 * in the endpoint context
64476 */
64477
64478static UA_StatusCode
64479UA_Asy_Basic256_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
64480 const UA_ByteString * certificateThumbprint) {
64481 if (securityPolicy == NULL || certificateThumbprint == NULL) {
64482 return UA_STATUSCODE_BADINVALIDARGUMENT;
64483 }
64484 Policy_Context_Basic256 *pc = (Policy_Context_Basic256 *)
64485 securityPolicy->policyContext;
64486 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint)) {
64487 return UA_STATUSCODE_BADCERTIFICATEINVALID;
64488 }
64489 return UA_STATUSCODE_GOOD;
64490}
64491
64492/* Generates a thumbprint for the specified certificate */
64493
64494static UA_StatusCode
64495UA_Asy_Basic256_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy,
64496 const UA_ByteString * certificate,
64497 UA_ByteString * thumbprint) {
64498 return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate,
64499 pThumbprint: thumbprint, false);
64500}
64501
64502static UA_StatusCode
64503UA_ChannelModule_Basic256_setLocalSymSigningKey (void * channelContext,
64504 const UA_ByteString * key) {
64505 if (key == NULL || channelContext == NULL) {
64506 return UA_STATUSCODE_BADINVALIDARGUMENT;
64507 }
64508
64509 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64510 UA_ByteString_clear(p: &cc->localSymSigningKey);
64511 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
64512}
64513
64514static UA_StatusCode
64515UA_ChannelModule_Basic256_setLocalSymEncryptingKey (void * channelContext,
64516 const UA_ByteString * key) {
64517 if (key == NULL || channelContext == NULL) {
64518 return UA_STATUSCODE_BADINVALIDARGUMENT;
64519 }
64520
64521 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64522 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
64523 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
64524}
64525
64526static UA_StatusCode
64527UA_ChannelModule_Basic256_setLocalSymIv (void * channelContext,
64528 const UA_ByteString * iv) {
64529 if (iv == NULL || channelContext == NULL) {
64530 return UA_STATUSCODE_BADINVALIDARGUMENT;
64531 }
64532
64533 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64534 UA_ByteString_clear(p: &cc->localSymIv);
64535 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
64536}
64537
64538static UA_StatusCode
64539UA_ChannelModule_Basic256_setRemoteSymSigningKey (void * channelContext,
64540 const UA_ByteString * key) {
64541 if (key == NULL || channelContext == NULL) {
64542 return UA_STATUSCODE_BADINVALIDARGUMENT;
64543 }
64544
64545 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64546 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
64547 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
64548}
64549
64550static UA_StatusCode
64551UA_ChannelModule_Basic256_setRemoteSymEncryptingKey (void * channelContext,
64552 const UA_ByteString * key) {
64553 if (key == NULL || channelContext == NULL) {
64554 return UA_STATUSCODE_BADINVALIDARGUMENT;
64555 }
64556
64557 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64558 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
64559 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
64560}
64561
64562static UA_StatusCode
64563UA_ChannelModule_Basic256_setRemoteSymIv (void * channelContext,
64564 const UA_ByteString * key) {
64565 if (key == NULL || channelContext == NULL) {
64566 return UA_STATUSCODE_BADINVALIDARGUMENT;
64567 }
64568
64569 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64570 UA_ByteString_clear(p: &cc->remoteSymIv);
64571 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
64572}
64573
64574static UA_StatusCode
64575UA_ChannelModule_Basic256_compareCertificate (const void * channelContext,
64576 const UA_ByteString * certificate) {
64577 if(channelContext == NULL || certificate == NULL) {
64578 return UA_STATUSCODE_BADINVALIDARGUMENT;
64579 }
64580
64581 const Channel_Context_Basic256 * cc =
64582 (const Channel_Context_Basic256 *) channelContext;
64583 return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509);
64584}
64585
64586static size_t
64587UA_AsySig_Basic256_getRemoteSignatureSize (const void *channelContext) {
64588 if (channelContext == NULL) {
64589 return UA_STATUSCODE_BADINVALIDARGUMENT;
64590 }
64591
64592 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64593 UA_Int32 keyLen = 0;
64594 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64595 return (size_t) keyLen;
64596}
64597
64598static size_t
64599UA_AsySig_Basic256_getLocalSignatureSize (const void *channelContext) {
64600 if (channelContext == NULL) {
64601 return UA_STATUSCODE_BADINVALIDARGUMENT;
64602 }
64603
64604 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64605 Policy_Context_Basic256 * pc = cc->policyContext;
64606 UA_Int32 keyLen = 0;
64607 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
64608
64609 return (size_t) keyLen;
64610}
64611
64612static UA_StatusCode
64613UA_AsySig_Basic256_Verify (void * channelContext,
64614 const UA_ByteString * message,
64615 const UA_ByteString * signature) {
64616 if (message == NULL || signature == NULL || channelContext == NULL) {
64617 return UA_STATUSCODE_BADINVALIDARGUMENT;
64618 }
64619
64620 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64621 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message,
64622 publicKeyX509: cc->remoteCertificateX509, signature);
64623 return retval;
64624}
64625
64626static UA_StatusCode
64627UA_AsySig_Basic256_Sign (void * channelContext,
64628 const UA_ByteString * message,
64629 UA_ByteString * signature) {
64630 if (channelContext == NULL || message == NULL || signature == NULL) {
64631 return UA_STATUSCODE_BADINVALIDARGUMENT;
64632 }
64633
64634 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64635 Policy_Context_Basic256 * pc = cc->policyContext;
64636 return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey,
64637 outSignature: signature);
64638}
64639
64640static size_t
64641UA_AsymEn_Basic256_getRemotePlainTextBlockSize (const void *channelContext) {
64642 if (channelContext == NULL) {
64643 return UA_STATUSCODE_BADINVALIDARGUMENT;
64644 }
64645
64646 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64647 UA_Int32 keyLen = 0;
64648 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64649 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
64650}
64651
64652static size_t
64653UA_AsymEn_Basic256_getRemoteBlockSize (const void *channelContext) {
64654 if (channelContext == NULL) {
64655 return UA_STATUSCODE_BADINVALIDARGUMENT;
64656 }
64657
64658 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64659 UA_Int32 keyLen = 0;
64660 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64661 return (size_t) keyLen;
64662}
64663
64664static size_t
64665UA_AsymEn_Basic256_getRemoteKeyLength (const void *channelContext) {
64666 if (channelContext == NULL)
64667 return UA_STATUSCODE_BADINVALIDARGUMENT;
64668
64669 const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext;
64670 UA_Int32 keyLen = 0;
64671 UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
64672 return (size_t) keyLen * 8;
64673}
64674
64675static size_t
64676UA_AsymEn_Basic256_getLocalKeyLength (const void *channelContext) {
64677 if (channelContext == NULL)
64678 return UA_STATUSCODE_BADINVALIDARGUMENT;
64679
64680 const Channel_Context_Basic256 *cc = (const Channel_Context_Basic256 *) channelContext;
64681 Policy_Context_Basic256 *pc = cc->policyContext;
64682 UA_Int32 keyLen = 0;
64683 UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen);
64684
64685 return (size_t) keyLen * 8;
64686}
64687
64688static UA_StatusCode
64689UA_AsymEn_Basic256_Decrypt (void * channelContext,
64690 UA_ByteString * data) {
64691 if (channelContext == NULL || data == NULL) {
64692 return UA_STATUSCODE_BADINVALIDARGUMENT;
64693 }
64694
64695 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64696 UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data,
64697 privateKey: cc->policyContext->localPrivateKey);
64698 return ret;
64699}
64700
64701static UA_StatusCode
64702UA_AsymEn_Basic256_Encrypt (void * channelContext,
64703 UA_ByteString * data) {
64704 if (channelContext == NULL || data == NULL) {
64705 return UA_STATUSCODE_BADINVALIDARGUMENT;
64706 }
64707
64708 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64709 return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN,
64710 publicX509: cc->remoteCertificateX509);
64711}
64712
64713static UA_StatusCode
64714UA_Sym_Basic256_generateNonce(void *policyContext,
64715 UA_ByteString *out) {
64716 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
64717 if (rc != 1) {
64718 return UA_STATUSCODE_BADUNEXPECTEDERROR;
64719 }
64720 return UA_STATUSCODE_GOOD;
64721}
64722
64723static UA_StatusCode
64724UA_Sym_Basic256_generateKey(void *policyContext, const UA_ByteString *secret,
64725 const UA_ByteString *seed, UA_ByteString *out) {
64726 return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out);
64727}
64728
64729static size_t
64730UA_SymEn_Basic256_getLocalKeyLength (const void * channelContext) {
64731 /* 32 bytes 256 bits */
64732 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
64733}
64734
64735static size_t
64736UA_SymEn_Basic256_getBlockSize (const void * channelContext) {
64737 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
64738}
64739
64740static size_t
64741UA_SymEn_Basic256_getRemoteKeyLength (const void * channelContext) {
64742 /* 32 bytes 256 bits */
64743 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH;
64744}
64745
64746static UA_StatusCode
64747UA_SymEn_Basic256_Encrypt (void * channelContext,
64748 UA_ByteString * data) {
64749 if(channelContext == NULL || data == NULL)
64750 return UA_STATUSCODE_BADINVALIDARGUMENT;
64751
64752 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64753 return UA_OpenSSL_AES_256_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
64754}
64755
64756static UA_StatusCode
64757UA_SymEn_Basic256_Decrypt (void * channelContext,
64758 UA_ByteString * data) {
64759 if(channelContext == NULL || data == NULL)
64760 return UA_STATUSCODE_BADINVALIDARGUMENT;
64761 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64762 return UA_OpenSSL_AES_256_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data);
64763}
64764
64765static size_t
64766UA_SymSig_Basic256_getKeyLength (const void * channelContext) {
64767 return UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH;
64768}
64769
64770static size_t
64771UA_SymSig_Basic256_getSignatureSize (const void * channelContext) {
64772 return UA_SHA1_LENGTH;
64773}
64774
64775static UA_StatusCode
64776UA_SymSig_Basic256_Verify (void * channelContext,
64777 const UA_ByteString * message,
64778 const UA_ByteString * signature) {
64779 if (channelContext == NULL ||
64780 message == NULL || signature == NULL)
64781 return UA_STATUSCODE_BADINVALIDARGUMENT;
64782
64783 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64784 return UA_OpenSSL_HMAC_SHA1_Verify (message,
64785 key: &cc->remoteSymSigningKey,
64786 signature);
64787}
64788
64789static UA_StatusCode
64790UA_SymSig_Basic256_Sign (void * channelContext,
64791 const UA_ByteString * message,
64792 UA_ByteString * signature) {
64793 if (channelContext == NULL || message == NULL || signature == NULL)
64794 return UA_STATUSCODE_BADINVALIDARGUMENT;
64795
64796 Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext;
64797 return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature);
64798}
64799
64800/* the main entry of Basic256 */
64801
64802UA_StatusCode
64803UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy,
64804 const UA_ByteString localCertificate,
64805 const UA_ByteString localPrivateKey,
64806 const UA_Logger * logger) {
64807 UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule;
64808 UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule;
64809 UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule;
64810 UA_StatusCode retval;
64811
64812 UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
64813 msg: "The basic256 security policy with openssl is added.");
64814
64815 UA_Openssl_Init ();
64816 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
64817 policy->logger = logger;
64818 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
64819
64820 /* set ChannelModule context */
64821
64822 channelModule->newContext = UA_ChannelModule_Basic256_New_Context;
64823 channelModule->deleteContext = UA_ChannelModule_Basic256_Delete_Context;
64824
64825 channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256_setLocalSymSigningKey;
64826 channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic256_setLocalSymEncryptingKey;
64827 channelModule->setLocalSymIv = UA_ChannelModule_Basic256_setLocalSymIv;
64828 channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic256_setRemoteSymSigningKey;
64829 channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic256_setRemoteSymEncryptingKey;
64830 channelModule->setRemoteSymIv = UA_ChannelModule_Basic256_setRemoteSymIv;
64831 channelModule->compareCertificate = UA_ChannelModule_Basic256_compareCertificate;
64832
64833 retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
64834
64835 if (retval != UA_STATUSCODE_GOOD)
64836 return retval;
64837
64838 /* asymmetricModule */
64839
64840 asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic256_compareCertificateThumbprint;
64841 asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic256_makeCertificateThumbprint;
64842
64843 /* AsymmetricModule - signature algorithm */
64844
64845 UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm =
64846 &asymmetricModule->cryptoModule.signatureAlgorithm;
64847 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
64848 asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic256_getRemoteSignatureSize;
64849 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256_getLocalSignatureSize;
64850 asySigAlgorithm->verify = UA_AsySig_Basic256_Verify;
64851 asySigAlgorithm->sign = UA_AsySig_Basic256_Sign;
64852 asySigAlgorithm->getLocalKeyLength = NULL;
64853 asySigAlgorithm->getRemoteKeyLength = NULL;
64854
64855 /* AsymmetricModule encryption algorithm */
64856
64857 UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg =
64858 &asymmetricModule->cryptoModule.encryptionAlgorithm;
64859 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
64860 asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic256_getRemotePlainTextBlockSize;
64861 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256_getRemoteBlockSize;
64862 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256_getRemoteKeyLength;
64863 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256_getLocalKeyLength;
64864 asymEncryAlg->decrypt = UA_AsymEn_Basic256_Decrypt;
64865 asymEncryAlg->encrypt = UA_AsymEn_Basic256_Encrypt;
64866
64867 /* SymmetricModule */
64868
64869 symmetricModule->secureChannelNonceLength = 32;
64870 symmetricModule->generateNonce = UA_Sym_Basic256_generateNonce;
64871 symmetricModule->generateKey = UA_Sym_Basic256_generateKey;
64872
64873 /* Symmetric encryption Algorithm */
64874
64875 UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm =
64876 &symmetricModule->cryptoModule.encryptionAlgorithm;
64877 symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
64878 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256_getLocalKeyLength;
64879 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256_getRemoteKeyLength;
64880 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256_getBlockSize;
64881 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256_getBlockSize;
64882 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256_Decrypt;
64883 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256_Encrypt;
64884
64885 /* Symmetric signature Algorithm */
64886
64887 UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm =
64888 &symmetricModule->cryptoModule.signatureAlgorithm;
64889 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
64890 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256_getKeyLength;
64891 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256_getKeyLength;
64892 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic256_getSignatureSize;
64893 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256_getSignatureSize;
64894 symSignatureAlgorithm->verify = UA_SymSig_Basic256_Verify;
64895 symSignatureAlgorithm->sign = UA_SymSig_Basic256_Sign;
64896
64897 /* set the policy context */
64898
64899 retval = UA_Policy_Basic256_New_Context (securityPolicy: policy, localPrivateKey, logger);
64900 if (retval != UA_STATUSCODE_GOOD) {
64901 UA_ByteString_clear (p: &policy->localCertificate);
64902 return retval;
64903 }
64904 policy->clear = UA_Policy_Basic256_Clear_Context;
64905
64906 /* Use the same signature algorithm as the asymmetric component for
64907 certificate signing (see standard) */
64908 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
64909
64910 return UA_STATUSCODE_GOOD;
64911}
64912
64913#endif
64914
64915/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256sha256.c" ****/
64916
64917/* This Source Code Form is subject to the terms of the Mozilla Public
64918 * License, v. 2.0. If a copy of the MPL was not distributed with this
64919 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
64920 *
64921 * Copyright 2020 (c) Wind River Systems, Inc.
64922 * Copyright 2020 (c) basysKom GmbH
64923 */
64924
64925
64926#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
64927
64928
64929#include <openssl/hmac.h>
64930#include <openssl/sha.h>
64931#include <openssl/rsa.h>
64932#include <openssl/x509.h>
64933#include <openssl/rand.h>
64934#include <openssl/rsa.h>
64935
64936#define UA_SHA256_LENGTH 32 /* 256 bit */
64937#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
64938#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
64939#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH 32
64940#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
64941#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
64942#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
64943#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
64944
64945typedef struct {
64946 EVP_PKEY *localPrivateKey;
64947 UA_ByteString localCertThumbprint;
64948 const UA_Logger *logger;
64949} Policy_Context_Basic256Sha256;
64950
64951typedef struct {
64952 UA_ByteString localSymSigningKey;
64953 UA_ByteString localSymEncryptingKey;
64954 UA_ByteString localSymIv;
64955 UA_ByteString remoteSymSigningKey;
64956 UA_ByteString remoteSymEncryptingKey;
64957 UA_ByteString remoteSymIv;
64958
64959 Policy_Context_Basic256Sha256 *policyContext;
64960 UA_ByteString remoteCertificate;
64961 X509 *remoteCertificateX509; /* X509 */
64962} Channel_Context_Basic256Sha256;
64963
64964/* create the policy context */
64965
64966static UA_StatusCode
64967UA_Policy_New_Context(UA_SecurityPolicy * securityPolicy,
64968 const UA_ByteString localPrivateKey,
64969 const UA_Logger *logger) {
64970 Policy_Context_Basic256Sha256 *context = (Policy_Context_Basic256Sha256 *)
64971 UA_malloc(size: sizeof(Policy_Context_Basic256Sha256));
64972 if(context == NULL)
64973 return UA_STATUSCODE_BADOUTOFMEMORY;
64974 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
64975
64976 if(!context->localPrivateKey) {
64977 UA_free(ptr: context);
64978 return UA_STATUSCODE_BADINVALIDARGUMENT;
64979 }
64980
64981 UA_StatusCode retval =
64982 UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate,
64983 pThumbprint: &context->localCertThumbprint, true);
64984 if(retval != UA_STATUSCODE_GOOD) {
64985 EVP_PKEY_free(pkey: context->localPrivateKey);
64986 UA_free(ptr: context);
64987 return retval;
64988 }
64989
64990 context->logger = logger;
64991 securityPolicy->policyContext = context;
64992 return UA_STATUSCODE_GOOD;
64993}
64994
64995/* Clear the policy context */
64996static void
64997UA_Policy_Clear_Context(UA_SecurityPolicy *policy) {
64998 if(policy == NULL)
64999 return;
65000
65001 UA_ByteString_clear(p: &policy->localCertificate);
65002
65003 /* Delete all allocated members in the context */
65004 Policy_Context_Basic256Sha256 *pc =
65005 (Policy_Context_Basic256Sha256 *) policy->policyContext;
65006 EVP_PKEY_free(pkey: pc->localPrivateKey);
65007 UA_ByteString_clear(p: &pc->localCertThumbprint);
65008 UA_free(ptr: pc);
65009 return;
65010}
65011
65012/* create the channel context */
65013
65014static UA_StatusCode
65015UA_ChannelModule_New_Context(const UA_SecurityPolicy * securityPolicy,
65016 const UA_ByteString * remoteCertificate,
65017 void ** channelContext) {
65018 if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL)
65019 return UA_STATUSCODE_BADINTERNALERROR;
65020
65021 Channel_Context_Basic256Sha256 *context = (Channel_Context_Basic256Sha256 *)
65022 UA_malloc(size: sizeof(Channel_Context_Basic256Sha256));
65023 if(context == NULL)
65024 return UA_STATUSCODE_BADOUTOFMEMORY;
65025
65026 UA_ByteString_init(p: &context->localSymSigningKey);
65027 UA_ByteString_init(p: &context->localSymEncryptingKey);
65028 UA_ByteString_init(p: &context->localSymIv);
65029 UA_ByteString_init(p: &context->remoteSymSigningKey);
65030 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
65031 UA_ByteString_init(p: &context->remoteSymIv);
65032
65033 UA_StatusCode retval =
65034 UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate);
65035 if(retval != UA_STATUSCODE_GOOD) {
65036 UA_free(ptr: context);
65037 return retval;
65038 }
65039
65040 /* decode to X509 */
65041 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
65042 if(context->remoteCertificateX509 == NULL) {
65043 UA_ByteString_clear(p: &context->remoteCertificate);
65044 UA_free(ptr: context);
65045 return UA_STATUSCODE_BADINTERNALERROR;
65046 }
65047
65048 context->policyContext =
65049 (Policy_Context_Basic256Sha256 *)securityPolicy->policyContext;
65050 *channelContext = context;
65051
65052 UA_LOG_INFO(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65053 msg: "The basic256sha256 security policy channel with openssl is created.");
65054
65055 return UA_STATUSCODE_GOOD;
65056}
65057
65058/* delete the channel context */
65059
65060static void
65061UA_ChannelModule_Delete_Context(void * channelContext) {
65062 if(!channelContext)
65063 return;
65064
65065 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)channelContext;
65066 X509_free(a: cc->remoteCertificateX509);
65067 UA_ByteString_clear(p: &cc->remoteCertificate);
65068 UA_ByteString_clear(p: &cc->localSymSigningKey);
65069 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65070 UA_ByteString_clear(p: &cc->localSymIv);
65071 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65072 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65073 UA_ByteString_clear(p: &cc->remoteSymIv);
65074
65075 UA_LOG_INFO(logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65076 msg: "The basic256sha256 security policy channel with openssl is deleted.");
65077 UA_free(ptr: cc);
65078}
65079
65080/* Verifies the signature of the message using the provided keys in the context.
65081 * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
65082static UA_StatusCode
65083UA_AsySig_Basic256Sha256_Verify(void *channelContext,
65084 const UA_ByteString *message,
65085 const UA_ByteString *signature) {
65086 if(message == NULL || signature == NULL || channelContext == NULL)
65087 return UA_STATUSCODE_BADINTERNALERROR;
65088
65089 Channel_Context_Basic256Sha256 * cc =
65090 (Channel_Context_Basic256Sha256 *) channelContext;
65091 return UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(msg: message, publicKeyX509: cc->remoteCertificateX509,
65092 signature);
65093}
65094
65095/* Compares the supplied certificate with the certificate
65096 * in the endpoint context
65097 */
65098
65099static UA_StatusCode
65100UA_compareCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
65101 const UA_ByteString * certificateThumbprint) {
65102 if(securityPolicy == NULL || certificateThumbprint == NULL)
65103 return UA_STATUSCODE_BADINVALIDARGUMENT;
65104 Policy_Context_Basic256Sha256 *pc = (Policy_Context_Basic256Sha256 *)
65105 securityPolicy->policyContext;
65106 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint))
65107 return UA_STATUSCODE_BADCERTIFICATEINVALID;
65108 return UA_STATUSCODE_GOOD;
65109}
65110
65111/* Generates a thumbprint for the specified certificate */
65112
65113static UA_StatusCode
65114UA_makeCertificateThumbprint(const UA_SecurityPolicy * securityPolicy,
65115 const UA_ByteString * certificate,
65116 UA_ByteString * thumbprint) {
65117 return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false);
65118}
65119
65120static UA_StatusCode
65121UA_Asym_Basic256Sha256_Decrypt(void * channelContext, UA_ByteString * data) {
65122 if(channelContext == NULL || data == NULL)
65123 return UA_STATUSCODE_BADINVALIDARGUMENT;
65124
65125 Channel_Context_Basic256Sha256 * cc =
65126 (Channel_Context_Basic256Sha256 *) channelContext;
65127 return UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey);
65128}
65129
65130static size_t
65131UA_Asym_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
65132 if(channelContext == NULL)
65133 return UA_STATUSCODE_BADINTERNALERROR;
65134
65135 const Channel_Context_Basic256Sha256 * cc =
65136 (const Channel_Context_Basic256Sha256 *) channelContext;
65137 UA_Int32 keyLen = 0;
65138 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65139 return (size_t) keyLen;
65140}
65141
65142static size_t
65143UA_AsySig_Basic256Sha256_getLocalSignatureSize(const void *channelContext) {
65144 if(channelContext == NULL)
65145 return UA_STATUSCODE_BADINTERNALERROR;
65146
65147 const Channel_Context_Basic256Sha256 *cc =
65148 (const Channel_Context_Basic256Sha256 *) channelContext;
65149 Policy_Context_Basic256Sha256 * pc = cc->policyContext;
65150 UA_Int32 keyLen = 0;
65151 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65152 return (size_t) keyLen;
65153}
65154
65155static size_t
65156UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize(const void *channelContext) {
65157 if(channelContext == NULL)
65158 return UA_STATUSCODE_BADINTERNALERROR;
65159
65160 const Channel_Context_Basic256Sha256 *cc =
65161 (const Channel_Context_Basic256Sha256 *) channelContext;
65162 UA_Int32 keyLen = 0;
65163 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65164 return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
65165}
65166
65167static size_t
65168UA_AsymEn_Basic256Sha256_getRemoteBlockSize(const void *channelContext) {
65169 if(channelContext == NULL)
65170 return UA_STATUSCODE_BADINTERNALERROR;
65171
65172 const Channel_Context_Basic256Sha256 * cc =
65173 (const Channel_Context_Basic256Sha256 *) channelContext;
65174 UA_Int32 keyLen = 0;
65175 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65176 return (size_t) keyLen;
65177}
65178
65179static size_t
65180UA_AsymEn_Basic256Sha256_getRemoteKeyLength(const void *channelContext) {
65181 if(channelContext == NULL)
65182 return UA_STATUSCODE_BADINTERNALERROR;
65183
65184 const Channel_Context_Basic256Sha256 *cc =
65185 (const Channel_Context_Basic256Sha256 *) channelContext;
65186 UA_Int32 keyLen = 0;
65187 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65188 return (size_t) keyLen * 8;
65189}
65190
65191static UA_StatusCode
65192UA_Sym_Basic256Sha256_generateNonce(void *policyContext,
65193 UA_ByteString *out) {
65194 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length);
65195 if(rc != 1)
65196 return UA_STATUSCODE_BADUNEXPECTEDERROR;
65197 return UA_STATUSCODE_GOOD;
65198}
65199
65200static size_t
65201UA_SymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65202 /* 32 bytes 256 bits */
65203 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
65204}
65205
65206static size_t
65207UA_SymSig_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65208 /* 32 bytes 256 bits */
65209 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
65210}
65211
65212static UA_StatusCode
65213UA_Sym_Basic256Sha256_generateKey(void *policyContext,
65214 const UA_ByteString *secret,
65215 const UA_ByteString *seed,
65216 UA_ByteString *out) {
65217 return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
65218}
65219
65220static UA_StatusCode
65221UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey(void * channelContext,
65222 const UA_ByteString * key) {
65223 if(key == NULL || channelContext == NULL)
65224 return UA_STATUSCODE_BADINTERNALERROR;
65225 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65226 UA_ByteString_clear(p: &cc->localSymSigningKey);
65227 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
65228}
65229
65230static UA_StatusCode
65231UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey(void * channelContext,
65232 const UA_ByteString * key) {
65233 if(key == NULL || channelContext == NULL)
65234 return UA_STATUSCODE_BADINTERNALERROR;
65235 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65236 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65237 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
65238}
65239
65240static UA_StatusCode
65241UA_ChannelM_Basic256Sha256_setLocalSymIv(void * channelContext,
65242 const UA_ByteString * iv) {
65243 if(iv == NULL || channelContext == NULL)
65244 return UA_STATUSCODE_BADINTERNALERROR;
65245 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65246 UA_ByteString_clear(p: &cc->localSymIv);
65247 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
65248}
65249
65250static size_t
65251UA_SymEn_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
65252 /* 32 bytes 256 bits */
65253 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH;
65254}
65255
65256static size_t
65257UA_SymEn_Basic256Sha256_getBlockSize(const void *channelContext) {
65258 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
65259}
65260
65261static size_t
65262UA_SymSig_Basic256Sha256_getRemoteKeyLength(const void * channelContext) {
65263 /* 32 bytes 256 bits */
65264 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
65265}
65266
65267static UA_StatusCode
65268UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey(void *channelContext,
65269 const UA_ByteString * key) {
65270 if(key == NULL || channelContext == NULL)
65271 return UA_STATUSCODE_BADINTERNALERROR;
65272 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65273 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65274 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
65275}
65276
65277static UA_StatusCode
65278UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey(void *channelContext,
65279 const UA_ByteString * key) {
65280 if(key == NULL || channelContext == NULL)
65281 return UA_STATUSCODE_BADINTERNALERROR;
65282 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65283 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65284 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
65285}
65286
65287static UA_StatusCode
65288UA_ChannelM_Basic256Sha256_setRemoteSymIv(void *channelContext,
65289 const UA_ByteString * key) {
65290 if(key == NULL || channelContext == NULL)
65291 return UA_STATUSCODE_BADINTERNALERROR;
65292 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65293 UA_ByteString_clear(p: &cc->remoteSymIv);
65294 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
65295}
65296
65297static UA_StatusCode
65298UA_AsySig_Basic256Sha256_sign(void *channelContext, const UA_ByteString * message,
65299 UA_ByteString *signature) {
65300 if(channelContext == NULL || message == NULL || signature == NULL)
65301 return UA_STATUSCODE_BADINTERNALERROR;
65302 Channel_Context_Basic256Sha256 *cc = (Channel_Context_Basic256Sha256 *) channelContext;
65303 Policy_Context_Basic256Sha256 *pc = cc->policyContext;
65304 return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature);
65305}
65306
65307static UA_StatusCode
65308UA_AsymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
65309 if(channelContext == NULL || data == NULL)
65310 return UA_STATUSCODE_BADINTERNALERROR;
65311 Channel_Context_Basic256Sha256 * cc =
65312 (Channel_Context_Basic256Sha256 *) channelContext;
65313 return UA_Openssl_RSA_OAEP_Encrypt(data, UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN,
65314 publicX509: cc->remoteCertificateX509);
65315}
65316
65317static size_t
65318UA_SymSig_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) {
65319 return UA_SHA256_LENGTH;
65320}
65321
65322static UA_StatusCode
65323UA_SymSig_Basic256Sha256_verify(void *channelContext, const UA_ByteString *message,
65324 const UA_ByteString *signature) {
65325 if(channelContext == NULL || message == NULL || signature == NULL)
65326 return UA_STATUSCODE_BADINTERNALERROR;
65327
65328 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65329 return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature);
65330}
65331
65332static UA_StatusCode
65333UA_SymSig_Basic256Sha256_sign(void *channelContext, const UA_ByteString *message,
65334 UA_ByteString *signature) {
65335 if(channelContext == NULL || message == NULL || signature == NULL)
65336 return UA_STATUSCODE_BADINTERNALERROR;
65337
65338 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65339 return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature);
65340}
65341
65342static size_t
65343UA_SymSig_Basic256Sha256_getLocalSignatureSize(const void * channelContext) {
65344 return UA_SHA256_LENGTH;
65345}
65346
65347static UA_StatusCode
65348UA_SymEn_Basic256Sha256_decrypt(void *channelContext, UA_ByteString *data) {
65349 if(channelContext == NULL || data == NULL)
65350 return UA_STATUSCODE_BADINTERNALERROR;
65351 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65352 return UA_OpenSSL_AES_256_CBC_Decrypt(iv: &cc->remoteSymIv,
65353 key: &cc->remoteSymEncryptingKey, data);
65354}
65355
65356static UA_StatusCode
65357UA_SymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) {
65358 if(channelContext == NULL || data == NULL)
65359 return UA_STATUSCODE_BADINTERNALERROR;
65360
65361 Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext;
65362 return UA_OpenSSL_AES_256_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data);
65363}
65364
65365static UA_StatusCode
65366UA_ChannelM_Basic256Sha256_compareCertificate(const void *channelContext,
65367 const UA_ByteString *certificate) {
65368 if(channelContext == NULL || certificate == NULL)
65369 return UA_STATUSCODE_BADINTERNALERROR;
65370
65371 const Channel_Context_Basic256Sha256 * cc =
65372 (const Channel_Context_Basic256Sha256 *) channelContext;
65373 return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509);
65374}
65375
65376static size_t
65377UA_AsymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) {
65378 if(channelContext == NULL)
65379 return UA_STATUSCODE_BADINTERNALERROR;
65380
65381 const Channel_Context_Basic256Sha256 * cc =
65382 (const Channel_Context_Basic256Sha256 *) channelContext;
65383 Policy_Context_Basic256Sha256 *pc = cc->policyContext;
65384 UA_Int32 keyLen = 0;
65385 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65386 return (size_t) keyLen * 8;
65387}
65388
65389/* the main entry of Basic256Sha256 */
65390
65391UA_StatusCode
65392UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy,
65393 const UA_ByteString localCertificate,
65394 const UA_ByteString localPrivateKey,
65395 const UA_Logger *logger) {
65396 UA_SecurityPolicyAsymmetricModule *asymmetricModule = &policy->asymmetricModule;
65397 UA_SecurityPolicySymmetricModule *symmetricModule = &policy->symmetricModule;
65398 UA_SecurityPolicyChannelModule *channelModule = &policy->channelModule;
65399 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65400 msg: "The basic256sha256 security policy with openssl is added.");
65401
65402 UA_Openssl_Init();
65403 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
65404 policy->logger = logger;
65405 policy->policyUri =
65406 UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\0");
65407
65408 /* Set ChannelModule context */
65409 channelModule->newContext = UA_ChannelModule_New_Context;
65410 channelModule->deleteContext = UA_ChannelModule_Delete_Context;
65411 channelModule->setLocalSymSigningKey =
65412 UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey;
65413 channelModule->setLocalSymEncryptingKey =
65414 UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey;
65415 channelModule->setLocalSymIv = UA_ChannelM_Basic256Sha256_setLocalSymIv;
65416 channelModule->setRemoteSymSigningKey =
65417 UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey;
65418 channelModule->setRemoteSymEncryptingKey =
65419 UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey;
65420 channelModule->setRemoteSymIv = UA_ChannelM_Basic256Sha256_setRemoteSymIv;
65421 channelModule->compareCertificate = UA_ChannelM_Basic256Sha256_compareCertificate;
65422 UA_StatusCode retval =
65423 UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
65424 if(retval != UA_STATUSCODE_GOOD)
65425 return retval;
65426
65427 /* AsymmetricModule - signature algorithm */
65428 UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
65429 &asymmetricModule->cryptoModule.signatureAlgorithm;
65430 asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
65431 asySigAlgorithm->verify = UA_AsySig_Basic256Sha256_Verify;
65432 asySigAlgorithm->sign = UA_AsySig_Basic256Sha256_sign;
65433 asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256Sha256_getLocalSignatureSize;
65434 asySigAlgorithm->getRemoteSignatureSize = UA_Asym_Basic256Sha256_getRemoteSignatureSize;
65435 asySigAlgorithm->getLocalKeyLength = NULL;
65436 asySigAlgorithm->getRemoteKeyLength = NULL;
65437
65438 /* AsymmetricModule encryption algorithm */
65439 UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
65440 &asymmetricModule->cryptoModule.encryptionAlgorithm;
65441 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
65442 asymEncryAlg->encrypt = UA_AsymEn_Basic256Sha256_encrypt;
65443 asymEncryAlg->decrypt = UA_Asym_Basic256Sha256_Decrypt;
65444 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256Sha256_getLocalKeyLength;
65445 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256Sha256_getRemoteKeyLength;
65446 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256Sha256_getRemoteBlockSize;
65447 asymEncryAlg->getRemotePlainTextBlockSize =
65448 UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize;
65449
65450 /* AsymmetricModule */
65451 asymmetricModule->compareCertificateThumbprint = UA_compareCertificateThumbprint;
65452 asymmetricModule->makeCertificateThumbprint = UA_makeCertificateThumbprint;
65453
65454 /* SymmetricModule */
65455 symmetricModule->secureChannelNonceLength = 32;
65456 symmetricModule->generateNonce = UA_Sym_Basic256Sha256_generateNonce;
65457 symmetricModule->generateKey = UA_Sym_Basic256Sha256_generateKey;
65458
65459 /* Symmetric encryption Algorithm */
65460 UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
65461 &symmetricModule->cryptoModule.encryptionAlgorithm;
65462 symEncryptionAlgorithm->uri =
65463 UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
65464 symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256Sha256_encrypt;
65465 symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256Sha256_decrypt;
65466 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256Sha256_getLocalKeyLength;
65467 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256Sha256_getRemoteKeyLength;
65468 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
65469 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256Sha256_getBlockSize;
65470
65471 /* Symmetric signature Algorithm */
65472 UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
65473 &symmetricModule->cryptoModule.signatureAlgorithm;
65474 symSignatureAlgorithm->uri =
65475 UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
65476 symSignatureAlgorithm->verify = UA_SymSig_Basic256Sha256_verify;
65477 symSignatureAlgorithm->sign = UA_SymSig_Basic256Sha256_sign;
65478 symSignatureAlgorithm->getLocalSignatureSize =
65479 UA_SymSig_Basic256Sha256_getLocalSignatureSize;
65480 symSignatureAlgorithm->getRemoteSignatureSize =
65481 UA_SymSig_Basic256Sha256_getRemoteSignatureSize;
65482 symSignatureAlgorithm->getLocalKeyLength =
65483 UA_SymSig_Basic256Sha256_getLocalKeyLength;
65484 symSignatureAlgorithm->getRemoteKeyLength =
65485 UA_SymSig_Basic256Sha256_getRemoteKeyLength;
65486
65487 policy->clear = UA_Policy_Clear_Context;
65488 retval = UA_Policy_New_Context(securityPolicy: policy, localPrivateKey, logger);
65489 if(retval != UA_STATUSCODE_GOOD) {
65490 UA_ByteString_clear(p: &policy->localCertificate);
65491 return retval;
65492 }
65493
65494 /* Use the same signature algorithm as the asymmetric component for
65495 * certificate signing (see standard) */
65496 policy->certificateSigningAlgorithm =
65497 policy->asymmetricModule.cryptoModule.signatureAlgorithm;
65498
65499 return UA_STATUSCODE_GOOD;
65500}
65501
65502#endif
65503
65504/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_aes128sha256rsaoaep.c" ****/
65505
65506/* This Source Code Form is subject to the terms of the Mozilla Public
65507 * License, v. 2.0. If a copy of the MPL was not distributed with this
65508 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
65509 *
65510 * Copyright 2020 (c) Wind River Systems, Inc.
65511 */
65512
65513
65514#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
65515
65516
65517#include <openssl/hmac.h>
65518#include <openssl/sha.h>
65519#include <openssl/rsa.h>
65520#include <openssl/x509.h>
65521#include <openssl/rand.h>
65522#include <openssl/rsa.h>
65523
65524#define UA_SHA256_LENGTH 32 /* 256 bit */
65525#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
65526#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
65527#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH 16
65528#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
65529#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
65530#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
65531#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
65532
65533typedef struct {
65534 EVP_PKEY *localPrivateKey;
65535 UA_ByteString localCertThumbprint;
65536 const UA_Logger *logger;
65537} Policy_Context_Aes128Sha256RsaOaep;
65538
65539typedef struct {
65540 UA_ByteString localSymSigningKey;
65541 UA_ByteString localSymEncryptingKey;
65542 UA_ByteString localSymIv;
65543 UA_ByteString remoteSymSigningKey;
65544 UA_ByteString remoteSymEncryptingKey;
65545 UA_ByteString remoteSymIv;
65546
65547 Policy_Context_Aes128Sha256RsaOaep *policyContext;
65548 UA_ByteString remoteCertificate;
65549 X509 *remoteCertificateX509; /* X509 */
65550} Channel_Context_Aes128Sha256RsaOaep;
65551
65552/* create the policy context */
65553
65554static UA_StatusCode
65555UA_Policy_Aes128Sha256RsaOaep_New_Context(UA_SecurityPolicy *securityPolicy,
65556 const UA_ByteString localPrivateKey,
65557 const UA_Logger *logger) {
65558 Policy_Context_Aes128Sha256RsaOaep *context =
65559 (Policy_Context_Aes128Sha256RsaOaep *)UA_malloc(
65560 size: sizeof(Policy_Context_Aes128Sha256RsaOaep));
65561 if(context == NULL) {
65562 return UA_STATUSCODE_BADOUTOFMEMORY;
65563 }
65564
65565 context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey);
65566 if (!context->localPrivateKey) {
65567 UA_free(ptr: context);
65568 return UA_STATUSCODE_BADINVALIDARGUMENT;
65569 }
65570
65571 UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint(
65572 certficate: &securityPolicy->localCertificate, pThumbprint: &context->localCertThumbprint, true);
65573 if(retval != UA_STATUSCODE_GOOD) {
65574 EVP_PKEY_free(pkey: context->localPrivateKey);
65575 UA_free(ptr: context);
65576 return retval;
65577 }
65578
65579 context->logger = logger;
65580 securityPolicy->policyContext = context;
65581
65582 return UA_STATUSCODE_GOOD;
65583}
65584
65585/* clear the policy context */
65586
65587static void
65588UA_Policy_Aes128Sha256RsaOaep_Clear_Context(UA_SecurityPolicy *policy) {
65589 if(policy == NULL)
65590 return;
65591
65592 UA_ByteString_clear(p: &policy->localCertificate);
65593
65594 /* delete all allocated members in the context */
65595
65596 Policy_Context_Aes128Sha256RsaOaep *pc =
65597 (Policy_Context_Aes128Sha256RsaOaep *)policy->policyContext;
65598 if (pc == NULL) {
65599 return;
65600 }
65601
65602 EVP_PKEY_free(pkey: pc->localPrivateKey);
65603 UA_ByteString_clear(p: &pc->localCertThumbprint);
65604 UA_free(ptr: pc);
65605
65606 return;
65607}
65608
65609/* create the channel context */
65610
65611static UA_StatusCode
65612UA_ChannelModule_Aes128Sha256RsaOaep_New_Context(const UA_SecurityPolicy *securityPolicy,
65613 const UA_ByteString *remoteCertificate,
65614 void **channelContext) {
65615 if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) {
65616 return UA_STATUSCODE_BADINTERNALERROR;
65617 }
65618 Channel_Context_Aes128Sha256RsaOaep *context =
65619 (Channel_Context_Aes128Sha256RsaOaep *)UA_malloc(
65620 size: sizeof(Channel_Context_Aes128Sha256RsaOaep));
65621 if(context == NULL) {
65622 return UA_STATUSCODE_BADOUTOFMEMORY;
65623 }
65624
65625 UA_ByteString_init(p: &context->localSymSigningKey);
65626 UA_ByteString_init(p: &context->localSymEncryptingKey);
65627 UA_ByteString_init(p: &context->localSymIv);
65628 UA_ByteString_init(p: &context->remoteSymSigningKey);
65629 UA_ByteString_init(p: &context->remoteSymEncryptingKey);
65630 UA_ByteString_init(p: &context->remoteSymIv);
65631
65632 UA_StatusCode retval =
65633 UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate);
65634 if(retval != UA_STATUSCODE_GOOD) {
65635 UA_free(ptr: context);
65636 return retval;
65637 }
65638
65639 /* decode to X509 */
65640 context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate);
65641 if (context->remoteCertificateX509 == NULL) {
65642 UA_ByteString_clear (p: &context->remoteCertificate);
65643 UA_free (ptr: context);
65644 return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE;
65645 }
65646
65647 context->policyContext =
65648 (Policy_Context_Aes128Sha256RsaOaep *)(securityPolicy->policyContext);
65649
65650 *channelContext = context;
65651
65652 UA_LOG_INFO(
65653 logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65654 msg: "The Aes128Sha256RsaOaep security policy channel with openssl is created.");
65655
65656 return UA_STATUSCODE_GOOD;
65657}
65658
65659/* delete the channel context */
65660
65661static void
65662UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context(void *channelContext) {
65663 if(channelContext != NULL) {
65664 Channel_Context_Aes128Sha256RsaOaep *cc =
65665 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65666 X509_free(a: cc->remoteCertificateX509);
65667 UA_ByteString_clear(p: &cc->remoteCertificate);
65668 UA_ByteString_clear(p: &cc->localSymSigningKey);
65669 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65670 UA_ByteString_clear(p: &cc->localSymIv);
65671 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65672 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65673 UA_ByteString_clear(p: &cc->remoteSymIv);
65674
65675 UA_LOG_INFO(
65676 logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
65677 msg: "The Aes128Sha256RsaOaep security policy channel with openssl is deleted.");
65678 UA_free(ptr: cc);
65679 }
65680}
65681
65682/* Verifies the signature of the message using the provided keys in the context.
65683 * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256
65684 */
65685
65686static UA_StatusCode
65687UA_AsySig_Aes128Sha256RsaOaep_Verify(void *channelContext, const UA_ByteString *message,
65688 const UA_ByteString *signature) {
65689 if(message == NULL || signature == NULL || channelContext == NULL) {
65690 return UA_STATUSCODE_BADINTERNALERROR;
65691 }
65692
65693 Channel_Context_Aes128Sha256RsaOaep *cc =
65694 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65695 UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(
65696 msg: message, publicKeyX509: cc->remoteCertificateX509, signature);
65697
65698 return retval;
65699}
65700
65701/* Compares the supplied certificate with the certificate
65702 * in the endpoint context
65703 */
65704
65705static UA_StatusCode
65706UA_compareCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
65707 const UA_ByteString *certificateThumbprint) {
65708 if(securityPolicy == NULL || certificateThumbprint == NULL) {
65709 return UA_STATUSCODE_BADINVALIDARGUMENT;
65710 }
65711 Policy_Context_Aes128Sha256RsaOaep *pc =
65712 (Policy_Context_Aes128Sha256RsaOaep *)securityPolicy->policyContext;
65713 if(!UA_ByteString_equal(string1: certificateThumbprint, string2: &pc->localCertThumbprint))
65714 return UA_STATUSCODE_BADCERTIFICATEINVALID;
65715 return UA_STATUSCODE_GOOD;
65716}
65717
65718/* Generates a thumbprint for the specified certificate */
65719
65720static UA_StatusCode
65721UA_makeCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy,
65722 const UA_ByteString *certificate,
65723 UA_ByteString *thumbprint) {
65724 return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false);
65725}
65726
65727static UA_StatusCode
65728UA_Asym_Aes128Sha256RsaOaep_Decrypt(void *channelContext, UA_ByteString *data) {
65729 if(channelContext == NULL || data == NULL)
65730 return UA_STATUSCODE_BADINVALIDARGUMENT;
65731
65732 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65733 UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey);
65734 return ret;
65735}
65736
65737static size_t
65738UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
65739 if(channelContext == NULL)
65740 return UA_STATUSCODE_BADINTERNALERROR;
65741
65742 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65743 UA_Int32 keyLen = 0;
65744 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65745 return (size_t)keyLen;
65746}
65747
65748static size_t
65749UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
65750 if(channelContext == NULL)
65751 return UA_STATUSCODE_BADINTERNALERROR;
65752
65753 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65754 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
65755 UA_Int32 keyLen = 0;
65756 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
65757 return (size_t)keyLen;
65758}
65759
65760static size_t
65761UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize(const void *channelContext) {
65762 if(channelContext == NULL)
65763 return UA_STATUSCODE_BADINTERNALERROR;
65764
65765 const Channel_Context_Aes128Sha256RsaOaep *cc =
65766 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65767 UA_Int32 keyLen = 0;
65768 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65769 return (size_t)keyLen - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
65770}
65771
65772static size_t
65773UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize(const void *channelContext) {
65774 if(channelContext == NULL)
65775 return UA_STATUSCODE_BADINTERNALERROR;
65776
65777 const Channel_Context_Aes128Sha256RsaOaep *cc =
65778 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65779 UA_Int32 keyLen = 0;
65780 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65781 return (size_t)keyLen;
65782}
65783
65784static size_t
65785UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65786 if(channelContext == NULL)
65787 return UA_STATUSCODE_BADINTERNALERROR;
65788
65789 const Channel_Context_Aes128Sha256RsaOaep *cc =
65790 (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65791 UA_Int32 keyLen = 0;
65792 UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen);
65793 return (size_t)keyLen * 8;
65794}
65795
65796static UA_StatusCode
65797UA_Sym_Aes128Sha256RsaOaep_generateNonce(void *policyContext,
65798 UA_ByteString *out) {
65799 UA_Int32 rc = RAND_bytes(buf: out->data, num: (int)out->length);
65800 if(rc != 1) {
65801 return UA_STATUSCODE_BADUNEXPECTEDERROR;
65802 }
65803 return UA_STATUSCODE_GOOD;
65804}
65805
65806static size_t
65807UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65808 /* 32 bytes 256 bits */
65809 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
65810}
65811
65812static size_t
65813UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65814 /* 32 bytes 256 bits */
65815 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
65816}
65817
65818static UA_StatusCode
65819UA_Sym_Aes128Sha256RsaOaep_generateKey(void *policyContext,
65820 const UA_ByteString *secret,
65821 const UA_ByteString *seed, UA_ByteString *out) {
65822 return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out);
65823}
65824
65825static UA_StatusCode
65826UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey(void *channelContext,
65827 const UA_ByteString *key) {
65828 if(key == NULL || channelContext == NULL)
65829 return UA_STATUSCODE_BADINTERNALERROR;
65830 Channel_Context_Aes128Sha256RsaOaep *cc =
65831 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65832 UA_ByteString_clear(p: &cc->localSymSigningKey);
65833 return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey);
65834}
65835
65836static UA_StatusCode
65837UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey(void *channelContext,
65838 const UA_ByteString *key) {
65839 if(key == NULL || channelContext == NULL)
65840 return UA_STATUSCODE_BADINTERNALERROR;
65841 Channel_Context_Aes128Sha256RsaOaep *cc =
65842 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65843 UA_ByteString_clear(p: &cc->localSymEncryptingKey);
65844 return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey);
65845}
65846
65847static UA_StatusCode
65848UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv(void *channelContext,
65849 const UA_ByteString *iv) {
65850 if(iv == NULL || channelContext == NULL)
65851 return UA_STATUSCODE_BADINTERNALERROR;
65852 Channel_Context_Aes128Sha256RsaOaep *cc =
65853 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65854 UA_ByteString_clear(p: &cc->localSymIv);
65855 return UA_ByteString_copy(src: iv, dst: &cc->localSymIv);
65856}
65857
65858static size_t
65859UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65860 /* 32 bytes 256 bits */
65861 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH;
65862}
65863
65864static size_t
65865UA_SymEn_Aes128Sha256RsaOaep_getBlockSize(const void *channelContext) {
65866 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
65867}
65868
65869static size_t
65870UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) {
65871 /* 32 bytes 256 bits */
65872 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
65873}
65874
65875static UA_StatusCode
65876UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey(void *channelContext,
65877 const UA_ByteString *key) {
65878 if(key == NULL || channelContext == NULL)
65879 return UA_STATUSCODE_BADINTERNALERROR;
65880 Channel_Context_Aes128Sha256RsaOaep *cc =
65881 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65882 UA_ByteString_clear(p: &cc->remoteSymSigningKey);
65883 return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey);
65884}
65885
65886static UA_StatusCode
65887UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey(void *channelContext,
65888 const UA_ByteString *key) {
65889 if(key == NULL || channelContext == NULL)
65890 return UA_STATUSCODE_BADINTERNALERROR;
65891 Channel_Context_Aes128Sha256RsaOaep *cc =
65892 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65893 UA_ByteString_clear(p: &cc->remoteSymEncryptingKey);
65894 return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey);
65895}
65896
65897static UA_StatusCode
65898UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv(void *channelContext,
65899 const UA_ByteString *key) {
65900 if(key == NULL || channelContext == NULL)
65901 return UA_STATUSCODE_BADINTERNALERROR;
65902 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65903 UA_ByteString_clear(p: &cc->remoteSymIv);
65904 return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv);
65905}
65906
65907static UA_StatusCode
65908UA_AsySig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
65909 UA_ByteString *signature) {
65910 if(channelContext == NULL || message == NULL ||
65911 signature == NULL)
65912 return UA_STATUSCODE_BADINTERNALERROR;
65913 Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65914 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
65915 return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature);
65916}
65917
65918static UA_StatusCode
65919UA_AsymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
65920 if(channelContext == NULL || data == NULL)
65921 return UA_STATUSCODE_BADINTERNALERROR;
65922 Channel_Context_Aes128Sha256RsaOaep *cc =
65923 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65924 return UA_Openssl_RSA_OAEP_Encrypt(
65925 data, UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN,
65926 publicX509: cc->remoteCertificateX509);
65927}
65928
65929static size_t
65930UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) {
65931 return UA_SHA256_LENGTH;
65932}
65933
65934static UA_StatusCode
65935UA_SymSig_Aes128Sha256RsaOaep_verify(void *channelContext, const UA_ByteString *message,
65936 const UA_ByteString *signature) {
65937 if(channelContext == NULL || message == NULL ||
65938 signature == NULL)
65939 return UA_STATUSCODE_BADINTERNALERROR;
65940
65941 Channel_Context_Aes128Sha256RsaOaep *cc =
65942 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65943 return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature);
65944}
65945
65946static UA_StatusCode
65947UA_SymSig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message,
65948 UA_ByteString *signature) {
65949 if(channelContext == NULL || message == NULL ||
65950 signature == NULL)
65951 return UA_STATUSCODE_BADINTERNALERROR;
65952
65953 Channel_Context_Aes128Sha256RsaOaep *cc =
65954 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65955 return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature);
65956}
65957
65958static size_t
65959UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) {
65960 return UA_SHA256_LENGTH;
65961}
65962
65963static UA_StatusCode
65964UA_SymEn_Aes128Sha256RsaOaep_decrypt(void *channelContext, UA_ByteString *data) {
65965 if(channelContext == NULL || data == NULL)
65966 return UA_STATUSCODE_BADINTERNALERROR;
65967 Channel_Context_Aes128Sha256RsaOaep *cc =
65968 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65969 return UA_OpenSSL_AES_128_CBC_Decrypt(iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey,
65970 data);
65971}
65972
65973static UA_StatusCode
65974UA_SymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) {
65975 if(channelContext == NULL || data == NULL)
65976 return UA_STATUSCODE_BADINTERNALERROR;
65977
65978 Channel_Context_Aes128Sha256RsaOaep *cc =
65979 (Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65980 return UA_OpenSSL_AES_128_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey,
65981 data);
65982}
65983
65984static UA_StatusCode
65985UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate(const void *channelContext,
65986 const UA_ByteString *certificate) {
65987 if(channelContext == NULL || certificate == NULL)
65988 return UA_STATUSCODE_BADINTERNALERROR;
65989
65990 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
65991 return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509);
65992}
65993
65994static size_t
65995UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) {
65996 if(channelContext == NULL)
65997 return UA_STATUSCODE_BADINTERNALERROR;
65998
65999 const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext;
66000 Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext;
66001 UA_Int32 keyLen = 0;
66002 UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen);
66003 return (size_t)keyLen * 8;
66004}
66005
66006/* the main entry of Aes128Sha256RsaOaep */
66007
66008UA_StatusCode
66009UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy,
66010 const UA_ByteString localCertificate,
66011 const UA_ByteString localPrivateKey,
66012 const UA_Logger *logger) {
66013
66014 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
66015 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
66016 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
66017 UA_StatusCode retval;
66018
66019 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY,
66020 msg: "The Aes128Sha256RsaOaep security policy with openssl is added.");
66021
66022 UA_Openssl_Init();
66023 memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy));
66024 policy->logger = logger;
66025 policy->policyUri =
66026 UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep\0");
66027
66028 /* set ChannelModule context */
66029
66030 channelModule->newContext = UA_ChannelModule_Aes128Sha256RsaOaep_New_Context;
66031 channelModule->deleteContext = UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context;
66032 channelModule->setLocalSymSigningKey =
66033 UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey;
66034 channelModule->setLocalSymEncryptingKey =
66035 UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey;
66036 channelModule->setLocalSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv;
66037 channelModule->setRemoteSymSigningKey =
66038 UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey;
66039 channelModule->setRemoteSymEncryptingKey =
66040 UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey;
66041 channelModule->setRemoteSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv;
66042 channelModule->compareCertificate =
66043 UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate;
66044
66045 /* Copy the certificate and add a NULL to the end */
66046
66047 retval = UA_copyCertificate(dst: &policy->localCertificate, src: &localCertificate);
66048 if(retval != UA_STATUSCODE_GOOD)
66049 return retval;
66050
66051 /* AsymmetricModule - signature algorithm */
66052
66053 UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm =
66054 &asymmetricModule->cryptoModule.signatureAlgorithm;
66055 asySigAlgorithm->uri =
66056 UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
66057 asySigAlgorithm->verify = UA_AsySig_Aes128Sha256RsaOaep_Verify;
66058 asySigAlgorithm->getRemoteSignatureSize =
66059 UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize;
66060 asySigAlgorithm->getLocalSignatureSize =
66061 UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize;
66062 asySigAlgorithm->sign = UA_AsySig_Aes128Sha256RsaOaep_sign;
66063 asySigAlgorithm->getLocalKeyLength = NULL;
66064 asySigAlgorithm->getRemoteKeyLength = NULL;
66065
66066 /* AsymmetricModule encryption algorithm */
66067
66068 UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg =
66069 &asymmetricModule->cryptoModule.encryptionAlgorithm;
66070 asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
66071 asymEncryAlg->decrypt = UA_Asym_Aes128Sha256RsaOaep_Decrypt;
66072 asymEncryAlg->getRemotePlainTextBlockSize =
66073 UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize;
66074 asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize;
66075 asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
66076 asymEncryAlg->encrypt = UA_AsymEn_Aes128Sha256RsaOaep_encrypt;
66077 asymEncryAlg->getLocalKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
66078
66079 /* asymmetricModule */
66080
66081 asymmetricModule->compareCertificateThumbprint =
66082 UA_compareCertificateThumbprint_Aes128Sha256RsaOaep;
66083 asymmetricModule->makeCertificateThumbprint =
66084 UA_makeCertificateThumbprint_Aes128Sha256RsaOaep;
66085
66086 /* SymmetricModule */
66087
66088 symmetricModule->secureChannelNonceLength = 32;
66089 symmetricModule->generateNonce = UA_Sym_Aes128Sha256RsaOaep_generateNonce;
66090 symmetricModule->generateKey = UA_Sym_Aes128Sha256RsaOaep_generateKey;
66091
66092 /* Symmetric encryption Algorithm */
66093
66094 UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm =
66095 &symmetricModule->cryptoModule.encryptionAlgorithm;
66096 symEncryptionAlgorithm->uri =
66097 UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0");
66098 symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength;
66099 symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength;
66100 symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
66101 symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize;
66102 symEncryptionAlgorithm->decrypt = UA_SymEn_Aes128Sha256RsaOaep_decrypt;
66103 symEncryptionAlgorithm->encrypt = UA_SymEn_Aes128Sha256RsaOaep_encrypt;
66104
66105 /* Symmetric signature Algorithm */
66106
66107 UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm =
66108 &symmetricModule->cryptoModule.signatureAlgorithm;
66109 symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0");
66110 symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength;
66111 symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength;
66112 symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize;
66113 symSignatureAlgorithm->verify = UA_SymSig_Aes128Sha256RsaOaep_verify;
66114 symSignatureAlgorithm->sign = UA_SymSig_Aes128Sha256RsaOaep_sign;
66115 symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize;
66116
66117 retval = UA_Policy_Aes128Sha256RsaOaep_New_Context(securityPolicy: policy, localPrivateKey, logger);
66118 if(retval != UA_STATUSCODE_GOOD) {
66119 UA_ByteString_clear(p: &policy->localCertificate);
66120 return retval;
66121 }
66122 policy->clear = UA_Policy_Aes128Sha256RsaOaep_Clear_Context;
66123
66124 /* Use the same signature algorithm as the asymmetric component for
66125 certificate signing (see standard) */
66126
66127 policy->certificateSigningAlgorithm =
66128 policy->asymmetricModule.cryptoModule.signatureAlgorithm;
66129
66130 return UA_STATUSCODE_GOOD;
66131}
66132
66133#endif
66134
66135/**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_create_certificate.c" ****/
66136
66137/* This Source Code Form is subject to the terms of the Mozilla Public
66138 * License, v. 2.0. If a copy of the MPL was not distributed with this
66139 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
66140 *
66141 * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati)
66142 * Copyright 2022 (c) Wind River Systems, Inc.
66143 *
66144 */
66145
66146
66147
66148#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
66149
66150
66151#include <openssl/pem.h>
66152#include <openssl/x509v3.h>
66153
66154/**
66155 * Join an array of UA_String to a single NULL-Terminated UA_String
66156 * separated by character sep
66157 */
66158static UA_StatusCode
66159join_string_with_sep(const UA_String *strings, size_t stringsSize,
66160 char sep, UA_String *out) {
66161 if(!out)
66162 return UA_STATUSCODE_BADINVALIDARGUMENT;
66163
66164 UA_String_clear(p: out);
66165 size_t totalSize = stringsSize;
66166 for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
66167 totalSize += strings[iStr].length;
66168 }
66169
66170 UA_ByteString_allocBuffer(bs: out, length: totalSize);
66171 if(!out->data) {
66172 return UA_STATUSCODE_BADOUTOFMEMORY;
66173 }
66174
66175 size_t pos = 0;
66176 for(size_t iStr = 0; iStr < stringsSize; ++iStr) {
66177 memcpy(dest: &out->data[pos], src: strings[iStr].data, n: strings[iStr].length);
66178 pos += strings[iStr].length;
66179 out->data[pos] = (UA_Byte) sep;
66180 ++pos;
66181 }
66182 out->data[out->length-1] = 0;
66183
66184 return UA_STATUSCODE_GOOD;
66185}
66186
66187/**
66188 * Search for a character in a string (like strchr).
66189 * \todo Handle UTF-8
66190 *
66191 * \return index of the character or -1 on case of an error.
66192 */
66193
66194static UA_Int32
66195UA_String_chr(const UA_String *pUaStr, char needl) {
66196 UA_Byte byteNeedl = (UA_Byte)needl;
66197 for(size_t i = 0; (size_t)i < pUaStr->length; ++i) {
66198 if(pUaStr->data[i] == byteNeedl) {
66199 return (UA_Int32) i;
66200 }
66201 }
66202 return -1;
66203}
66204
66205static UA_StatusCode
66206add_x509V3ext(X509 *x509, int nid, const char *value) {
66207 X509_EXTENSION *ex;
66208 X509V3_CTX ctx;
66209 X509V3_set_ctx_nodb(&ctx);
66210 X509V3_set_ctx(ctx: &ctx, issuer: x509, subject: x509, NULL, NULL, flags: 0);
66211 ex = X509V3_EXT_conf_nid(NULL, ctx: &ctx, ext_nid: nid, value);
66212 if(!ex)
66213 return UA_STATUSCODE_BADINTERNALERROR;
66214 X509_add_ext(x: x509, ex, loc: -1);
66215 X509_EXTENSION_free(a: ex);
66216 return UA_STATUSCODE_GOOD;
66217}
66218
66219#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
66220
66221/* generate the RSA key */
66222
66223static EVP_PKEY * UA_RSA_Generate_Key (size_t keySizeBits){
66224 return EVP_RSA_gen(keySizeBits);
66225}
66226
66227#endif
66228
66229UA_StatusCode
66230UA_CreateCertificate(const UA_Logger *logger,
66231 const UA_String *subject, size_t subjectSize,
66232 const UA_String *subjectAltName, size_t subjectAltNameSize,
66233 size_t keySizeBits, UA_CertificateFormat certFormat,
66234 UA_ByteString *outPrivateKey, UA_ByteString *outCertificate) {
66235 if(!outPrivateKey || !outCertificate || !logger || !subjectAltName ||
66236 !subject || subjectAltNameSize == 0 || subjectSize == 0 ||
66237 (certFormat != UA_CERTIFICATEFORMAT_DER && certFormat != UA_CERTIFICATEFORMAT_PEM ))
66238 return UA_STATUSCODE_BADINVALIDARGUMENT;
66239
66240 /* Use the maximum size */
66241 if(keySizeBits == 0)
66242 keySizeBits = 4096;
66243
66244 UA_ByteString_init(p: outPrivateKey);
66245 UA_ByteString_init(p: outCertificate);
66246
66247 UA_String fullAltSubj = UA_STRING_NULL;
66248 UA_Int32 serial = 1;
66249
66250 /** \TODO: Seed Random generator
66251 * See: (https://www.openssl.org/docs/man1.1.0/man3/RAND_add.html) */
66252 BIO *memCert = NULL;
66253 BIO *memPKey = NULL;
66254
66255 UA_StatusCode errRet = UA_STATUSCODE_GOOD;
66256
66257 X509 *x509 = X509_new();
66258
66259#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
66260 EVP_PKEY *pkey = UA_RSA_Generate_Key(keySizeBits);
66261 if((pkey == NULL) || (x509 == NULL)) {
66262 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66263 goto cleanup;
66264 }
66265#else
66266 BIGNUM *exponent = BN_new();
66267 EVP_PKEY *pkey = EVP_PKEY_new();
66268 RSA *rsa = RSA_new();
66269 if(!pkey || !x509 || !exponent || !rsa) {
66270 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66271 goto cleanup;
66272 }
66273
66274 UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURECHANNEL,
66275 "Create Certificate: Generating RSA key. This may take a while.");
66276
66277 if(BN_set_word(exponent, RSA_F4) != 1) {
66278 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66279 "Create Certificate: Setting RSA exponent failed.");
66280 errRet = UA_STATUSCODE_BADINTERNALERROR;
66281 goto cleanup;
66282 }
66283
66284 if(RSA_generate_key_ex(rsa, (int) keySizeBits, exponent, NULL) != 1) {
66285 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66286 "Create Certificate: Generating RSA key failed.");
66287 errRet = UA_STATUSCODE_BADINTERNALERROR;
66288 goto cleanup;
66289 }
66290
66291 if(EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
66292 UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL,
66293 "Create Certificate: Assign RSA key failed.");
66294 errRet = UA_STATUSCODE_BADINTERNALERROR;
66295 goto cleanup;
66296 }
66297 /* rsa will be freed by pkey */
66298 rsa = NULL;
66299
66300#endif /* end of OPENSSL_VERSION_NUMBER >= 0x30000000L */
66301
66302 /* x509v3 has version 2
66303 * (https://www.openssl.org/docs/man1.1.0/man3/X509_set_version.html) */
66304 if(X509_set_version(x: x509, version: 2) != 1) {
66305 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66306 msg: "Create Certificate: Setting version failed.");
66307 errRet = UA_STATUSCODE_BADINTERNALERROR;
66308 goto cleanup;
66309 }
66310
66311 if(ASN1_INTEGER_set(a: X509_get_serialNumber(x: x509), v: serial) != 1) {
66312 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66313 msg: "Create Certificate: Setting serial number failed.");
66314 /* Only memory errors are possible */
66315 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66316 goto cleanup;
66317 }
66318
66319 if(X509_gmtime_adj(X509_get_notBefore(x: x509), adj: 0) == NULL) {
66320 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66321 msg: "Create Certificate: Setting 'not before' failed.");
66322 errRet = UA_STATUSCODE_BADINTERNALERROR;
66323 goto cleanup;
66324 }
66325
66326 if(X509_gmtime_adj(X509_get_notAfter(x: x509), adj: (UA_Int64) 60 * 60 * 24 * 365) == NULL) {
66327 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66328 msg: "Create Certificate: Setting 'not before' failed.");
66329 errRet = UA_STATUSCODE_BADINTERNALERROR;
66330 goto cleanup;
66331 }
66332
66333 if(X509_set_pubkey(x: x509, pkey) != 1) {
66334 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66335 msg: "Create Certificate: Setting publik key failed.");
66336 errRet = UA_STATUSCODE_BADINTERNALERROR;
66337 goto cleanup;
66338 }
66339
66340 X509_NAME *name = X509_get_subject_name(a: x509);
66341 if(name == NULL) {
66342 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66343 msg: "Create Certificate: Getting name failed.");
66344 errRet = UA_STATUSCODE_BADINTERNALERROR;
66345 goto cleanup;
66346 }
66347
66348 for(UA_UInt32 iSubject = 0; iSubject < subjectSize; ++iSubject) {
66349 UA_Int32 sep = UA_String_chr(pUaStr: &subject[iSubject], needl: '=');
66350 char field[16];
66351 if(sep == -1 || sep == 0 ||
66352 ((size_t) sep == (subject[iSubject].length - 1)) || sep >= 15) {
66353 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66354 msg: "Create Certificate: Subject must contain one '=' with "
66355 "content before and after.");
66356 errRet = UA_STATUSCODE_BADINTERNALERROR;
66357 goto cleanup;
66358 }
66359 memcpy(dest: field, src: subject[iSubject].data, n: (size_t) sep);
66360 field[sep] = 0;
66361 UA_Byte* pData = &subject[iSubject].data[sep + 1];
66362 if(X509_NAME_add_entry_by_txt(
66363 name, field, MBSTRING_ASC,
66364 bytes: (const unsigned char *)pData,
66365 len: (int) subject[iSubject].length - (int) sep - 1, loc: -1, set: 0) != 1) {
66366 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66367 msg: "Create Certificate: Setting subject failed.");
66368 errRet = UA_STATUSCODE_BADINTERNALERROR;
66369 goto cleanup;
66370 }
66371 }
66372 /* Self signed, so issuer == subject */
66373 if(X509_set_issuer_name(x: x509, name) != 1) {
66374 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66375 msg: "Create Certificate: Setting name failed.");
66376 errRet = UA_STATUSCODE_BADINTERNALERROR;
66377 goto cleanup;
66378 }
66379
66380 errRet = add_x509V3ext(x509, NID_basic_constraints, value: "CA:FALSE");
66381 if(errRet != UA_STATUSCODE_GOOD) {
66382 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66383 msg: "Create Certificate: Setting 'Basic Constraints' failed.");
66384 goto cleanup;
66385 }
66386
66387 /* See https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3 for
66388 * possible values */
66389 errRet = add_x509V3ext(x509, NID_key_usage,
66390 value: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyCertSign");
66391 if(errRet != UA_STATUSCODE_GOOD) {
66392 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66393 msg: "Create Certificate: Setting 'Key Usage' failed.");
66394 goto cleanup;
66395 }
66396
66397 errRet = add_x509V3ext(x509, NID_ext_key_usage, value: "serverAuth,clientAuth");
66398 if(errRet != UA_STATUSCODE_GOOD) {
66399 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66400 msg: "Create Certificate: Setting 'Extended Key Usage' failed.");
66401 goto cleanup;
66402 }
66403
66404 errRet = add_x509V3ext(x509, NID_subject_key_identifier, value: "hash");
66405 if(errRet != UA_STATUSCODE_GOOD) {
66406 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66407 msg: "Create Certificate: Setting 'Subject Key Identifier' failed.");
66408 goto cleanup;
66409 }
66410
66411 errRet = join_string_with_sep(strings: subjectAltName, stringsSize: subjectAltNameSize, sep: ',', out: &fullAltSubj);
66412 if(errRet != UA_STATUSCODE_GOOD) {
66413 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66414 msg: "Create Certificate: Joining altSubject failed.");
66415 goto cleanup;
66416 }
66417
66418 errRet = add_x509V3ext(x509, NID_subject_alt_name, value: (const char*) fullAltSubj.data);
66419 if(errRet != UA_STATUSCODE_GOOD) {
66420 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66421 msg: "Create Certificate: Setting 'Subject Alternative Name:' failed.");
66422 goto cleanup;
66423 }
66424
66425 if(X509_sign(x: x509, pkey, md: EVP_sha256()) == 0) {
66426 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66427 msg: "Create Certificate: Signing failed.");
66428 errRet = UA_STATUSCODE_BADINTERNALERROR;
66429 goto cleanup;
66430 }
66431
66432 switch(certFormat) {
66433 case UA_CERTIFICATEFORMAT_DER: {
66434 int tmpLen = i2d_PrivateKey(a: pkey, pp: &outPrivateKey->data);
66435 if(tmpLen <= 0) {
66436 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66437 msg: "Create Certificate: Create private DER key failed.");
66438 errRet = UA_STATUSCODE_BADINTERNALERROR;
66439 goto cleanup;
66440 }
66441 outPrivateKey->length = (size_t) tmpLen;
66442
66443 tmpLen = i2d_X509(a: x509, out: &outCertificate->data);
66444 if(tmpLen <= 0) {
66445 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66446 msg: "Create Certificate: Create DER-certificate failed.");
66447 errRet = UA_STATUSCODE_BADINTERNALERROR;
66448 goto cleanup;
66449 }
66450 outCertificate->length = (size_t) tmpLen;
66451 break;
66452 }
66453 case UA_CERTIFICATEFORMAT_PEM: {
66454 /* Private Key */
66455 memPKey = BIO_new(type: BIO_s_mem());
66456 if(!memPKey) {
66457 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66458 msg: "Create Certificate: Allocate Membuffer for PKey failed.");
66459 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66460 goto cleanup;
66461 }
66462
66463 if(PEM_write_bio_PrivateKey(out: memPKey, x: pkey, NULL, NULL, klen: 0, cb: 0, NULL) != 1) {
66464 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66465 msg: "Create Certificate: Generate PEM-PrivateKey failed.");
66466 errRet = UA_STATUSCODE_BADINTERNALERROR;
66467 goto cleanup;
66468 }
66469
66470 UA_ByteString tmpPem = UA_BYTESTRING_NULL;
66471 tmpPem.length = (size_t) BIO_get_mem_data(memPKey, &tmpPem.data);
66472 errRet = UA_ByteString_copy(src: &tmpPem, dst: outPrivateKey);
66473 if(errRet != UA_STATUSCODE_GOOD) {
66474 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66475 msg: "Create Certificate: Copy PEM PKey failed.");
66476 goto cleanup;
66477 }
66478
66479 /* Certificate */
66480 memCert = BIO_new(type: BIO_s_mem());
66481 if(!memCert) {
66482 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66483 msg: "Create Certificate: Allocate Membuffer for Cert failed.");
66484 errRet = UA_STATUSCODE_BADOUTOFMEMORY;
66485 goto cleanup;
66486 }
66487
66488 if(PEM_write_bio_X509(out: memCert, x: x509) != 1) {
66489 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66490 msg: "Create Certificate: Generate PEM-Certifcate failed.");
66491 errRet = UA_STATUSCODE_BADINTERNALERROR;
66492 goto cleanup;
66493 }
66494
66495 tmpPem.length = (size_t) BIO_get_mem_data(memCert, &tmpPem.data);
66496 errRet = UA_ByteString_copy(src: &tmpPem, dst: outCertificate);
66497 if(errRet != UA_STATUSCODE_GOOD) {
66498 UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL,
66499 msg: "Create Certificate: Copy PEM Certificate failed.");
66500 goto cleanup;
66501 }
66502 break;
66503 }
66504 }
66505
66506cleanup:
66507 UA_String_clear(p: &fullAltSubj);
66508#if (OPENSSL_VERSION_NUMBER < 0x30000000L)
66509 RSA_free(rsa);
66510 BN_free(exponent);
66511#endif
66512 X509_free(a: x509);
66513 EVP_PKEY_free(pkey);
66514 BIO_free(a: memCert);
66515 BIO_free(a: memPKey);
66516 return errRet;
66517}
66518
66519#endif
66520
66521/**** amalgamated original file "/plugins/crypto/openssl/ua_pki_openssl.c" ****/
66522
66523/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
66524 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
66525 *
66526 * Copyright 2020 (c) Wind River Systems, Inc.
66527 * Copyright 2020 (c) basysKom GmbH
66528
66529 */
66530
66531
66532
66533#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
66534#include <openssl/x509.h>
66535#include <openssl/x509_vfy.h>
66536#include <openssl/x509v3.h>
66537#include <openssl/pem.h>
66538
66539
66540/* Find binary substring. Taken and adjusted from
66541 * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
66542
66543static const unsigned char *
66544bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
66545 /* find first occurrence of c in char s[] for length l*/
66546 for(; l > 0; ++s, --l) {
66547 if(*s == ch)
66548 return s;
66549 }
66550 return NULL;
66551}
66552
66553static const unsigned char *
66554UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
66555 /* find first occurrence of s2[] in s1[] for length l1*/
66556 const unsigned char *ss1 = s1;
66557 const unsigned char *ss2 = s2;
66558 /* handle special case */
66559 if(l1 == 0)
66560 return (NULL);
66561 if(l2 == 0)
66562 return s1;
66563
66564 /* match prefix */
66565 for (; (s1 = bstrchr(s: s1, ch: *s2, l: (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
66566 (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
66567
66568 /* match rest of prefix */
66569 const unsigned char *sc1, *sc2;
66570 for (sc1 = s1, sc2 = s2; ;)
66571 if (++sc2 >= ss2+l2)
66572 return s1;
66573 else if (*++sc1 != *sc2)
66574 break;
66575 }
66576 return NULL;
66577}
66578
66579typedef struct {
66580 /*
66581 * If the folders are defined, we use them to reload the certificates during
66582 * runtime
66583 */
66584
66585 UA_String trustListFolder;
66586 UA_String issuerListFolder;
66587 UA_String revocationListFolder;
66588
66589 STACK_OF(X509) * skIssue;
66590 STACK_OF(X509) * skTrusted;
66591 STACK_OF(X509_CRL) * skCrls; /* Revocation list*/
66592} CertContext;
66593
66594static UA_StatusCode
66595UA_CertContext_sk_Init (CertContext * context) {
66596 context->skTrusted = sk_X509_new_null();
66597 context->skIssue = sk_X509_new_null();
66598 context->skCrls = sk_X509_CRL_new_null();
66599 if (context->skTrusted == NULL || context->skIssue == NULL ||
66600 context->skCrls == NULL) {
66601 return UA_STATUSCODE_BADOUTOFMEMORY;
66602 }
66603 return UA_STATUSCODE_GOOD;
66604}
66605
66606static void
66607UA_CertContext_sk_free (CertContext * context) {
66608 sk_X509_pop_free (context->skTrusted, X509_free);
66609 sk_X509_pop_free (context->skIssue, X509_free);
66610 sk_X509_CRL_pop_free (context->skCrls, X509_CRL_free);
66611}
66612
66613static UA_StatusCode
66614UA_CertContext_Init (CertContext * context) {
66615 (void) memset (s: context, c: 0, n: sizeof (CertContext));
66616 UA_ByteString_init (p: &context->trustListFolder);
66617 UA_ByteString_init (p: &context->issuerListFolder);
66618 UA_ByteString_init (p: &context->revocationListFolder);
66619 return UA_CertContext_sk_Init (context);
66620}
66621
66622static void
66623UA_CertificateVerification_clear (UA_CertificateVerification * cv) {
66624 if (cv == NULL) {
66625 return ;
66626 }
66627 CertContext * context = (CertContext *) cv->context;
66628 if (context == NULL) {
66629 return;
66630 }
66631 UA_ByteString_clear (p: &context->trustListFolder);
66632 UA_ByteString_clear (p: &context->issuerListFolder);
66633 UA_ByteString_clear (p: &context->revocationListFolder);
66634
66635 UA_CertContext_sk_free (context);
66636 UA_free (ptr: context);
66637
66638 cv->context = NULL;
66639
66640 return;
66641}
66642
66643static UA_StatusCode
66644UA_skTrusted_Cert2X509 (const UA_ByteString * certificateTrustList,
66645 size_t certificateTrustListSize,
66646 CertContext * ctx) {
66647 size_t i;
66648
66649 for (i = 0; i < certificateTrustListSize; i++) {
66650 X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateTrustList[i]);
66651
66652 if (x509 == NULL) {
66653 return UA_STATUSCODE_BADINTERNALERROR;
66654 }
66655 sk_X509_push (ctx->skTrusted, x509);
66656 }
66657
66658 return UA_STATUSCODE_GOOD;
66659}
66660
66661static UA_StatusCode
66662UA_skIssuer_Cert2X509 (const UA_ByteString * certificateIssuerList,
66663 size_t certificateIssuerListSize,
66664 CertContext * ctx) {
66665 size_t i;
66666
66667 for (i = 0; i < certificateIssuerListSize; i++) {
66668 X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateIssuerList[i]);
66669
66670 if (x509 == NULL) {
66671 return UA_STATUSCODE_BADINTERNALERROR;
66672 }
66673 sk_X509_push (ctx->skIssue, x509);
66674 }
66675
66676 return UA_STATUSCODE_GOOD;
66677}
66678
66679static UA_StatusCode
66680UA_skCrls_Cert2X509 (const UA_ByteString * certificateRevocationList,
66681 size_t certificateRevocationListSize,
66682 CertContext * ctx) {
66683 size_t i;
66684 const unsigned char * pData;
66685
66686 for (i = 0; i < certificateRevocationListSize; i++) {
66687 pData = certificateRevocationList[i].data;
66688 X509_CRL * crl = NULL;
66689
66690 if (certificateRevocationList[i].length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files
66691 crl = d2i_X509_CRL (NULL, in: &pData, len: (long) certificateRevocationList[i].length);
66692 } else {
66693 BIO* bio = NULL;
66694 bio = BIO_new_mem_buf(buf: (void *) certificateRevocationList[i].data,
66695 len: (int) certificateRevocationList[i].length);
66696 crl = PEM_read_bio_X509_CRL(out: bio, NULL, NULL, NULL);
66697 BIO_free(a: bio);
66698 }
66699
66700 if (crl == NULL) {
66701 return UA_STATUSCODE_BADINTERNALERROR;
66702 }
66703 sk_X509_CRL_push (ctx->skCrls, crl);
66704 }
66705
66706 return UA_STATUSCODE_GOOD;
66707}
66708
66709#ifdef __linux__
66710#include <dirent.h>
66711
66712static int UA_Certificate_Filter_der_pem (const struct dirent * entry) {
66713 /* ignore hidden files */
66714 if (entry->d_name[0] == '.') return 0;
66715
66716 /* check file extension */
66717 const char *pszFind = strrchr(s: entry->d_name, c: '.');
66718 if (pszFind == 0)
66719 return 0;
66720 pszFind++;
66721 if (strcmp (s1: pszFind, s2: "der") == 0 || strcmp (s1: pszFind, s2: "pem") == 0)
66722 return 1;
66723
66724 return 0;
66725}
66726
66727static int UA_Certificate_Filter_crl (const struct dirent * entry) {
66728
66729 /* ignore hidden files */
66730 if (entry->d_name[0] == '.') return 0;
66731
66732 /* check file extension */
66733 const char *pszFind = strrchr(s: entry->d_name, c: '.');
66734 if (pszFind == 0)
66735 return 0;
66736 pszFind++;
66737 if (strcmp (s1: pszFind, s2: "crl") == 0)
66738 return 1;
66739
66740 return 0;
66741}
66742
66743static UA_StatusCode
66744UA_BuildFullPath (const char * path,
66745 const char * fileName,
66746 size_t fullPathBufferLength,
66747 char * fullPath) {
66748 size_t pathLen = strlen (s: path);
66749 size_t fileNameLen = strlen (s: fileName);
66750 if ((pathLen + fileNameLen + 2) > fullPathBufferLength) {
66751 return UA_STATUSCODE_BADINVALIDARGUMENT;
66752 }
66753 strcpy (dest: fullPath, src: path);
66754 strcat (dest: fullPath, src: "/");
66755 strcat (dest: fullPath, src: fileName);
66756
66757 return UA_STATUSCODE_GOOD;
66758}
66759
66760static UA_StatusCode
66761UA_loadCertFromFile (const char * fileName,
66762 UA_ByteString * cert) {
66763
66764 FILE * fp = fopen(filename: fileName, modes: "rb");
66765
66766 if (fp == NULL)
66767 return UA_STATUSCODE_BADINTERNALERROR;
66768
66769 fseek(stream: fp, off: 0, SEEK_END);
66770 cert->length = (size_t) ftell(stream: fp);
66771 if (UA_ByteString_allocBuffer (bs: cert, length: cert->length) != UA_STATUSCODE_GOOD) {
66772 fclose (stream: fp);
66773 return UA_STATUSCODE_BADOUTOFMEMORY;
66774 }
66775 fseek(stream: fp, off: 0, SEEK_SET);
66776 size_t readLen = fread (ptr: cert->data, size: 1, n: cert->length, stream: fp);
66777 if (readLen != cert->length) {
66778 UA_ByteString_clear (p: cert);
66779 cert->length = 0;
66780 fclose (stream: fp);
66781 return UA_STATUSCODE_BADINTERNALERROR;
66782 }
66783 fclose (stream: fp);
66784
66785 return UA_STATUSCODE_GOOD;
66786}
66787
66788static UA_StatusCode
66789UA_ReloadCertFromFolder (CertContext * ctx) {
66790 UA_StatusCode ret;
66791 struct dirent ** dirlist = NULL;
66792 int i;
66793 int numCertificates;
66794 char certFile[PATH_MAX];
66795 UA_ByteString strCert;
66796 char folderPath[PATH_MAX];
66797
66798 UA_ByteString_init (p: &strCert);
66799
66800 if (ctx->trustListFolder.length > 0) {
66801 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the trust-list");
66802
66803 sk_X509_pop_free (ctx->skTrusted, X509_free);
66804 ctx->skTrusted = sk_X509_new_null();
66805 if (ctx->skTrusted == NULL) {
66806 return UA_STATUSCODE_BADOUTOFMEMORY;
66807 }
66808
66809 (void) memcpy (dest: folderPath, src: ctx->trustListFolder.data,
66810 n: ctx->trustListFolder.length);
66811 folderPath[ctx->trustListFolder.length] = 0;
66812 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66813 selector: UA_Certificate_Filter_der_pem,
66814 cmp: alphasort);
66815 for (i = 0; i < numCertificates; i++) {
66816 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66817 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66818 continue;
66819 }
66820 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66821 if (ret != UA_STATUSCODE_GOOD) {
66822 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66823 msg: "Failed to load the certificate file %s", certFile);
66824 continue; /* continue or return ? */
66825 }
66826 if (UA_skTrusted_Cert2X509 (certificateTrustList: &strCert, certificateTrustListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66827 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66828 msg: "Failed to decode the certificate file %s", certFile);
66829 UA_ByteString_clear (p: &strCert);
66830 continue; /* continue or return ? */
66831 }
66832 UA_ByteString_clear (p: &strCert);
66833 }
66834 }
66835
66836 if (ctx->issuerListFolder.length > 0) {
66837 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the issuer-list");
66838
66839 sk_X509_pop_free (ctx->skIssue, X509_free);
66840 ctx->skIssue = sk_X509_new_null();
66841 if (ctx->skIssue == NULL) {
66842 return UA_STATUSCODE_BADOUTOFMEMORY;
66843 }
66844
66845 memcpy (dest: folderPath, src: ctx->issuerListFolder.data, n: ctx->issuerListFolder.length);
66846 folderPath[ctx->issuerListFolder.length] = 0;
66847 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66848 selector: UA_Certificate_Filter_der_pem,
66849 cmp: alphasort);
66850 for (i = 0; i < numCertificates; i++) {
66851 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66852 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66853 continue;
66854 }
66855 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66856 if (ret != UA_STATUSCODE_GOOD) {
66857 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66858 msg: "Failed to load the certificate file %s", certFile);
66859 continue; /* continue or return ? */
66860 }
66861 if (UA_skIssuer_Cert2X509 (certificateIssuerList: &strCert, certificateIssuerListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66862 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66863 msg: "Failed to decode the certificate file %s", certFile);
66864 UA_ByteString_clear (p: &strCert);
66865 continue; /* continue or return ? */
66866 }
66867 UA_ByteString_clear (p: &strCert);
66868 }
66869 }
66870
66871 if (ctx->revocationListFolder.length > 0) {
66872 UA_LOG_INFO(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the revocation-list");
66873
66874 sk_X509_CRL_pop_free (ctx->skCrls, X509_CRL_free);
66875 ctx->skCrls = sk_X509_CRL_new_null();
66876 if (ctx->skCrls == NULL) {
66877 return UA_STATUSCODE_BADOUTOFMEMORY;
66878 }
66879
66880 memcpy (dest: folderPath, src: ctx->revocationListFolder.data, n: ctx->revocationListFolder.length);
66881 folderPath[ctx->revocationListFolder.length] = 0;
66882 numCertificates = scandir(dir: folderPath, namelist: &dirlist,
66883 selector: UA_Certificate_Filter_crl,
66884 cmp: alphasort);
66885 for (i = 0; i < numCertificates; i++) {
66886 if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name,
66887 PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) {
66888 continue;
66889 }
66890 ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert);
66891 if (ret != UA_STATUSCODE_GOOD) {
66892 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66893 msg: "Failed to load the revocation file %s", certFile);
66894 continue; /* continue or return ? */
66895 }
66896 if (UA_skCrls_Cert2X509 (certificateRevocationList: &strCert, certificateRevocationListSize: 1, ctx) != UA_STATUSCODE_GOOD) {
66897 UA_LOG_INFO (logger: UA_Log_Stdout, category: UA_LOGCATEGORY_SERVER,
66898 msg: "Failed to decode the revocation file %s", certFile);
66899 UA_ByteString_clear (p: &strCert);
66900 continue; /* continue or return ? */
66901 }
66902 UA_ByteString_clear (p: &strCert);
66903 }
66904 }
66905
66906 ret = UA_STATUSCODE_GOOD;
66907 return ret;
66908}
66909
66910#endif /* end of __linux__ */
66911
66912static UA_StatusCode
66913UA_X509_Store_CTX_Error_To_UAError (int opensslErr) {
66914 UA_StatusCode ret;
66915
66916 switch (opensslErr) {
66917 case X509_V_ERR_CERT_HAS_EXPIRED:
66918 case X509_V_ERR_CERT_NOT_YET_VALID:
66919 case X509_V_ERR_CRL_NOT_YET_VALID:
66920 case X509_V_ERR_CRL_HAS_EXPIRED:
66921 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
66922 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
66923 case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
66924 case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
66925 ret = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
66926 break;
66927 case X509_V_ERR_CERT_REVOKED:
66928 ret = UA_STATUSCODE_BADCERTIFICATEREVOKED;
66929 break;
66930 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
66931 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
66932 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
66933 ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
66934 break;
66935 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
66936 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
66937 ret = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
66938 break;
66939 case X509_V_ERR_UNABLE_TO_GET_CRL:
66940 ret = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
66941 break;
66942 default:
66943 ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
66944 break;
66945 }
66946 return ret;
66947 }
66948
66949static UA_StatusCode
66950UA_CertificateVerification_Verify (void * verificationContext,
66951 const UA_ByteString * certificate) {
66952 X509_STORE_CTX* storeCtx;
66953 X509_STORE* store;
66954 CertContext * ctx;
66955 UA_StatusCode ret;
66956 int opensslRet;
66957 X509 * certificateX509 = NULL;
66958
66959 if (verificationContext == NULL) {
66960 return UA_STATUSCODE_BADINTERNALERROR;
66961 }
66962 ctx = (CertContext *) verificationContext;
66963
66964 store = X509_STORE_new();
66965 storeCtx = X509_STORE_CTX_new();
66966
66967 if (store == NULL || storeCtx == NULL) {
66968 ret = UA_STATUSCODE_BADOUTOFMEMORY;
66969 goto cleanup;
66970 }
66971#ifdef __linux__
66972 ret = UA_ReloadCertFromFolder (ctx);
66973 if (ret != UA_STATUSCODE_GOOD) {
66974 goto cleanup;
66975 }
66976#endif
66977
66978 certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
66979 if (certificateX509 == NULL) {
66980 ret = UA_STATUSCODE_BADCERTIFICATEINVALID;
66981 goto cleanup;
66982 }
66983
66984 X509_STORE_set_flags(ctx: store, flags: 0);
66985 opensslRet = X509_STORE_CTX_init (ctx: storeCtx, trust_store: store, target: certificateX509,
66986 untrusted: ctx->skIssue);
66987 if (opensslRet != 1) {
66988 ret = UA_STATUSCODE_BADINTERNALERROR;
66989 goto cleanup;
66990 }
66991#if defined(OPENSSL_API_COMPAT) && OPENSSL_API_COMPAT < 0x10100000L
66992 (void) X509_STORE_CTX_trusted_stack (storeCtx, ctx->skTrusted);
66993#else
66994 (void) X509_STORE_CTX_set0_trusted_stack (ctx: storeCtx, sk: ctx->skTrusted);
66995#endif
66996
66997 /* Set crls to ctx */
66998 if (sk_X509_CRL_num (ctx->skCrls) > 0) {
66999 X509_STORE_CTX_set0_crls (ctx: storeCtx, sk: ctx->skCrls);
67000 }
67001
67002 /* Set flag to check if the certificate has an invalid signature */
67003 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CHECK_SS_SIGNATURE);
67004
67005 if (X509_STORE_CTX_get_check_issued(ctx: storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
67006 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CRL_CHECK);
67007 }
67008
67009 /* This condition will check whether the certificate is a User certificate or a CA certificate.
67010 * If the KU_KEY_CERT_SIGN and KU_CRL_SIGN of key_usage are set, then the certificate shall be
67011 * condidered as CA Certificate and cannot be used to establish a connection. Refer the test case
67012 * CTT/Security/Security Certificate Validation/029.js for more details */
67013 /** \todo Can the ca-parameter of X509_check_purpose can be used? */
67014 if(X509_check_purpose(x: certificateX509, X509_PURPOSE_CRL_SIGN, ca: 0) && X509_check_ca(x: certificateX509)) {
67015 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
67016 }
67017
67018 opensslRet = X509_verify_cert (ctx: storeCtx);
67019 if (opensslRet == 1) {
67020 ret = UA_STATUSCODE_GOOD;
67021
67022 /* Check if the not trusted certificate has a CRL file. If there is no CRL file available for the corresponding
67023 * parent certificate then return status code UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN. Refer the test
67024 * case CTT/Security/Security Certificate Validation/002.js */
67025 if (X509_STORE_CTX_get_check_issued (ctx: storeCtx) (storeCtx,certificateX509, certificateX509) != 1) {
67026 /* Free X509_STORE_CTX and reuse it for certification verification */
67027 if (storeCtx != NULL) {
67028 X509_STORE_CTX_free(ctx: storeCtx);
67029 }
67030
67031 /* Initialised X509_STORE_CTX sructure*/
67032 storeCtx = X509_STORE_CTX_new();
67033
67034 /* Sets up X509_STORE_CTX structure for a subsequent verification operation */
67035 X509_STORE_set_flags(ctx: store, flags: 0);
67036 X509_STORE_CTX_init (ctx: storeCtx, trust_store: store, target: certificateX509,untrusted: ctx->skIssue);
67037
67038 /* Set trust list to ctx */
67039 (void) X509_STORE_CTX_trusted_stack (ctx: storeCtx, sk: ctx->skTrusted);
67040
67041 /* Set crls to ctx */
67042 X509_STORE_CTX_set0_crls (ctx: storeCtx, sk: ctx->skCrls);
67043
67044 /* Set flags for CRL check */
67045 X509_STORE_CTX_set_flags (ctx: storeCtx, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
67046
67047 opensslRet = X509_verify_cert (ctx: storeCtx);
67048 if (opensslRet != 1) {
67049 opensslRet = X509_STORE_CTX_get_error (ctx: storeCtx);
67050 if (opensslRet == X509_V_ERR_UNABLE_TO_GET_CRL) {
67051 ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
67052 }
67053 }
67054 }
67055 }
67056 else {
67057 opensslRet = X509_STORE_CTX_get_error (ctx: storeCtx);
67058
67059 /* Check the issued certificate of a CA that is not trusted but available */
67060 if(opensslRet == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN){
67061 int trusted_cert_len = sk_X509_num(ctx->skTrusted);
67062 int cmpVal;
67063 X509 *trusted_cert;
67064 const ASN1_OCTET_STRING *trusted_cert_keyid;
67065 const ASN1_OCTET_STRING *remote_cert_keyid;
67066
67067 for (int i = 0; i < trusted_cert_len; i++) {
67068 trusted_cert = sk_X509_value(ctx->skTrusted, i);
67069
67070 /* Fetch the Subject key identifier of the certificate in trust list */
67071 trusted_cert_keyid = X509_get0_subject_key_id(x: trusted_cert);
67072
67073 /* Fetch the Subject key identifier of the remote certificate */
67074 remote_cert_keyid = X509_get0_subject_key_id(x: certificateX509);
67075
67076 /* Check remote certificate is present in the trust list */
67077 cmpVal = ASN1_OCTET_STRING_cmp(a: trusted_cert_keyid, b: remote_cert_keyid);
67078 if (cmpVal == 0){
67079 ret = UA_STATUSCODE_GOOD;
67080 goto cleanup;
67081 }
67082 }
67083 }
67084
67085 /* Return expected OPCUA error code */
67086 ret = UA_X509_Store_CTX_Error_To_UAError (opensslErr: opensslRet);
67087 }
67088cleanup:
67089 if (store != NULL) {
67090 X509_STORE_free (v: store);
67091 }
67092 if (storeCtx != NULL) {
67093 X509_STORE_CTX_free (ctx: storeCtx);
67094 }
67095 if (certificateX509 != NULL) {
67096 X509_free (a: certificateX509);
67097 }
67098 return ret;
67099}
67100
67101static UA_StatusCode
67102UA_CertificateVerification_VerifyApplicationURI (void * verificationContext,
67103 const UA_ByteString * certificate,
67104 const UA_String * applicationURI) {
67105 (void) verificationContext;
67106
67107 const unsigned char * pData;
67108 X509 * certificateX509;
67109 UA_String subjectURI = UA_STRING_NULL;
67110 GENERAL_NAMES * pNames;
67111 int i;
67112 UA_StatusCode ret;
67113
67114 pData = certificate->data;
67115 if (pData == NULL) {
67116 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67117 }
67118
67119 certificateX509 = UA_OpenSSL_LoadCertificate(certificate);
67120 if (certificateX509 == NULL) {
67121 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67122 }
67123
67124 pNames = (GENERAL_NAMES *) X509_get_ext_d2i(x: certificateX509, NID_subject_alt_name,
67125 NULL, NULL);
67126 if (pNames == NULL) {
67127 X509_free (a: certificateX509);
67128 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67129 }
67130
67131 UA_String_init(p: &subjectURI);
67132
67133 for (i = 0; i < sk_GENERAL_NAME_num (pNames); i++) {
67134 GENERAL_NAME * value = sk_GENERAL_NAME_value (pNames, i);
67135 if (value->type == GEN_URI) {
67136 subjectURI.length = (size_t) (value->d.ia5->length);
67137 subjectURI.data = (UA_Byte *) UA_malloc (size: subjectURI.length);
67138 if (subjectURI.data == NULL) {
67139 X509_free (a: certificateX509);
67140 sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
67141 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67142 }
67143 (void) memcpy (dest: subjectURI.data, src: value->d.ia5->data, n: subjectURI.length);
67144 break;
67145 }
67146
67147 }
67148
67149 ret = UA_STATUSCODE_GOOD;
67150 if (UA_Bstrstr (s1: subjectURI.data, l1: subjectURI.length,
67151 s2: applicationURI->data, l2: applicationURI->length) == NULL) {
67152 ret = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
67153 }
67154
67155 X509_free (a: certificateX509);
67156 sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free);
67157 UA_String_clear (p: &subjectURI);
67158 return ret;
67159}
67160
67161/* main entry */
67162
67163UA_StatusCode
67164UA_CertificateVerification_Trustlist(UA_CertificateVerification * cv,
67165 const UA_ByteString * certificateTrustList,
67166 size_t certificateTrustListSize,
67167 const UA_ByteString * certificateIssuerList,
67168 size_t certificateIssuerListSize,
67169 const UA_ByteString * certificateRevocationList,
67170 size_t certificateRevocationListSize) {
67171 UA_StatusCode ret;
67172
67173 if (cv == NULL) {
67174 return UA_STATUSCODE_BADINTERNALERROR;
67175 }
67176
67177 CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext));
67178 if (context == NULL) {
67179 return UA_STATUSCODE_BADOUTOFMEMORY;
67180 }
67181 ret = UA_CertContext_Init (context);
67182 if (ret != UA_STATUSCODE_GOOD) {
67183 return ret;
67184 }
67185
67186 cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
67187 cv->clear = UA_CertificateVerification_clear;
67188 cv->context = context;
67189 cv->verifyCertificate = UA_CertificateVerification_Verify;
67190
67191 if (certificateTrustListSize > 0) {
67192 if (UA_skTrusted_Cert2X509 (certificateTrustList, certificateTrustListSize,
67193 ctx: context) != UA_STATUSCODE_GOOD) {
67194 ret = UA_STATUSCODE_BADINTERNALERROR;
67195 goto errout;
67196 }
67197 }
67198
67199 if (certificateIssuerListSize > 0) {
67200 if (UA_skIssuer_Cert2X509 (certificateIssuerList, certificateIssuerListSize,
67201 ctx: context) != UA_STATUSCODE_GOOD) {
67202 ret = UA_STATUSCODE_BADINTERNALERROR;
67203 goto errout;
67204 }
67205 }
67206
67207 if (certificateRevocationListSize > 0) {
67208 if (UA_skCrls_Cert2X509 (certificateRevocationList, certificateRevocationListSize,
67209 ctx: context) != UA_STATUSCODE_GOOD) {
67210 ret = UA_STATUSCODE_BADINTERNALERROR;
67211 goto errout;
67212 }
67213 }
67214
67215 return UA_STATUSCODE_GOOD;
67216
67217errout:
67218 UA_CertificateVerification_clear (cv);
67219 return ret;
67220}
67221
67222#ifdef __linux__ /* Linux only so far */
67223UA_StatusCode
67224UA_CertificateVerification_CertFolders(UA_CertificateVerification * cv,
67225 const char * trustListFolder,
67226 const char * issuerListFolder,
67227 const char * revocationListFolder) {
67228 UA_StatusCode ret;
67229 if (cv == NULL) {
67230 return UA_STATUSCODE_BADINTERNALERROR;
67231 }
67232
67233 CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext));
67234 if (context == NULL) {
67235 return UA_STATUSCODE_BADOUTOFMEMORY;
67236 }
67237 ret = UA_CertContext_Init (context);
67238 if (ret != UA_STATUSCODE_GOOD) {
67239 return ret;
67240 }
67241
67242 cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI;
67243 cv->clear = UA_CertificateVerification_clear;
67244 cv->context = context;
67245 cv->verifyCertificate = UA_CertificateVerification_Verify;
67246
67247 /* Only set the folder paths. They will be reloaded during runtime. */
67248
67249 context->trustListFolder = UA_STRING_ALLOC(trustListFolder);
67250 context->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
67251 context->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
67252
67253 return UA_STATUSCODE_GOOD;
67254}
67255#endif
67256
67257#endif /* end of defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */
67258
67259/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.h" ****/
67260
67261/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
67262 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
67263 *
67264 * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
67265 */
67266
67267
67268
67269#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
67270
67271#include <mbedtls/md.h>
67272#include <mbedtls/x509_crt.h>
67273#include <mbedtls/ctr_drbg.h>
67274
67275// MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy
67276
67277#define UA_SHA1_LENGTH 20
67278
67279_UA_BEGIN_DECLS
67280
67281void
67282swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB);
67283
67284void
67285mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
67286 const UA_ByteString *in, unsigned char *out);
67287
67288UA_StatusCode
67289mbedtls_generateKey(mbedtls_md_context_t *context,
67290 const UA_ByteString *secret, const UA_ByteString *seed,
67291 UA_ByteString *out);
67292
67293UA_StatusCode
67294mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
67295 const UA_ByteString *signature);
67296
67297UA_StatusCode
67298mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
67299 mbedtls_ctr_drbg_context *drbgContext,
67300 const UA_ByteString *message,
67301 UA_ByteString *signature);
67302
67303UA_StatusCode
67304mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
67305 UA_ByteString *thumbprint);
67306
67307/* Set the hashing scheme before calling
67308 * E.g. mbedtls_rsa_set_padding(context, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); */
67309UA_StatusCode
67310mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
67311 mbedtls_ctr_drbg_context *drbgContext,
67312 UA_ByteString *data, const size_t plainTextBlockSize);
67313
67314UA_StatusCode
67315mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
67316 mbedtls_ctr_drbg_context *drbgContext,
67317 UA_ByteString *data);
67318
67319int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng);
67320
67321UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target);
67322
67323UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data);
67324
67325_UA_END_DECLS
67326
67327#endif
67328
67329
67330/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c" ****/
67331
67332/* This Source Code Form is subject to the terms of the Mozilla Public
67333 * License, v. 2.0. If a copy of the MPL was not distributed with this
67334 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
67335 *
67336 * Copyright 2018-2019 (c) Mark Giraud, Fraunhofer IOSB
67337 * Copyright 2019 (c) Kalycito Infotech Private Limited
67338 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
67339 * Copyright 2020 (c) Wind River Systems, Inc.
67340 * Copyright 2020 (c) basysKom GmbH
67341 *
67342 */
67343
67344
67345#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
67346
67347
67348#include <mbedtls/aes.h>
67349#include <mbedtls/ctr_drbg.h>
67350#include <mbedtls/entropy.h>
67351#include <mbedtls/error.h>
67352#include <mbedtls/md.h>
67353#include <mbedtls/sha1.h>
67354#include <mbedtls/version.h>
67355#include <mbedtls/x509_crt.h>
67356
67357/* Notes:
67358 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
67359 * allocate temp buffers.
67360 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
67361 */
67362
67363#define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11
67364#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH 16
67365#define UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16
67366#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16
67367#define UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE 16
67368#define UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH 128
67369#define UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH 512
67370
67371typedef struct {
67372 UA_ByteString localCertThumbprint;
67373
67374 mbedtls_ctr_drbg_context drbgContext;
67375 mbedtls_entropy_context entropyContext;
67376 mbedtls_md_context_t sha1MdContext;
67377 mbedtls_pk_context localPrivateKey;
67378} Basic128Rsa15_PolicyContext;
67379
67380typedef struct {
67381 Basic128Rsa15_PolicyContext *policyContext;
67382
67383 UA_ByteString localSymSigningKey;
67384 UA_ByteString localSymEncryptingKey;
67385 UA_ByteString localSymIv;
67386
67387 UA_ByteString remoteSymSigningKey;
67388 UA_ByteString remoteSymEncryptingKey;
67389 UA_ByteString remoteSymIv;
67390
67391 mbedtls_x509_crt remoteCertificate;
67392} Basic128Rsa15_ChannelContext;
67393
67394/********************/
67395/* AsymmetricModule */
67396/********************/
67397
67398static UA_StatusCode
67399asym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67400 const UA_ByteString *message,
67401 const UA_ByteString *signature) {
67402 if(message == NULL || signature == NULL || cc == NULL)
67403 return UA_STATUSCODE_BADINTERNALERROR;
67404
67405 return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
67406}
67407
67408static UA_StatusCode
67409asym_sign_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67410 const UA_ByteString *message,
67411 UA_ByteString *signature) {
67412 if(message == NULL || signature == NULL || cc == NULL)
67413 return UA_STATUSCODE_BADINTERNALERROR;
67414
67415 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67416 return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext,
67417 message, signature);
67418}
67419
67420static size_t
67421asym_getLocalSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67422 if(cc == NULL)
67423 return 0;
67424#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67425 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
67426#else
67427 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
67428#endif
67429
67430
67431}
67432
67433static size_t
67434asym_getRemoteSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67435 if(cc == NULL)
67436 return 0;
67437
67438#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67439 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
67440#else
67441 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67442#endif
67443
67444}
67445
67446static UA_StatusCode
67447asym_encrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67448 UA_ByteString *data) {
67449 if(cc == NULL || data == NULL)
67450 return UA_STATUSCODE_BADINTERNALERROR;
67451
67452 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67453 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
67454
67455#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67456 size_t plainTextBlockSize = remoteRsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67457#else
67458 size_t keylen = mbedtls_rsa_get_len(remoteRsaContext);
67459 size_t plainTextBlockSize = mbedtls_rsa_get_len(remoteRsaContext) -
67460 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67461#endif
67462
67463 if(data->length % plainTextBlockSize != 0)
67464 return UA_STATUSCODE_BADINTERNALERROR;
67465
67466 size_t blocks = data->length / plainTextBlockSize;
67467 UA_ByteString encrypted;
67468#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67469 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * remoteRsaContext->len);
67470#else
67471 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * keylen);
67472#endif
67473 if(retval != UA_STATUSCODE_GOOD)
67474 return retval;
67475
67476 size_t lenDataToEncrypt = data->length;
67477 size_t inOffset = 0;
67478 size_t offset = 0;
67479 size_t outLength = 0;
67480 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67481 while(lenDataToEncrypt >= plainTextBlockSize) {
67482 int mbedErr = mbedtls_pk_encrypt(&cc->remoteCertificate.pk,
67483 data->data + inOffset, plainTextBlockSize,
67484 encrypted.data + offset, &outLength,
67485 encrypted.length - offset,
67486 mbedtls_ctr_drbg_random,
67487 &pc->drbgContext);
67488 if(mbedErr) {
67489 UA_ByteString_clear(&encrypted);
67490 return UA_STATUSCODE_BADINTERNALERROR;
67491 }
67492
67493 inOffset += plainTextBlockSize;
67494 offset += outLength;
67495 lenDataToEncrypt -= plainTextBlockSize;
67496 }
67497
67498 memcpy(data->data, encrypted.data, offset);
67499 UA_ByteString_clear(&encrypted);
67500
67501 return UA_STATUSCODE_GOOD;
67502}
67503
67504static UA_StatusCode
67505asym_decrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67506 UA_ByteString *data) {
67507 if(cc == NULL || data == NULL)
67508 return UA_STATUSCODE_BADINTERNALERROR;
67509
67510 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67511 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
67512 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
67513#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67514 size_t keylen = rsaContext->len;
67515#else
67516 size_t keylen = mbedtls_rsa_get_len(rsaContext);
67517#endif
67518 if(data->length % keylen != 0)
67519 return UA_STATUSCODE_BADINTERNALERROR;
67520
67521 size_t inOffset = 0;
67522 size_t outOffset = 0;
67523 size_t outLength = 0;
67524 unsigned char buf[512];
67525
67526 while(inOffset < data->length) {
67527 int mbedErr = mbedtls_pk_decrypt(&pc->localPrivateKey,
67528 data->data + inOffset, keylen,
67529 buf, &outLength, 512,
67530 mbedtls_ctr_drbg_random,
67531 &pc->drbgContext);
67532 if(mbedErr)
67533 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67534
67535 memcpy(data->data + outOffset, buf, outLength);
67536 inOffset += keylen;
67537 outOffset += outLength;
67538 }
67539
67540 data->length = outOffset;
67541 return UA_STATUSCODE_GOOD;
67542}
67543
67544static size_t
67545asym_getLocalEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67546#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67547 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67548 return rsaContext->len;
67549#else
67550 if(cc == NULL)
67551 return 0;
67552 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67553#endif
67554}
67555
67556static size_t
67557asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67558 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
67559}
67560
67561static size_t
67562asym_getRemoteBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67563#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67564 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67565 return rsaContext->len;
67566#else
67567 if(cc == NULL)
67568 return 0;
67569 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67570#endif
67571}
67572
67573static size_t
67574asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) {
67575#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67576 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67577 return rsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67578#else
67579 if(cc == NULL)
67580 return 0;
67581 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
67582 UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN;
67583#endif
67584}
67585
67586static UA_StatusCode
67587asym_makeThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67588 const UA_ByteString *certificate,
67589 UA_ByteString *thumbprint) {
67590 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
67591 return UA_STATUSCODE_BADINTERNALERROR;
67592 return mbedtls_thumbprint_sha1(certificate, thumbprint);
67593}
67594
67595static UA_StatusCode
67596asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67597 const UA_ByteString *certificateThumbprint) {
67598 if(securityPolicy == NULL || certificateThumbprint == NULL)
67599 return UA_STATUSCODE_BADINTERNALERROR;
67600
67601 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67602 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
67603 return UA_STATUSCODE_BADCERTIFICATEINVALID;
67604
67605 return UA_STATUSCODE_GOOD;
67606}
67607
67608/*******************/
67609/* SymmetricModule */
67610/*******************/
67611
67612static UA_StatusCode
67613sym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67614 const UA_ByteString *message,
67615 const UA_ByteString *signature) {
67616 if(cc == NULL || message == NULL || signature == NULL)
67617 return UA_STATUSCODE_BADINTERNALERROR;
67618
67619 /* Compute MAC */
67620 if(signature->length != UA_SHA1_LENGTH)
67621 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67622
67623 Basic128Rsa15_PolicyContext *pc = cc->policyContext;
67624
67625 unsigned char mac[UA_SHA1_LENGTH];
67626 mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
67627
67628 /* Compare with Signature */
67629 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH))
67630 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67631 return UA_STATUSCODE_GOOD;
67632}
67633
67634static UA_StatusCode
67635sym_sign_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67636 const UA_ByteString *message,
67637 UA_ByteString *signature) {
67638 if(signature->length != UA_SHA1_LENGTH)
67639 return UA_STATUSCODE_BADINTERNALERROR;
67640
67641 mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey,
67642 message, signature->data);
67643 return UA_STATUSCODE_GOOD;
67644}
67645
67646static size_t
67647sym_getSignatureSize_sp_basic128rsa15(const void *channelContext) {
67648 return UA_SHA1_LENGTH;
67649}
67650
67651static size_t
67652sym_getSigningKeyLength_sp_basic128rsa15(const void *const channelContext) {
67653 return UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH;
67654}
67655
67656static size_t
67657sym_getEncryptionKeyLength_sp_basic128rsa15(const void *channelContext) {
67658 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH;
67659}
67660
67661static size_t
67662sym_getEncryptionBlockSize_sp_basic128rsa15(const void *const channelContext) {
67663 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
67664}
67665
67666static size_t
67667sym_getPlainTextBlockSize_sp_basic128rsa15(const void *const channelContext) {
67668 return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
67669}
67670
67671static UA_StatusCode
67672sym_encrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67673 UA_ByteString *data) {
67674 if(cc == NULL || data == NULL)
67675 return UA_STATUSCODE_BADINTERNALERROR;
67676
67677 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE)
67678 return UA_STATUSCODE_BADINTERNALERROR;
67679
67680 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE;
67681 if(data->length % plainTextBlockSize != 0)
67682 return UA_STATUSCODE_BADINTERNALERROR;
67683
67684 /* Keylength in bits */
67685 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
67686 mbedtls_aes_context aesContext;
67687 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
67688 if(mbedErr)
67689 return UA_STATUSCODE_BADINTERNALERROR;
67690
67691 UA_ByteString ivCopy;
67692 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
67693 if(retval != UA_STATUSCODE_GOOD)
67694 return retval;
67695
67696 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
67697 ivCopy.data, data->data, data->data);
67698 if(mbedErr)
67699 retval = UA_STATUSCODE_BADINTERNALERROR;
67700 UA_ByteString_clear(&ivCopy);
67701 return retval;
67702}
67703
67704static UA_StatusCode
67705sym_decrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67706 UA_ByteString *data) {
67707 if(cc == NULL || data == NULL)
67708 return UA_STATUSCODE_BADINTERNALERROR;
67709
67710 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE;
67711 if(cc->remoteSymIv.length != encryptionBlockSize)
67712 return UA_STATUSCODE_BADINTERNALERROR;
67713
67714 if(data->length % encryptionBlockSize != 0)
67715 return UA_STATUSCODE_BADINTERNALERROR;
67716
67717 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
67718 mbedtls_aes_context aesContext;
67719 int mbedErr = mbedtls_aes_setkey_dec(&aesContext,
67720 cc->remoteSymEncryptingKey.data, keylength);
67721 if(mbedErr)
67722 return UA_STATUSCODE_BADINTERNALERROR;
67723
67724 UA_ByteString ivCopy;
67725 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
67726 if(retval != UA_STATUSCODE_GOOD)
67727 return retval;
67728
67729 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
67730 ivCopy.data, data->data, data->data);
67731 if(mbedErr)
67732 retval = UA_STATUSCODE_BADINTERNALERROR;
67733 UA_ByteString_clear(&ivCopy);
67734 return retval;
67735}
67736
67737static UA_StatusCode
67738sym_generateKey_sp_basic128rsa15(void *policyContext, const UA_ByteString *secret,
67739 const UA_ByteString *seed, UA_ByteString *out) {
67740 if(secret == NULL || seed == NULL || out == NULL)
67741 return UA_STATUSCODE_BADINTERNALERROR;
67742 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
67743 return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
67744}
67745
67746static UA_StatusCode
67747sym_generateNonce_sp_basic128rsa15(void *policyContext, UA_ByteString *out) {
67748 if(out == NULL)
67749 return UA_STATUSCODE_BADINTERNALERROR;
67750 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext;
67751 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
67752 if(mbedErr)
67753 return UA_STATUSCODE_BADUNEXPECTEDERROR;
67754 return UA_STATUSCODE_GOOD;
67755}
67756
67757/*****************/
67758/* ChannelModule */
67759/*****************/
67760
67761/* Assumes that the certificate has been verified externally */
67762static UA_StatusCode
67763parseRemoteCertificate_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67764 const UA_ByteString *remoteCertificate) {
67765 if(remoteCertificate == NULL || cc == NULL)
67766 return UA_STATUSCODE_BADINTERNALERROR;
67767
67768 /* Parse the certificate */
67769 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
67770 remoteCertificate->length);
67771 if(mbedErr)
67772 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67773
67774 /* Check the key length */
67775#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
67776 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
67777 if(rsaContext->len < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
67778 rsaContext->len > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
67779 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
67780#else
67781 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
67782 if(keylen < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH ||
67783 keylen > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH)
67784 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
67785#endif
67786 return UA_STATUSCODE_GOOD;
67787}
67788
67789static void
67790channelContext_deleteContext_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc) {
67791 UA_ByteString_clear(&cc->localSymSigningKey);
67792 UA_ByteString_clear(&cc->localSymEncryptingKey);
67793 UA_ByteString_clear(&cc->localSymIv);
67794 UA_ByteString_clear(&cc->remoteSymSigningKey);
67795 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
67796 UA_ByteString_clear(&cc->remoteSymIv);
67797 mbedtls_x509_crt_free(&cc->remoteCertificate);
67798 UA_free(cc);
67799}
67800
67801static UA_StatusCode
67802channelContext_newContext_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy,
67803 const UA_ByteString *remoteCertificate,
67804 void **pp_contextData) {
67805 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
67806 return UA_STATUSCODE_BADINTERNALERROR;
67807
67808 /* Allocate the channel context */
67809 *pp_contextData = UA_malloc(sizeof(Basic128Rsa15_ChannelContext));
67810 if(*pp_contextData == NULL)
67811 return UA_STATUSCODE_BADOUTOFMEMORY;
67812
67813 Basic128Rsa15_ChannelContext *cc = (Basic128Rsa15_ChannelContext *)*pp_contextData;
67814
67815 /* Initialize the channel context */
67816 cc->policyContext = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67817
67818 UA_ByteString_init(&cc->localSymSigningKey);
67819 UA_ByteString_init(&cc->localSymEncryptingKey);
67820 UA_ByteString_init(&cc->localSymIv);
67821
67822 UA_ByteString_init(&cc->remoteSymSigningKey);
67823 UA_ByteString_init(&cc->remoteSymEncryptingKey);
67824 UA_ByteString_init(&cc->remoteSymIv);
67825
67826 mbedtls_x509_crt_init(&cc->remoteCertificate);
67827
67828 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
67829 UA_StatusCode retval = parseRemoteCertificate_sp_basic128rsa15(cc, remoteCertificate);
67830 if(retval != UA_STATUSCODE_GOOD) {
67831 channelContext_deleteContext_sp_basic128rsa15(cc);
67832 *pp_contextData = NULL;
67833 }
67834 return retval;
67835}
67836
67837static UA_StatusCode
67838channelContext_setLocalSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67839 const UA_ByteString *key) {
67840 if(key == NULL || cc == NULL)
67841 return UA_STATUSCODE_BADINTERNALERROR;
67842
67843 UA_ByteString_clear(&cc->localSymEncryptingKey);
67844 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
67845}
67846
67847static UA_StatusCode
67848channelContext_setLocalSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67849 const UA_ByteString *key) {
67850 if(key == NULL || cc == NULL)
67851 return UA_STATUSCODE_BADINTERNALERROR;
67852
67853 UA_ByteString_clear(&cc->localSymSigningKey);
67854 return UA_ByteString_copy(key, &cc->localSymSigningKey);
67855}
67856
67857
67858static UA_StatusCode
67859channelContext_setLocalSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67860 const UA_ByteString *iv) {
67861 if(iv == NULL || cc == NULL)
67862 return UA_STATUSCODE_BADINTERNALERROR;
67863
67864 UA_ByteString_clear(&cc->localSymIv);
67865 return UA_ByteString_copy(iv, &cc->localSymIv);
67866}
67867
67868static UA_StatusCode
67869channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67870 const UA_ByteString *key) {
67871 if(key == NULL || cc == NULL)
67872 return UA_STATUSCODE_BADINTERNALERROR;
67873
67874 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
67875 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
67876}
67877
67878static UA_StatusCode
67879channelContext_setRemoteSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67880 const UA_ByteString *key) {
67881 if(key == NULL || cc == NULL)
67882 return UA_STATUSCODE_BADINTERNALERROR;
67883
67884 UA_ByteString_clear(&cc->remoteSymSigningKey);
67885 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
67886}
67887
67888static UA_StatusCode
67889channelContext_setRemoteSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc,
67890 const UA_ByteString *iv) {
67891 if(iv == NULL || cc == NULL)
67892 return UA_STATUSCODE_BADINTERNALERROR;
67893
67894 UA_ByteString_clear(&cc->remoteSymIv);
67895 return UA_ByteString_copy(iv, &cc->remoteSymIv);
67896}
67897
67898static UA_StatusCode
67899channelContext_compareCertificate_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc,
67900 const UA_ByteString *certificate) {
67901 if(cc == NULL || certificate == NULL)
67902 return UA_STATUSCODE_BADINTERNALERROR;
67903
67904 mbedtls_x509_crt cert;
67905 mbedtls_x509_crt_init(&cert);
67906 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
67907 if(mbedErr)
67908 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67909
67910 UA_StatusCode retval = UA_STATUSCODE_GOOD;
67911 if(cert.raw.len != cc->remoteCertificate.raw.len ||
67912 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
67913 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67914
67915 mbedtls_x509_crt_free(&cert);
67916 return retval;
67917}
67918
67919static void
67920clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) {
67921 if(securityPolicy == NULL)
67922 return;
67923
67924 UA_ByteString_clear(&securityPolicy->localCertificate);
67925
67926 if(securityPolicy->policyContext == NULL)
67927 return;
67928
67929 /* delete all allocated members in the context */
67930 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
67931 securityPolicy->policyContext;
67932
67933 mbedtls_ctr_drbg_free(&pc->drbgContext);
67934 mbedtls_entropy_free(&pc->entropyContext);
67935 mbedtls_pk_free(&pc->localPrivateKey);
67936 mbedtls_md_free(&pc->sha1MdContext);
67937 UA_ByteString_clear(&pc->localCertThumbprint);
67938
67939 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67940 "Deleted members of EndpointContext for sp_basic128rsa15");
67941
67942 UA_free(pc);
67943 securityPolicy->policyContext = NULL;
67944}
67945
67946static UA_StatusCode
67947updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
67948 const UA_ByteString newCertificate,
67949 const UA_ByteString newPrivateKey) {
67950 if(securityPolicy == NULL)
67951 return UA_STATUSCODE_BADINTERNALERROR;
67952
67953 if(securityPolicy->policyContext == NULL)
67954 return UA_STATUSCODE_BADINTERNALERROR;
67955
67956 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext;
67957
67958 UA_ByteString_clear(&securityPolicy->localCertificate);
67959
67960 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
67961
67962 if (retval != UA_STATUSCODE_GOOD)
67963 return retval;
67964
67965 /* Set the new private key */
67966 mbedtls_pk_free(&pc->localPrivateKey);
67967 mbedtls_pk_init(&pc->localPrivateKey);
67968 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
67969 if(mbedErr) {
67970 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
67971 goto error;
67972 }
67973
67974 retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy,
67975 &securityPolicy->localCertificate,
67976 &pc->localCertThumbprint);
67977 if(retval != UA_STATUSCODE_GOOD)
67978 goto error;
67979
67980 return retval;
67981
67982 error:
67983 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67984 "Could not update certificate and private key");
67985 if(securityPolicy->policyContext != NULL)
67986 clear_sp_basic128rsa15(securityPolicy);
67987 return retval;
67988}
67989
67990static UA_StatusCode
67991policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy,
67992 const UA_ByteString localPrivateKey) {
67993 UA_StatusCode retval = UA_STATUSCODE_GOOD;
67994 if(securityPolicy == NULL)
67995 return UA_STATUSCODE_BADINTERNALERROR;
67996
67997 if (localPrivateKey.length == 0) {
67998 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
67999 "Can not initialize security policy. Private key is empty.");
68000 return UA_STATUSCODE_BADINVALIDARGUMENT;
68001 }
68002
68003 Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)
68004 UA_malloc(sizeof(Basic128Rsa15_PolicyContext));
68005 securityPolicy->policyContext = (void *)pc;
68006 if(!pc) {
68007 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68008 goto error;
68009 }
68010
68011 /* Initialize the PolicyContext */
68012 memset(pc, 0, sizeof(Basic128Rsa15_PolicyContext));
68013 mbedtls_ctr_drbg_init(&pc->drbgContext);
68014 mbedtls_entropy_init(&pc->entropyContext);
68015 mbedtls_pk_init(&pc->localPrivateKey);
68016 mbedtls_md_init(&pc->sha1MdContext);
68017
68018 /* Initialized the message digest */
68019 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
68020 int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1);
68021 if(mbedErr) {
68022 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68023 goto error;
68024 }
68025
68026 mbedErr = mbedtls_entropy_self_test(0);
68027
68028 if(mbedErr) {
68029 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68030 goto error;
68031 }
68032
68033 /* Seed the RNG */
68034 char *personalization = "open62541-drbg";
68035 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
68036 &pc->entropyContext,
68037 (const unsigned char *)personalization, 14);
68038 if(mbedErr) {
68039 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68040 goto error;
68041 }
68042
68043 /* Set the private key */
68044 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
68045
68046 if(mbedErr) {
68047 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68048 goto error;
68049 }
68050
68051 /* Set the local certificate thumbprint */
68052 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
68053 if(retval != UA_STATUSCODE_GOOD)
68054 goto error;
68055 retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy,
68056 &securityPolicy->localCertificate,
68057 &pc->localCertThumbprint);
68058 if(retval != UA_STATUSCODE_GOOD)
68059 goto error;
68060
68061 return UA_STATUSCODE_GOOD;
68062
68063error:
68064 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68065 "Could not create securityContext: %s", UA_StatusCode_name(retval));
68066 if(securityPolicy->policyContext != NULL)
68067 clear_sp_basic128rsa15(securityPolicy);
68068 return retval;
68069}
68070
68071UA_StatusCode
68072UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
68073 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
68074 memset(policy, 0, sizeof(UA_SecurityPolicy));
68075 policy->logger = logger;
68076
68077 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0");
68078
68079 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
68080 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
68081 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
68082
68083 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
68084
68085 if (retval != UA_STATUSCODE_GOOD)
68086 return retval;
68087
68088 /* AsymmetricModule */
68089 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
68090 &asymmetricModule->cryptoModule.signatureAlgorithm;
68091 asym_signatureAlgorithm->uri =
68092 UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
68093 asym_signatureAlgorithm->verify =
68094 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic128rsa15;
68095 asym_signatureAlgorithm->sign =
68096 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15;
68097 asym_signatureAlgorithm->getLocalSignatureSize =
68098 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic128rsa15;
68099 asym_signatureAlgorithm->getRemoteSignatureSize =
68100 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic128rsa15;
68101 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
68102 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
68103
68104 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
68105 &asymmetricModule->cryptoModule.encryptionAlgorithm;
68106 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
68107 asym_encryptionAlgorithm->encrypt =
68108 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15;
68109 asym_encryptionAlgorithm->decrypt =
68110 (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_basic128rsa15;
68111 asym_encryptionAlgorithm->getLocalKeyLength =
68112 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic128rsa15;
68113 asym_encryptionAlgorithm->getRemoteKeyLength =
68114 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic128rsa15;
68115 asym_encryptionAlgorithm->getRemoteBlockSize =
68116 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic128rsa15;
68117 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68118 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15;
68119
68120 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic128rsa15;
68121 asymmetricModule->compareCertificateThumbprint =
68122 asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15;
68123
68124 /* SymmetricModule */
68125 symmetricModule->generateKey = sym_generateKey_sp_basic128rsa15;
68126 symmetricModule->generateNonce = sym_generateNonce_sp_basic128rsa15;
68127
68128 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
68129 &symmetricModule->cryptoModule.signatureAlgorithm;
68130 sym_signatureAlgorithm->uri =
68131 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
68132 sym_signatureAlgorithm->verify =
68133 (UA_StatusCode (*)(void *, const UA_ByteString *,
68134 const UA_ByteString *))sym_verify_sp_basic128rsa15;
68135 sym_signatureAlgorithm->sign =
68136 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic128rsa15;
68137 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
68138 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic128rsa15;
68139 sym_signatureAlgorithm->getLocalKeyLength =
68140 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
68141 sym_signatureAlgorithm->getRemoteKeyLength =
68142 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15;
68143
68144 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
68145 &symmetricModule->cryptoModule.encryptionAlgorithm;
68146 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
68147 sym_encryptionAlgorithm->encrypt =
68148 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic128rsa15;
68149 sym_encryptionAlgorithm->decrypt =
68150 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic128rsa15;
68151 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
68152 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15;
68153 sym_encryptionAlgorithm->getRemoteBlockSize =
68154 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic128rsa15;
68155 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68156 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic128rsa15;
68157 symmetricModule->secureChannelNonceLength = 16;
68158
68159 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
68160 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
68161
68162 /* ChannelModule */
68163 channelModule->newContext = channelContext_newContext_sp_basic128rsa15;
68164 channelModule->deleteContext = (void (*)(void *))
68165 channelContext_deleteContext_sp_basic128rsa15;
68166
68167 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68168 channelContext_setLocalSymEncryptingKey_sp_basic128rsa15;
68169 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68170 channelContext_setLocalSymSigningKey_sp_basic128rsa15;
68171 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68172 channelContext_setLocalSymIv_sp_basic128rsa15;
68173
68174 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68175 channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15;
68176 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68177 channelContext_setRemoteSymSigningKey_sp_basic128rsa15;
68178 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68179 channelContext_setRemoteSymIv_sp_basic128rsa15;
68180
68181 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
68182 channelContext_compareCertificate_sp_basic128rsa15;
68183
68184 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic128rsa15;
68185 policy->clear = clear_sp_basic128rsa15;
68186
68187 UA_StatusCode res = policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey);
68188 if(res != UA_STATUSCODE_GOOD)
68189 clear_sp_basic128rsa15(policy);
68190
68191 return res;
68192}
68193
68194#endif
68195
68196/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c" ****/
68197
68198/* This Source Code Form is subject to the terms of the Mozilla Public
68199 * License, v. 2.0. If a copy of the MPL was not distributed with this
68200 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
68201 *
68202 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
68203 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
68204 * Copyright 2019 (c) Kalycito Infotech Private Limited
68205 * Copyright 2020 (c) Wind River Systems, Inc.
68206 * Copyright 2020 (c) basysKom GmbH
68207 *
68208 */
68209
68210
68211#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
68212
68213
68214#include <mbedtls/aes.h>
68215#include <mbedtls/entropy.h>
68216#include <mbedtls/error.h>
68217#include <mbedtls/sha1.h>
68218#include <mbedtls/version.h>
68219
68220/* Notes:
68221 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
68222 * allocate temp buffers.
68223 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
68224 */
68225
68226#define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42
68227#define UA_SHA1_LENGTH 20
68228#define UA_BASIC256_SYM_SIGNING_KEY_LENGTH 24
68229#define UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH 32
68230#define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16
68231#define UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
68232#define UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH 128
68233#define UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH 512
68234
68235typedef struct {
68236 UA_ByteString localCertThumbprint;
68237
68238 mbedtls_ctr_drbg_context drbgContext;
68239 mbedtls_entropy_context entropyContext;
68240 mbedtls_md_context_t sha1MdContext;
68241 mbedtls_pk_context localPrivateKey;
68242} Basic256_PolicyContext;
68243
68244typedef struct {
68245 Basic256_PolicyContext *policyContext;
68246
68247 UA_ByteString localSymSigningKey;
68248 UA_ByteString localSymEncryptingKey;
68249 UA_ByteString localSymIv;
68250
68251 UA_ByteString remoteSymSigningKey;
68252 UA_ByteString remoteSymEncryptingKey;
68253 UA_ByteString remoteSymIv;
68254
68255 mbedtls_x509_crt remoteCertificate;
68256} Basic256_ChannelContext;
68257
68258/********************/
68259/* AsymmetricModule */
68260/********************/
68261
68262/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68263static UA_StatusCode
68264asym_verify_sp_basic256(Basic256_ChannelContext *cc,
68265 const UA_ByteString *message,
68266 const UA_ByteString *signature) {
68267 if(message == NULL || signature == NULL || cc == NULL)
68268 return UA_STATUSCODE_BADINTERNALERROR;
68269
68270 return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature);
68271}
68272
68273/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
68274static UA_StatusCode
68275asym_sign_sp_basic256(Basic256_ChannelContext *cc,
68276 const UA_ByteString *message,
68277 UA_ByteString *signature) {
68278 if(message == NULL || signature == NULL || cc == NULL)
68279 return UA_STATUSCODE_BADINTERNALERROR;
68280
68281 Basic256_PolicyContext *pc = cc->policyContext;
68282 return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext,
68283 message, signature);
68284}
68285
68286static size_t
68287asym_getLocalSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
68288 if(cc == NULL)
68289 return 0;
68290#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68291 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
68292#else
68293 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
68294
68295#endif
68296}
68297
68298static size_t
68299asym_getRemoteSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) {
68300 if(cc == NULL)
68301 return 0;
68302#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68303 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
68304#else
68305 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68306#endif
68307}
68308
68309static size_t
68310asym_getRemotePlainTextBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
68311#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68312 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68313 return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
68314#else
68315 if(cc == NULL)
68316 return 0;
68317 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
68318 UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN;
68319#endif
68320}
68321
68322/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
68323static UA_StatusCode
68324asym_encrypt_sp_basic256(Basic256_ChannelContext *cc,
68325 UA_ByteString *data) {
68326 if(cc == NULL || data == NULL)
68327 return UA_STATUSCODE_BADINTERNALERROR;
68328
68329 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256(cc);
68330
68331 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68332 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
68333
68334 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
68335 data, plainTextBlockSize);
68336}
68337
68338/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
68339static UA_StatusCode
68340asym_decrypt_sp_basic256(Basic256_ChannelContext *cc,
68341 UA_ByteString *data) {
68342 if(cc == NULL || data == NULL)
68343 return UA_STATUSCODE_BADINTERNALERROR;
68344 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
68345 &cc->policyContext->drbgContext, data);
68346}
68347
68348static size_t
68349asym_getLocalEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
68350 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
68351}
68352
68353static size_t
68354asym_getRemoteEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) {
68355 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
68356}
68357
68358static size_t
68359asym_getRemoteBlockSize_sp_basic256(const Basic256_ChannelContext *cc) {
68360#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68361 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68362 return rsaContext->len;
68363#else
68364 if(cc == NULL)
68365 return 0;
68366 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68367#endif
68368}
68369
68370static UA_StatusCode
68371asym_makeThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68372 const UA_ByteString *certificate,
68373 UA_ByteString *thumbprint) {
68374 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
68375 return UA_STATUSCODE_BADINTERNALERROR;
68376 return mbedtls_thumbprint_sha1(certificate, thumbprint);
68377}
68378
68379static UA_StatusCode
68380asymmetricModule_compareCertificateThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68381 const UA_ByteString *certificateThumbprint) {
68382 if(securityPolicy == NULL || certificateThumbprint == NULL)
68383 return UA_STATUSCODE_BADINTERNALERROR;
68384
68385 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)securityPolicy->policyContext;
68386 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
68387 return UA_STATUSCODE_BADCERTIFICATEINVALID;
68388
68389 return UA_STATUSCODE_GOOD;
68390}
68391
68392/*******************/
68393/* SymmetricModule */
68394/*******************/
68395
68396static UA_StatusCode
68397sym_verify_sp_basic256(Basic256_ChannelContext *cc,
68398 const UA_ByteString *message,
68399 const UA_ByteString *signature) {
68400 if(cc == NULL || message == NULL || signature == NULL)
68401 return UA_STATUSCODE_BADINTERNALERROR;
68402
68403 /* Compute MAC */
68404 if(signature->length != UA_SHA1_LENGTH)
68405 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68406
68407 Basic256_PolicyContext *pc = cc->policyContext;
68408
68409 unsigned char mac[UA_SHA1_LENGTH];
68410 mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac);
68411
68412 /* Compare with Signature */
68413 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH))
68414 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68415 return UA_STATUSCODE_GOOD;
68416}
68417
68418static UA_StatusCode
68419sym_sign_sp_basic256(const Basic256_ChannelContext *cc,
68420 const UA_ByteString *message, UA_ByteString *signature) {
68421 if(signature->length != UA_SHA1_LENGTH)
68422 return UA_STATUSCODE_BADINTERNALERROR;
68423
68424 mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey,
68425 message, signature->data);
68426 return UA_STATUSCODE_GOOD;
68427}
68428
68429static size_t
68430sym_getSignatureSize_sp_basic256(const void *channelContext) {
68431 return UA_SHA1_LENGTH;
68432}
68433
68434static size_t
68435sym_getSigningKeyLength_sp_basic256(const void *const channelContext) {
68436 return UA_BASIC256_SYM_SIGNING_KEY_LENGTH;
68437}
68438
68439static size_t
68440sym_getEncryptionKeyLength_sp_basic256(const void *channelContext) {
68441 return UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH;
68442}
68443
68444static size_t
68445sym_getEncryptionBlockSize_sp_basic256(const void *const channelContext) {
68446 return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
68447}
68448
68449static size_t
68450sym_getPlainTextBlockSize_sp_basic256(const void *const channelContext) {
68451 return UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
68452}
68453
68454static UA_StatusCode
68455sym_encrypt_sp_basic256(const Basic256_ChannelContext *cc,
68456 UA_ByteString *data) {
68457 if(cc == NULL || data == NULL)
68458 return UA_STATUSCODE_BADINTERNALERROR;
68459
68460 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE)
68461 return UA_STATUSCODE_BADINTERNALERROR;
68462
68463 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE;
68464 if(data->length % plainTextBlockSize != 0)
68465 return UA_STATUSCODE_BADINTERNALERROR;
68466
68467 /* Keylength in bits */
68468 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
68469 mbedtls_aes_context aesContext;
68470 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
68471 if(mbedErr)
68472 return UA_STATUSCODE_BADINTERNALERROR;
68473
68474 UA_ByteString ivCopy;
68475 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
68476 if(retval != UA_STATUSCODE_GOOD)
68477 return retval;
68478
68479 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
68480 ivCopy.data, data->data, data->data);
68481 if(mbedErr)
68482 retval = UA_STATUSCODE_BADINTERNALERROR;
68483 UA_ByteString_clear(&ivCopy);
68484 return retval;
68485}
68486
68487static UA_StatusCode
68488sym_decrypt_sp_basic256(const Basic256_ChannelContext *cc,
68489 UA_ByteString *data) {
68490 if(cc == NULL || data == NULL)
68491 return UA_STATUSCODE_BADINTERNALERROR;
68492
68493 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE;
68494 if(cc->remoteSymIv.length != encryptionBlockSize)
68495 return UA_STATUSCODE_BADINTERNALERROR;
68496
68497 if(data->length % encryptionBlockSize != 0)
68498 return UA_STATUSCODE_BADINTERNALERROR;
68499
68500 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
68501 mbedtls_aes_context aesContext;
68502 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
68503 if(mbedErr)
68504 return UA_STATUSCODE_BADINTERNALERROR;
68505
68506 UA_ByteString ivCopy;
68507 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
68508 if(retval != UA_STATUSCODE_GOOD)
68509 return retval;
68510
68511 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
68512 ivCopy.data, data->data, data->data);
68513 if(mbedErr)
68514 retval = UA_STATUSCODE_BADINTERNALERROR;
68515 UA_ByteString_clear(&ivCopy);
68516 return retval;
68517}
68518
68519static UA_StatusCode
68520sym_generateKey_sp_basic256(void *policyContext, const UA_ByteString *secret,
68521 const UA_ByteString *seed, UA_ByteString *out) {
68522 if(secret == NULL || seed == NULL || out == NULL)
68523 return UA_STATUSCODE_BADINTERNALERROR;
68524 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
68525 return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out);
68526}
68527
68528static UA_StatusCode
68529sym_generateNonce_sp_basic256(void *policyContext, UA_ByteString *out) {
68530 if(out == NULL)
68531 return UA_STATUSCODE_BADINTERNALERROR;
68532 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext;
68533 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
68534 if(mbedErr)
68535 return UA_STATUSCODE_BADUNEXPECTEDERROR;
68536 return UA_STATUSCODE_GOOD;
68537}
68538
68539/*****************/
68540/* ChannelModule */
68541/*****************/
68542
68543/* Assumes that the certificate has been verified externally */
68544static UA_StatusCode
68545parseRemoteCertificate_sp_basic256(Basic256_ChannelContext *cc,
68546 const UA_ByteString *remoteCertificate) {
68547 if(remoteCertificate == NULL || cc == NULL)
68548 return UA_STATUSCODE_BADINTERNALERROR;
68549
68550 /* Parse the certificate */
68551 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
68552 remoteCertificate->length);
68553 if(mbedErr)
68554 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68555
68556 /* Check the key length */
68557#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
68558 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
68559 if(rsaContext->len < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
68560 rsaContext->len > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
68561#else
68562 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
68563 if(keylen < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH ||
68564 keylen > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH)
68565#endif
68566 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
68567
68568 return UA_STATUSCODE_GOOD;
68569}
68570
68571static void
68572channelContext_deleteContext_sp_basic256(Basic256_ChannelContext *cc) {
68573 UA_ByteString_clear(&cc->localSymSigningKey);
68574 UA_ByteString_clear(&cc->localSymEncryptingKey);
68575 UA_ByteString_clear(&cc->localSymIv);
68576
68577 UA_ByteString_clear(&cc->remoteSymSigningKey);
68578 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
68579 UA_ByteString_clear(&cc->remoteSymIv);
68580
68581 mbedtls_x509_crt_free(&cc->remoteCertificate);
68582
68583 UA_free(cc);
68584}
68585
68586static UA_StatusCode
68587channelContext_newContext_sp_basic256(const UA_SecurityPolicy *securityPolicy,
68588 const UA_ByteString *remoteCertificate,
68589 void **pp_contextData) {
68590 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
68591 return UA_STATUSCODE_BADINTERNALERROR;
68592
68593 /* Allocate the channel context */
68594 *pp_contextData = UA_malloc(sizeof(Basic256_ChannelContext));
68595 if(*pp_contextData == NULL)
68596 return UA_STATUSCODE_BADOUTOFMEMORY;
68597
68598 Basic256_ChannelContext *cc = (Basic256_ChannelContext *)*pp_contextData;
68599
68600 /* Initialize the channel context */
68601 cc->policyContext = (Basic256_PolicyContext *)securityPolicy->policyContext;
68602
68603 UA_ByteString_init(&cc->localSymSigningKey);
68604 UA_ByteString_init(&cc->localSymEncryptingKey);
68605 UA_ByteString_init(&cc->localSymIv);
68606
68607 UA_ByteString_init(&cc->remoteSymSigningKey);
68608 UA_ByteString_init(&cc->remoteSymEncryptingKey);
68609 UA_ByteString_init(&cc->remoteSymIv);
68610
68611 mbedtls_x509_crt_init(&cc->remoteCertificate);
68612
68613 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
68614 UA_StatusCode retval = parseRemoteCertificate_sp_basic256(cc, remoteCertificate);
68615 if(retval != UA_STATUSCODE_GOOD) {
68616 channelContext_deleteContext_sp_basic256(cc);
68617 *pp_contextData = NULL;
68618 }
68619 return retval;
68620}
68621
68622static UA_StatusCode
68623channelContext_setLocalSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc,
68624 const UA_ByteString *key) {
68625 if(key == NULL || cc == NULL)
68626 return UA_STATUSCODE_BADINTERNALERROR;
68627
68628 UA_ByteString_clear(&cc->localSymEncryptingKey);
68629 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
68630}
68631
68632static UA_StatusCode
68633channelContext_setLocalSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
68634 const UA_ByteString *key) {
68635 if(key == NULL || cc == NULL)
68636 return UA_STATUSCODE_BADINTERNALERROR;
68637
68638 UA_ByteString_clear(&cc->localSymSigningKey);
68639 return UA_ByteString_copy(key, &cc->localSymSigningKey);
68640}
68641
68642
68643static UA_StatusCode
68644channelContext_setLocalSymIv_sp_basic256(Basic256_ChannelContext *cc,
68645 const UA_ByteString *iv) {
68646 if(iv == NULL || cc == NULL)
68647 return UA_STATUSCODE_BADINTERNALERROR;
68648
68649 UA_ByteString_clear(&cc->localSymIv);
68650 return UA_ByteString_copy(iv, &cc->localSymIv);
68651}
68652
68653static UA_StatusCode
68654channelContext_setRemoteSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc,
68655 const UA_ByteString *key) {
68656 if(key == NULL || cc == NULL)
68657 return UA_STATUSCODE_BADINTERNALERROR;
68658
68659 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
68660 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
68661}
68662
68663static UA_StatusCode
68664channelContext_setRemoteSymSigningKey_sp_basic256(Basic256_ChannelContext *cc,
68665 const UA_ByteString *key) {
68666 if(key == NULL || cc == NULL)
68667 return UA_STATUSCODE_BADINTERNALERROR;
68668
68669 UA_ByteString_clear(&cc->remoteSymSigningKey);
68670 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
68671}
68672
68673static UA_StatusCode
68674channelContext_setRemoteSymIv_sp_basic256(Basic256_ChannelContext *cc,
68675 const UA_ByteString *iv) {
68676 if(iv == NULL || cc == NULL)
68677 return UA_STATUSCODE_BADINTERNALERROR;
68678
68679 UA_ByteString_clear(&cc->remoteSymIv);
68680 return UA_ByteString_copy(iv, &cc->remoteSymIv);
68681}
68682
68683static UA_StatusCode
68684channelContext_compareCertificate_sp_basic256(const Basic256_ChannelContext *cc,
68685 const UA_ByteString *certificate) {
68686 if(cc == NULL || certificate == NULL)
68687 return UA_STATUSCODE_BADINTERNALERROR;
68688
68689 mbedtls_x509_crt cert;
68690 mbedtls_x509_crt_init(&cert);
68691 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
68692 if(mbedErr)
68693 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68694
68695 UA_StatusCode retval = UA_STATUSCODE_GOOD;
68696 if(cert.raw.len != cc->remoteCertificate.raw.len ||
68697 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
68698 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68699
68700 mbedtls_x509_crt_free(&cert);
68701 return retval;
68702}
68703
68704static void
68705clear_sp_basic256(UA_SecurityPolicy *securityPolicy) {
68706 if(securityPolicy == NULL)
68707 return;
68708
68709 UA_ByteString_clear(&securityPolicy->localCertificate);
68710
68711 if(securityPolicy->policyContext == NULL)
68712 return;
68713
68714 /* delete all allocated members in the context */
68715 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68716 securityPolicy->policyContext;
68717
68718 mbedtls_ctr_drbg_free(&pc->drbgContext);
68719 mbedtls_entropy_free(&pc->entropyContext);
68720 mbedtls_pk_free(&pc->localPrivateKey);
68721 mbedtls_md_free(&pc->sha1MdContext);
68722 UA_ByteString_clear(&pc->localCertThumbprint);
68723
68724 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68725 "Deleted members of EndpointContext for sp_basic256");
68726
68727 UA_free(pc);
68728 securityPolicy->policyContext = NULL;
68729}
68730
68731static UA_StatusCode
68732updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy,
68733 const UA_ByteString newCertificate,
68734 const UA_ByteString newPrivateKey) {
68735 if(securityPolicy == NULL)
68736 return UA_STATUSCODE_BADINTERNALERROR;
68737
68738 if(securityPolicy->policyContext == NULL)
68739 return UA_STATUSCODE_BADINTERNALERROR;
68740
68741 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68742 securityPolicy->policyContext;
68743
68744 UA_ByteString_clear(&securityPolicy->localCertificate);
68745
68746 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
68747
68748 if (retval != UA_STATUSCODE_GOOD)
68749 return retval;
68750
68751 /* Set the new private key */
68752 mbedtls_pk_free(&pc->localPrivateKey);
68753 mbedtls_pk_init(&pc->localPrivateKey);
68754
68755 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
68756
68757 if(mbedErr) {
68758 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68759 goto error;
68760 }
68761
68762 retval = asym_makeThumbprint_sp_basic256(securityPolicy,
68763 &securityPolicy->localCertificate,
68764 &pc->localCertThumbprint);
68765 if(retval != UA_STATUSCODE_GOOD)
68766 goto error;
68767
68768 return retval;
68769
68770 error:
68771 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68772 "Could not update certificate and private key");
68773 if(securityPolicy->policyContext != NULL)
68774 clear_sp_basic256(securityPolicy);
68775 return retval;
68776}
68777
68778static UA_StatusCode
68779policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy,
68780 const UA_ByteString localPrivateKey) {
68781 UA_StatusCode retval = UA_STATUSCODE_GOOD;
68782 if(securityPolicy == NULL)
68783 return UA_STATUSCODE_BADINTERNALERROR;
68784
68785 if (localPrivateKey.length == 0) {
68786 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68787 "Can not initialize security policy. Private key is empty.");
68788 return UA_STATUSCODE_BADINVALIDARGUMENT;
68789 }
68790
68791 Basic256_PolicyContext *pc = (Basic256_PolicyContext *)
68792 UA_malloc(sizeof(Basic256_PolicyContext));
68793 securityPolicy->policyContext = (void *)pc;
68794 if(!pc) {
68795 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68796 goto error;
68797 }
68798
68799 /* Initialize the PolicyContext */
68800 memset(pc, 0, sizeof(Basic256_PolicyContext));
68801 mbedtls_ctr_drbg_init(&pc->drbgContext);
68802 mbedtls_entropy_init(&pc->entropyContext);
68803 mbedtls_pk_init(&pc->localPrivateKey);
68804 mbedtls_md_init(&pc->sha1MdContext);
68805
68806 /* Initialized the message digest */
68807 const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
68808 int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1);
68809 if(mbedErr) {
68810 retval = UA_STATUSCODE_BADOUTOFMEMORY;
68811 goto error;
68812 }
68813
68814 mbedErr = mbedtls_entropy_self_test(0);
68815
68816 if(mbedErr) {
68817 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68818 goto error;
68819 }
68820
68821 /* Seed the RNG */
68822 char *personalization = "open62541-drbg";
68823 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
68824 &pc->entropyContext,
68825 (const unsigned char *)personalization, 14);
68826 if(mbedErr) {
68827 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68828 goto error;
68829 }
68830
68831 /* Set the private key */
68832 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
68833 if(mbedErr) {
68834 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
68835 goto error;
68836 }
68837
68838 /* Set the local certificate thumbprint */
68839 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
68840 if(retval != UA_STATUSCODE_GOOD)
68841 goto error;
68842 retval = asym_makeThumbprint_sp_basic256(securityPolicy,
68843 &securityPolicy->localCertificate,
68844 &pc->localCertThumbprint);
68845 if(retval != UA_STATUSCODE_GOOD)
68846 goto error;
68847
68848 return UA_STATUSCODE_GOOD;
68849
68850error:
68851 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
68852 "Could not create securityContext: %s", UA_StatusCode_name(retval));
68853 if(securityPolicy->policyContext != NULL)
68854 clear_sp_basic256(securityPolicy);
68855 return retval;
68856}
68857
68858UA_StatusCode
68859UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
68860 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
68861 memset(policy, 0, sizeof(UA_SecurityPolicy));
68862 policy->logger = logger;
68863
68864 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256\0");
68865
68866 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
68867 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
68868 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
68869
68870 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
68871
68872 if (retval != UA_STATUSCODE_GOOD)
68873 return retval;
68874
68875 /* AsymmetricModule */
68876 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
68877 &asymmetricModule->cryptoModule.signatureAlgorithm;
68878 asym_signatureAlgorithm->uri =
68879 UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0");
68880 asym_signatureAlgorithm->verify =
68881 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256;
68882 asym_signatureAlgorithm->sign =
68883 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256;
68884 asym_signatureAlgorithm->getLocalSignatureSize =
68885 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256;
68886 asym_signatureAlgorithm->getRemoteSignatureSize =
68887 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256;
68888 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
68889 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
68890
68891 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
68892 &asymmetricModule->cryptoModule.encryptionAlgorithm;
68893 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
68894 asym_encryptionAlgorithm->encrypt =
68895 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256;
68896 asym_encryptionAlgorithm->decrypt =
68897 (UA_StatusCode(*)(void *, UA_ByteString *))asym_decrypt_sp_basic256;
68898 asym_encryptionAlgorithm->getLocalKeyLength =
68899 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256;
68900 asym_encryptionAlgorithm->getRemoteKeyLength =
68901 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256;
68902 asym_encryptionAlgorithm->getRemoteBlockSize =
68903 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256;
68904 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68905 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256;
68906
68907 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256;
68908 asymmetricModule->compareCertificateThumbprint =
68909 asymmetricModule_compareCertificateThumbprint_sp_basic256;
68910
68911 /* SymmetricModule */
68912 symmetricModule->generateKey = sym_generateKey_sp_basic256;
68913 symmetricModule->generateNonce = sym_generateNonce_sp_basic256;
68914
68915 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
68916 &symmetricModule->cryptoModule.signatureAlgorithm;
68917 sym_signatureAlgorithm->uri =
68918 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
68919 sym_signatureAlgorithm->verify =
68920 (UA_StatusCode (*)(void *, const UA_ByteString *,
68921 const UA_ByteString *))sym_verify_sp_basic256;
68922 sym_signatureAlgorithm->sign =
68923 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256;
68924 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256;
68925 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256;
68926 sym_signatureAlgorithm->getLocalKeyLength =
68927 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
68928 sym_signatureAlgorithm->getRemoteKeyLength =
68929 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256;
68930
68931 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
68932 &symmetricModule->cryptoModule.encryptionAlgorithm;
68933 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0");
68934 sym_encryptionAlgorithm->encrypt =
68935 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256;
68936 sym_encryptionAlgorithm->decrypt =
68937 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256;
68938 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256;
68939 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256;
68940 sym_encryptionAlgorithm->getRemoteBlockSize =
68941 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256;
68942 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
68943 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256;
68944 symmetricModule->secureChannelNonceLength = 32;
68945
68946 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
68947 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
68948
68949 /* ChannelModule */
68950 channelModule->newContext = channelContext_newContext_sp_basic256;
68951 channelModule->deleteContext = (void (*)(void *))
68952 channelContext_deleteContext_sp_basic256;
68953
68954 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68955 channelContext_setLocalSymEncryptingKey_sp_basic256;
68956 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68957 channelContext_setLocalSymSigningKey_sp_basic256;
68958 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68959 channelContext_setLocalSymIv_sp_basic256;
68960
68961 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68962 channelContext_setRemoteSymEncryptingKey_sp_basic256;
68963 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
68964 channelContext_setRemoteSymSigningKey_sp_basic256;
68965 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
68966 channelContext_setRemoteSymIv_sp_basic256;
68967
68968 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
68969 channelContext_compareCertificate_sp_basic256;
68970
68971 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256;
68972 policy->clear = clear_sp_basic256;
68973
68974 UA_StatusCode res = policyContext_newContext_sp_basic256(policy, localPrivateKey);
68975 if(res != UA_STATUSCODE_GOOD)
68976 clear_sp_basic256(policy);
68977
68978 return res;
68979}
68980
68981#endif
68982
68983/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256sha256.c" ****/
68984
68985/* This Source Code Form is subject to the terms of the Mozilla Public
68986 * License, v. 2.0. If a copy of the MPL was not distributed with this
68987 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
68988 *
68989 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
68990 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
68991 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
68992 * Copyright 2020 (c) Wind River Systems, Inc.
68993 * Copyright 2020 (c) basysKom GmbH
68994 */
68995
68996
68997#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
68998
68999
69000#include <mbedtls/aes.h>
69001#include <mbedtls/ctr_drbg.h>
69002#include <mbedtls/entropy.h>
69003#include <mbedtls/error.h>
69004#include <mbedtls/md.h>
69005#include <mbedtls/sha1.h>
69006#include <mbedtls/sha256.h>
69007#include <mbedtls/version.h>
69008#include <mbedtls/x509_crt.h>
69009
69010/* Notes:
69011 * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to
69012 * allocate temp buffers.
69013 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
69014 */
69015
69016#define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42
69017#define UA_SHA1_LENGTH 20
69018#define UA_SHA256_LENGTH 32
69019#define UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32
69020#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH 32
69021#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16
69022#define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16
69023#define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256
69024#define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512
69025
69026typedef struct {
69027 UA_ByteString localCertThumbprint;
69028
69029 mbedtls_ctr_drbg_context drbgContext;
69030 mbedtls_entropy_context entropyContext;
69031 mbedtls_md_context_t sha256MdContext;
69032 mbedtls_pk_context localPrivateKey;
69033} Basic256Sha256_PolicyContext;
69034
69035typedef struct {
69036 Basic256Sha256_PolicyContext *policyContext;
69037
69038 UA_ByteString localSymSigningKey;
69039 UA_ByteString localSymEncryptingKey;
69040 UA_ByteString localSymIv;
69041
69042 UA_ByteString remoteSymSigningKey;
69043 UA_ByteString remoteSymEncryptingKey;
69044 UA_ByteString remoteSymIv;
69045
69046 mbedtls_x509_crt remoteCertificate;
69047} Basic256Sha256_ChannelContext;
69048
69049/********************/
69050/* AsymmetricModule */
69051/********************/
69052
69053/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69054static UA_StatusCode
69055asym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69056 const UA_ByteString *message,
69057 const UA_ByteString *signature) {
69058 if(message == NULL || signature == NULL || cc == NULL)
69059 return UA_STATUSCODE_BADINTERNALERROR;
69060
69061 unsigned char hash[UA_SHA256_LENGTH];
69062#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69063 // TODO check return status
69064 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69065#else
69066 mbedtls_sha256(message->data, message->length, hash, 0);
69067#endif
69068
69069 /* Set the RSA settings */
69070 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69071 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69072
69073 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */
69074 /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */
69075 /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL,
69076 MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
69077 UA_SHA256_LENGTH, hash,
69078 signature->data); */
69079 int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
69080 MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH,
69081 signature->data, signature->length);
69082
69083 if(mbedErr)
69084 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69085 return UA_STATUSCODE_GOOD;
69086}
69087
69088/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69089static UA_StatusCode
69090asym_sign_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69091 const UA_ByteString *message,
69092 UA_ByteString *signature) {
69093 if(message == NULL || signature == NULL || cc == NULL)
69094 return UA_STATUSCODE_BADINTERNALERROR;
69095
69096 unsigned char hash[UA_SHA256_LENGTH];
69097#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69098 // TODO check return status
69099 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69100#else
69101 mbedtls_sha256(message->data, message->length, hash, 0);
69102#endif
69103
69104 Basic256Sha256_PolicyContext *pc = cc->policyContext;
69105 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
69106 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69107
69108 size_t sigLen = 0;
69109
69110 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */
69111 /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */
69112 int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
69113 MBEDTLS_MD_SHA256, hash,
69114 UA_SHA256_LENGTH, signature->data,
69115#if MBEDTLS_VERSION_NUMBER >= 0x03000000
69116 signature->length,
69117#endif
69118 &sigLen, mbedtls_ctr_drbg_random,
69119 &pc->drbgContext);
69120 if(mbedErr)
69121 return UA_STATUSCODE_BADINTERNALERROR;
69122 return UA_STATUSCODE_GOOD;
69123}
69124
69125static size_t
69126asym_getLocalSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69127 if(cc == NULL)
69128 return 0;
69129#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69130 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
69131#else
69132 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
69133#endif
69134}
69135
69136static size_t
69137asym_getRemoteSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69138 if(cc == NULL)
69139 return 0;
69140#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69141 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
69142#else
69143 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69144#endif
69145}
69146
69147static size_t
69148asym_getRemoteBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69149#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69150 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69151 return rsaContext->len;
69152#else
69153 if(cc == NULL)
69154 return 0;
69155 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69156#endif
69157}
69158
69159static size_t
69160asym_getRemotePlainTextBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69161#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69162 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69163 return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
69164#else
69165 if(cc == NULL)
69166 return 0;
69167 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
69168 UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN;
69169#endif
69170}
69171
69172
69173/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69174static UA_StatusCode
69175asym_encrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69176 UA_ByteString *data) {
69177 if(cc == NULL || data == NULL)
69178 return UA_STATUSCODE_BADINTERNALERROR;
69179
69180 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256sha256(cc);
69181
69182 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69183 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
69184
69185 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
69186 data, plainTextBlockSize);
69187}
69188
69189/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
69190static UA_StatusCode
69191asym_decrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69192 UA_ByteString *data) {
69193 if(cc == NULL || data == NULL)
69194 return UA_STATUSCODE_BADINTERNALERROR;
69195 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
69196 &cc->policyContext->drbgContext, data);
69197}
69198
69199static size_t
69200asym_getLocalEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69201 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
69202}
69203
69204static size_t
69205asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) {
69206 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
69207}
69208
69209static UA_StatusCode
69210asym_makeThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69211 const UA_ByteString *certificate,
69212 UA_ByteString *thumbprint) {
69213 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
69214 return UA_STATUSCODE_BADINTERNALERROR;
69215 return mbedtls_thumbprint_sha1(certificate, thumbprint);
69216}
69217
69218static UA_StatusCode
69219asymmetricModule_compareCertificateThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69220 const UA_ByteString *certificateThumbprint) {
69221 if(securityPolicy == NULL || certificateThumbprint == NULL)
69222 return UA_STATUSCODE_BADINTERNALERROR;
69223
69224 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
69225 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
69226 return UA_STATUSCODE_BADCERTIFICATEINVALID;
69227
69228 return UA_STATUSCODE_GOOD;
69229}
69230
69231/*******************/
69232/* SymmetricModule */
69233/*******************/
69234
69235static UA_StatusCode
69236sym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69237 const UA_ByteString *message,
69238 const UA_ByteString *signature) {
69239 if(cc == NULL || message == NULL || signature == NULL)
69240 return UA_STATUSCODE_BADINTERNALERROR;
69241
69242 /* Compute MAC */
69243 if(signature->length != UA_SHA256_LENGTH)
69244 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69245
69246 Basic256Sha256_PolicyContext *pc = cc->policyContext;
69247 unsigned char mac[UA_SHA256_LENGTH];
69248 mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
69249
69250 /* Compare with Signature */
69251 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH))
69252 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69253 return UA_STATUSCODE_GOOD;
69254}
69255
69256static UA_StatusCode
69257sym_sign_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69258 const UA_ByteString *message,
69259 UA_ByteString *signature) {
69260 if(signature->length != UA_SHA256_LENGTH)
69261 return UA_STATUSCODE_BADINTERNALERROR;
69262
69263 mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
69264 message, signature->data);
69265 return UA_STATUSCODE_GOOD;
69266}
69267
69268static size_t
69269sym_getSignatureSize_sp_basic256sha256(const void *channelContext) {
69270 return UA_SHA256_LENGTH;
69271}
69272
69273static size_t
69274sym_getSigningKeyLength_sp_basic256sha256(const void *channelContext) {
69275 return UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH;
69276}
69277
69278static size_t
69279sym_getEncryptionKeyLength_sp_basic256sha256(const void *channelContext) {
69280 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH;
69281}
69282
69283static size_t
69284sym_getEncryptionBlockSize_sp_basic256sha256(const void *channelContext) {
69285 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
69286}
69287
69288static size_t
69289sym_getPlainTextBlockSize_sp_basic256sha256(const void *channelContext) {
69290 return UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
69291}
69292
69293static UA_StatusCode
69294sym_encrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69295 UA_ByteString *data) {
69296 if(cc == NULL || data == NULL)
69297 return UA_STATUSCODE_BADINTERNALERROR;
69298
69299 if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE)
69300 return UA_STATUSCODE_BADINTERNALERROR;
69301
69302 size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE;
69303
69304 if(data->length % plainTextBlockSize != 0)
69305 return UA_STATUSCODE_BADINTERNALERROR;
69306
69307 /* Keylength in bits */
69308 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
69309 mbedtls_aes_context aesContext;
69310 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
69311 if(mbedErr)
69312 return UA_STATUSCODE_BADINTERNALERROR;
69313
69314 UA_ByteString ivCopy;
69315 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
69316 if(retval != UA_STATUSCODE_GOOD)
69317 return retval;
69318
69319 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
69320 ivCopy.data, data->data, data->data);
69321 if(mbedErr)
69322 retval = UA_STATUSCODE_BADINTERNALERROR;
69323 UA_ByteString_clear(&ivCopy);
69324 return retval;
69325}
69326
69327static UA_StatusCode
69328sym_decrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69329 UA_ByteString *data) {
69330 if(cc == NULL || data == NULL)
69331 return UA_STATUSCODE_BADINTERNALERROR;
69332
69333 size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE;
69334 if(cc->remoteSymIv.length != encryptionBlockSize)
69335 return UA_STATUSCODE_BADINTERNALERROR;
69336
69337 if(data->length % encryptionBlockSize != 0)
69338 return UA_STATUSCODE_BADINTERNALERROR;
69339
69340 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
69341 mbedtls_aes_context aesContext;
69342 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
69343 if(mbedErr)
69344 return UA_STATUSCODE_BADINTERNALERROR;
69345
69346 UA_ByteString ivCopy;
69347 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
69348 if(retval != UA_STATUSCODE_GOOD)
69349 return retval;
69350
69351 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
69352 ivCopy.data, data->data, data->data);
69353 if(mbedErr)
69354 retval = UA_STATUSCODE_BADINTERNALERROR;
69355 UA_ByteString_clear(&ivCopy);
69356 return retval;
69357}
69358
69359static UA_StatusCode
69360sym_generateKey_sp_basic256sha256(void *policyContext, const UA_ByteString *secret,
69361 const UA_ByteString *seed, UA_ByteString *out) {
69362 if(secret == NULL || seed == NULL || out == NULL)
69363 return UA_STATUSCODE_BADINTERNALERROR;
69364 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
69365 return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
69366}
69367
69368static UA_StatusCode
69369sym_generateNonce_sp_basic256sha256(void *policyContext, UA_ByteString *out) {
69370 if(out == NULL)
69371 return UA_STATUSCODE_BADINTERNALERROR;
69372 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext;
69373 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
69374 if(mbedErr)
69375 return UA_STATUSCODE_BADUNEXPECTEDERROR;
69376 return UA_STATUSCODE_GOOD;
69377}
69378
69379/*****************/
69380/* ChannelModule */
69381/*****************/
69382
69383/* Assumes that the certificate has been verified externally */
69384static UA_StatusCode
69385parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69386 const UA_ByteString *remoteCertificate) {
69387 if(remoteCertificate == NULL || cc == NULL)
69388 return UA_STATUSCODE_BADINTERNALERROR;
69389
69390 /* Parse the certificate */
69391 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
69392 remoteCertificate->length);
69393 if(mbedErr)
69394 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69395
69396 /* Check the key length */
69397#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69398 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69399 if(rsaContext->len < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
69400 rsaContext->len > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
69401#else
69402 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69403 if(keylen < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH ||
69404 keylen > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH)
69405#endif
69406 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
69407
69408 return UA_STATUSCODE_GOOD;
69409}
69410
69411static void
69412channelContext_deleteContext_sp_basic256sha256(Basic256Sha256_ChannelContext *cc) {
69413 UA_ByteString_clear(&cc->localSymSigningKey);
69414 UA_ByteString_clear(&cc->localSymEncryptingKey);
69415 UA_ByteString_clear(&cc->localSymIv);
69416
69417 UA_ByteString_clear(&cc->remoteSymSigningKey);
69418 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
69419 UA_ByteString_clear(&cc->remoteSymIv);
69420
69421 mbedtls_x509_crt_free(&cc->remoteCertificate);
69422
69423 UA_free(cc);
69424}
69425
69426static UA_StatusCode
69427channelContext_newContext_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy,
69428 const UA_ByteString *remoteCertificate,
69429 void **pp_contextData) {
69430 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
69431 return UA_STATUSCODE_BADINTERNALERROR;
69432
69433 /* Allocate the channel context */
69434 *pp_contextData = UA_malloc(sizeof(Basic256Sha256_ChannelContext));
69435 if(*pp_contextData == NULL)
69436 return UA_STATUSCODE_BADOUTOFMEMORY;
69437
69438 Basic256Sha256_ChannelContext *cc = (Basic256Sha256_ChannelContext *)*pp_contextData;
69439
69440 /* Initialize the channel context */
69441 cc->policyContext = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext;
69442
69443 UA_ByteString_init(&cc->localSymSigningKey);
69444 UA_ByteString_init(&cc->localSymEncryptingKey);
69445 UA_ByteString_init(&cc->localSymIv);
69446
69447 UA_ByteString_init(&cc->remoteSymSigningKey);
69448 UA_ByteString_init(&cc->remoteSymEncryptingKey);
69449 UA_ByteString_init(&cc->remoteSymIv);
69450
69451 mbedtls_x509_crt_init(&cc->remoteCertificate);
69452
69453 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
69454 UA_StatusCode retval = parseRemoteCertificate_sp_basic256sha256(cc, remoteCertificate);
69455 if(retval != UA_STATUSCODE_GOOD) {
69456 channelContext_deleteContext_sp_basic256sha256(cc);
69457 *pp_contextData = NULL;
69458 }
69459 return retval;
69460}
69461
69462static UA_StatusCode
69463channelContext_setLocalSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69464 const UA_ByteString *key) {
69465 if(key == NULL || cc == NULL)
69466 return UA_STATUSCODE_BADINTERNALERROR;
69467
69468 UA_ByteString_clear(&cc->localSymEncryptingKey);
69469 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
69470}
69471
69472static UA_StatusCode
69473channelContext_setLocalSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69474 const UA_ByteString *key) {
69475 if(key == NULL || cc == NULL)
69476 return UA_STATUSCODE_BADINTERNALERROR;
69477
69478 UA_ByteString_clear(&cc->localSymSigningKey);
69479 return UA_ByteString_copy(key, &cc->localSymSigningKey);
69480}
69481
69482
69483static UA_StatusCode
69484channelContext_setLocalSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69485 const UA_ByteString *iv) {
69486 if(iv == NULL || cc == NULL)
69487 return UA_STATUSCODE_BADINTERNALERROR;
69488
69489 UA_ByteString_clear(&cc->localSymIv);
69490 return UA_ByteString_copy(iv, &cc->localSymIv);
69491}
69492
69493static UA_StatusCode
69494channelContext_setRemoteSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69495 const UA_ByteString *key) {
69496 if(key == NULL || cc == NULL)
69497 return UA_STATUSCODE_BADINTERNALERROR;
69498
69499 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
69500 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
69501}
69502
69503static UA_StatusCode
69504channelContext_setRemoteSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69505 const UA_ByteString *key) {
69506 if(key == NULL || cc == NULL)
69507 return UA_STATUSCODE_BADINTERNALERROR;
69508
69509 UA_ByteString_clear(&cc->remoteSymSigningKey);
69510 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
69511}
69512
69513static UA_StatusCode
69514channelContext_setRemoteSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc,
69515 const UA_ByteString *iv) {
69516 if(iv == NULL || cc == NULL)
69517 return UA_STATUSCODE_BADINTERNALERROR;
69518
69519 UA_ByteString_clear(&cc->remoteSymIv);
69520 return UA_ByteString_copy(iv, &cc->remoteSymIv);
69521}
69522
69523static UA_StatusCode
69524channelContext_compareCertificate_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc,
69525 const UA_ByteString *certificate) {
69526 if(cc == NULL || certificate == NULL)
69527 return UA_STATUSCODE_BADINTERNALERROR;
69528
69529 mbedtls_x509_crt cert;
69530 mbedtls_x509_crt_init(&cert);
69531 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
69532 if(mbedErr)
69533 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69534
69535 UA_StatusCode retval = UA_STATUSCODE_GOOD;
69536 if(cert.raw.len != cc->remoteCertificate.raw.len ||
69537 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
69538 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69539
69540 mbedtls_x509_crt_free(&cert);
69541 return retval;
69542}
69543
69544static void
69545clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) {
69546 if(securityPolicy == NULL)
69547 return;
69548
69549 UA_ByteString_clear(&securityPolicy->localCertificate);
69550
69551 if(securityPolicy->policyContext == NULL)
69552 return;
69553
69554 /* delete all allocated members in the context */
69555 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
69556 securityPolicy->policyContext;
69557
69558 mbedtls_ctr_drbg_free(&pc->drbgContext);
69559 mbedtls_entropy_free(&pc->entropyContext);
69560 mbedtls_pk_free(&pc->localPrivateKey);
69561 mbedtls_md_free(&pc->sha256MdContext);
69562 UA_ByteString_clear(&pc->localCertThumbprint);
69563
69564 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69565 "Deleted members of EndpointContext for sp_basic256sha256");
69566
69567 UA_free(pc);
69568 securityPolicy->policyContext = NULL;
69569}
69570
69571static UA_StatusCode
69572updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
69573 const UA_ByteString newCertificate,
69574 const UA_ByteString newPrivateKey) {
69575 if(securityPolicy == NULL)
69576 return UA_STATUSCODE_BADINTERNALERROR;
69577
69578 if(securityPolicy->policyContext == NULL)
69579 return UA_STATUSCODE_BADINTERNALERROR;
69580
69581 Basic256Sha256_PolicyContext *pc =
69582 (Basic256Sha256_PolicyContext *) securityPolicy->policyContext;
69583
69584 UA_ByteString_clear(&securityPolicy->localCertificate);
69585
69586 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate);
69587
69588 if (retval != UA_STATUSCODE_GOOD)
69589 return retval;
69590
69591 /* Set the new private key */
69592 mbedtls_pk_free(&pc->localPrivateKey);
69593 mbedtls_pk_init(&pc->localPrivateKey);
69594 int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
69595 if(mbedErr) {
69596 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69597 goto error;
69598 }
69599
69600 retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy,
69601 &securityPolicy->localCertificate,
69602 &pc->localCertThumbprint);
69603 if(retval != UA_STATUSCODE_GOOD)
69604 goto error;
69605
69606 return retval;
69607
69608 error:
69609 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69610 "Could not update certificate and private key");
69611 if(securityPolicy->policyContext != NULL)
69612 clear_sp_basic256sha256(securityPolicy);
69613 return retval;
69614}
69615
69616static UA_StatusCode
69617policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy,
69618 const UA_ByteString localPrivateKey) {
69619 UA_StatusCode retval = UA_STATUSCODE_GOOD;
69620 if(securityPolicy == NULL)
69621 return UA_STATUSCODE_BADINTERNALERROR;
69622
69623 if (localPrivateKey.length == 0) {
69624 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69625 "Can not initialize security policy. Private key is empty.");
69626 return UA_STATUSCODE_BADINVALIDARGUMENT;
69627 }
69628
69629 Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)
69630 UA_malloc(sizeof(Basic256Sha256_PolicyContext));
69631 securityPolicy->policyContext = (void *)pc;
69632 if(!pc) {
69633 retval = UA_STATUSCODE_BADOUTOFMEMORY;
69634 goto error;
69635 }
69636
69637 /* Initialize the PolicyContext */
69638 memset(pc, 0, sizeof(Basic256Sha256_PolicyContext));
69639 mbedtls_ctr_drbg_init(&pc->drbgContext);
69640 mbedtls_entropy_init(&pc->entropyContext);
69641 mbedtls_pk_init(&pc->localPrivateKey);
69642 mbedtls_md_init(&pc->sha256MdContext);
69643
69644 /* Initialized the message digest */
69645 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
69646 int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256);
69647 if(mbedErr) {
69648 retval = UA_STATUSCODE_BADOUTOFMEMORY;
69649 goto error;
69650 }
69651
69652 mbedErr = mbedtls_entropy_self_test(0);
69653
69654 if(mbedErr) {
69655 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69656 goto error;
69657 }
69658
69659 /* Seed the RNG */
69660 char *personalization = "open62541-drbg";
69661 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
69662 &pc->entropyContext,
69663 (const unsigned char *)personalization, 14);
69664 if(mbedErr) {
69665 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69666 goto error;
69667 }
69668
69669 /* Set the private key */
69670 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
69671 if(mbedErr) {
69672 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69673 goto error;
69674 }
69675
69676 /* Set the local certificate thumbprint */
69677 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
69678 if(retval != UA_STATUSCODE_GOOD)
69679 goto error;
69680 retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy,
69681 &securityPolicy->localCertificate,
69682 &pc->localCertThumbprint);
69683 if(retval != UA_STATUSCODE_GOOD)
69684 goto error;
69685
69686 return UA_STATUSCODE_GOOD;
69687
69688error:
69689 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
69690 "Could not create securityContext: %s", UA_StatusCode_name(retval));
69691 if(securityPolicy->policyContext != NULL)
69692 clear_sp_basic256sha256(securityPolicy);
69693 return retval;
69694}
69695
69696UA_StatusCode
69697UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
69698 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
69699 memset(policy, 0, sizeof(UA_SecurityPolicy));
69700 policy->logger = logger;
69701
69702 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256");
69703
69704 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
69705 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
69706 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
69707
69708 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
69709
69710 if (retval != UA_STATUSCODE_GOOD)
69711 return retval;
69712
69713 /* AsymmetricModule */
69714 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
69715 &asymmetricModule->cryptoModule.signatureAlgorithm;
69716 asym_signatureAlgorithm->uri =
69717 UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
69718 asym_signatureAlgorithm->verify =
69719 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256sha256;
69720 asym_signatureAlgorithm->sign =
69721 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256sha256;
69722 asym_signatureAlgorithm->getLocalSignatureSize =
69723 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256sha256;
69724 asym_signatureAlgorithm->getRemoteSignatureSize =
69725 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256sha256;
69726 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
69727 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
69728
69729 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
69730 &asymmetricModule->cryptoModule.encryptionAlgorithm;
69731 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
69732 asym_encryptionAlgorithm->encrypt =
69733 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256sha256;
69734 asym_encryptionAlgorithm->decrypt =
69735 (UA_StatusCode(*)(void *, UA_ByteString *))
69736 asym_decrypt_sp_basic256sha256;
69737 asym_encryptionAlgorithm->getLocalKeyLength =
69738 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256sha256;
69739 asym_encryptionAlgorithm->getRemoteKeyLength =
69740 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256sha256;
69741 asym_encryptionAlgorithm->getRemoteBlockSize =
69742 (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256sha256;
69743 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
69744 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256;
69745
69746 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256sha256;
69747 asymmetricModule->compareCertificateThumbprint =
69748 asymmetricModule_compareCertificateThumbprint_sp_basic256sha256;
69749
69750 /* SymmetricModule */
69751 symmetricModule->generateKey = sym_generateKey_sp_basic256sha256;
69752 symmetricModule->generateNonce = sym_generateNonce_sp_basic256sha256;
69753
69754 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
69755 &symmetricModule->cryptoModule.signatureAlgorithm;
69756 sym_signatureAlgorithm->uri =
69757 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
69758 sym_signatureAlgorithm->verify =
69759 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_basic256sha256;
69760 sym_signatureAlgorithm->sign =
69761 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256sha256;
69762 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256sha256;
69763 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256sha256;
69764 sym_signatureAlgorithm->getLocalKeyLength =
69765 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
69766 sym_signatureAlgorithm->getRemoteKeyLength =
69767 (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256;
69768
69769 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
69770 &symmetricModule->cryptoModule.encryptionAlgorithm;
69771 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc");
69772 sym_encryptionAlgorithm->encrypt =
69773 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256sha256;
69774 sym_encryptionAlgorithm->decrypt =
69775 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256sha256;
69776 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
69777 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256;
69778 sym_encryptionAlgorithm->getRemoteBlockSize =
69779 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256sha256;
69780 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
69781 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256sha256;
69782 symmetricModule->secureChannelNonceLength = 32;
69783
69784 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
69785 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
69786
69787 /* ChannelModule */
69788 channelModule->newContext = channelContext_newContext_sp_basic256sha256;
69789 channelModule->deleteContext = (void (*)(void *))
69790 channelContext_deleteContext_sp_basic256sha256;
69791
69792 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69793 channelContext_setLocalSymEncryptingKey_sp_basic256sha256;
69794 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69795 channelContext_setLocalSymSigningKey_sp_basic256sha256;
69796 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
69797 channelContext_setLocalSymIv_sp_basic256sha256;
69798
69799 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69800 channelContext_setRemoteSymEncryptingKey_sp_basic256sha256;
69801 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
69802 channelContext_setRemoteSymSigningKey_sp_basic256sha256;
69803 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
69804 channelContext_setRemoteSymIv_sp_basic256sha256;
69805
69806 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
69807 channelContext_compareCertificate_sp_basic256sha256;
69808
69809 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256sha256;
69810 policy->clear = clear_sp_basic256sha256;
69811
69812 UA_StatusCode res = policyContext_newContext_sp_basic256sha256(policy, localPrivateKey);
69813 if(res != UA_STATUSCODE_GOOD)
69814 clear_sp_basic256sha256(policy);
69815
69816 return res;
69817}
69818
69819#endif
69820
69821/**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_aes128sha256rsaoaep.c" ****/
69822
69823/* This Source Code Form is subject to the terms of the Mozilla Public
69824 * License, v. 2.0. If a copy of the MPL was not distributed with this
69825 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
69826 *
69827 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
69828 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
69829 * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green)
69830 * Copyright 2020 (c) Wind River Systems, Inc.
69831 */
69832
69833
69834#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
69835
69836
69837#include <mbedtls/aes.h>
69838#include <mbedtls/ctr_drbg.h>
69839#include <mbedtls/entropy.h>
69840#include <mbedtls/error.h>
69841#include <mbedtls/md.h>
69842#include <mbedtls/sha1.h>
69843#include <mbedtls/sha256.h>
69844#include <mbedtls/version.h>
69845#include <mbedtls/x509_crt.h>
69846
69847/* Notes:
69848 * mbedTLS' AES allows in-place encryption and decryption. So we don't have to
69849 * allocate temp buffers.
69850 * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer
69851 */
69852
69853#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42
69854#define UA_SHA1_LENGTH 20
69855#define UA_SHA256_LENGTH 32
69856#define UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32
69857#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH 16
69858#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16
69859#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16
69860#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256
69861#define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512
69862
69863typedef struct {
69864 UA_ByteString localCertThumbprint;
69865
69866 mbedtls_ctr_drbg_context drbgContext;
69867 mbedtls_entropy_context entropyContext;
69868 mbedtls_md_context_t sha256MdContext;
69869 mbedtls_pk_context localPrivateKey;
69870} Aes128Sha256PsaOaep_PolicyContext;
69871
69872typedef struct {
69873 Aes128Sha256PsaOaep_PolicyContext *policyContext;
69874
69875 UA_ByteString localSymSigningKey;
69876 UA_ByteString localSymEncryptingKey;
69877 UA_ByteString localSymIv;
69878
69879 UA_ByteString remoteSymSigningKey;
69880 UA_ByteString remoteSymEncryptingKey;
69881 UA_ByteString remoteSymIv;
69882
69883 mbedtls_x509_crt remoteCertificate;
69884} Aes128Sha256PsaOaep_ChannelContext;
69885
69886/********************/
69887/* AsymmetricModule */
69888/********************/
69889
69890/* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69891static UA_StatusCode
69892asym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69893 const UA_ByteString *message,
69894 const UA_ByteString *signature) {
69895 if(message == NULL || signature == NULL || cc == NULL)
69896 return UA_STATUSCODE_BADINTERNALERROR;
69897
69898 unsigned char hash[UA_SHA256_LENGTH];
69899#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69900 // TODO check return status
69901 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69902#else
69903 mbedtls_sha256(message->data, message->length, hash, 0);
69904#endif
69905
69906 /* Set the RSA settings */
69907 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
69908 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69909
69910 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */
69911 /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */
69912 /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL,
69913 MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
69914 UA_SHA256_LENGTH, hash,
69915 signature->data); */
69916 int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk,
69917 MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH,
69918 signature->data, signature->length);
69919
69920 if(mbedErr)
69921 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
69922 return UA_STATUSCODE_GOOD;
69923}
69924
69925/* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */
69926static UA_StatusCode
69927asym_sign_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
69928 const UA_ByteString *message,
69929 UA_ByteString *signature) {
69930 if(message == NULL || signature == NULL || cc == NULL)
69931 return UA_STATUSCODE_BADINTERNALERROR;
69932
69933 unsigned char hash[UA_SHA256_LENGTH];
69934#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69935 // TODO check return status
69936 mbedtls_sha256_ret(message->data, message->length, hash, 0);
69937#else
69938 mbedtls_sha256(message->data, message->length, hash, 0);
69939#endif
69940
69941 Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
69942 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey);
69943 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
69944
69945 size_t sigLen = 0;
69946
69947 /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */
69948 /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */
69949 int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey,
69950 MBEDTLS_MD_SHA256, hash,
69951 UA_SHA256_LENGTH, signature->data,
69952#if MBEDTLS_VERSION_NUMBER >= 0x03000000
69953 signature->length,
69954#endif
69955 &sigLen, mbedtls_ctr_drbg_random,
69956 &pc->drbgContext);
69957 if(mbedErr)
69958 return UA_STATUSCODE_BADINTERNALERROR;
69959 return UA_STATUSCODE_GOOD;
69960}
69961
69962static size_t
69963asym_getLocalSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69964#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69965 return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len;
69966#else
69967 if(cc == NULL)
69968 return 0;
69969 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey));
69970#endif
69971
69972}
69973
69974static size_t
69975asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69976#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69977 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
69978#else
69979 if(cc == NULL)
69980 return 0;
69981 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69982#endif
69983}
69984
69985static size_t
69986asym_getRemoteBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69987#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69988 return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len;
69989#else
69990 if(cc == NULL)
69991 return 0;
69992 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
69993#endif
69994}
69995
69996static size_t
69997asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
69998#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
69999 mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
70000 return rsaContext->len - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
70001#else
70002 if(cc == NULL)
70003 return 0;
70004 return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) -
70005 UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN;
70006#endif
70007}
70008
70009
70010/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
70011static UA_StatusCode
70012asym_encrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70013 UA_ByteString *data) {
70014 if(cc == NULL || data == NULL)
70015 return UA_STATUSCODE_BADINTERNALERROR;
70016
70017 const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(cc);
70018
70019 mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
70020 mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
70021
70022 return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext,
70023 data, plainTextBlockSize);
70024}
70025
70026/* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */
70027static UA_StatusCode
70028asym_decrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70029 UA_ByteString *data) {
70030 if(cc == NULL || data == NULL)
70031 return UA_STATUSCODE_BADINTERNALERROR;
70032 return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey,
70033 &cc->policyContext->drbgContext, data);
70034}
70035
70036static size_t
70037asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
70038 return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8;
70039}
70040
70041static size_t
70042asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) {
70043 return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8;
70044}
70045
70046static UA_StatusCode
70047asym_makeThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
70048 const UA_ByteString *certificate,
70049 UA_ByteString *thumbprint) {
70050 if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL)
70051 return UA_STATUSCODE_BADINTERNALERROR;
70052 return mbedtls_thumbprint_sha1(certificate, thumbprint);
70053}
70054
70055static UA_StatusCode
70056asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
70057 const UA_ByteString *certificateThumbprint) {
70058 if(securityPolicy == NULL || certificateThumbprint == NULL)
70059 return UA_STATUSCODE_BADINTERNALERROR;
70060
70061 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
70062 if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint))
70063 return UA_STATUSCODE_BADCERTIFICATEINVALID;
70064
70065 return UA_STATUSCODE_GOOD;
70066}
70067
70068/*******************/
70069/* SymmetricModule */
70070/*******************/
70071
70072static UA_StatusCode
70073sym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70074 const UA_ByteString *message,
70075 const UA_ByteString *signature) {
70076 if(cc == NULL || message == NULL || signature == NULL)
70077 return UA_STATUSCODE_BADINTERNALERROR;
70078
70079 /* Compute MAC */
70080 if(signature->length != UA_SHA256_LENGTH)
70081 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70082 Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext;
70083 unsigned char mac[UA_SHA256_LENGTH];
70084 mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac);
70085
70086 /* Compare with Signature */
70087 if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH))
70088 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70089 return UA_STATUSCODE_GOOD;
70090}
70091
70092static UA_StatusCode
70093sym_sign_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
70094 const UA_ByteString *message,
70095 UA_ByteString *signature) {
70096 if(signature->length != UA_SHA256_LENGTH)
70097 return UA_STATUSCODE_BADINTERNALERROR;
70098
70099 mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey,
70100 message, signature->data);
70101 return UA_STATUSCODE_GOOD;
70102}
70103
70104static size_t
70105sym_getSignatureSize_sp_aes128sha256rsaoaep(const void *channelContext) {
70106 return UA_SHA256_LENGTH;
70107}
70108
70109static size_t
70110sym_getSigningKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
70111 return UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH;
70112}
70113
70114static size_t
70115sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) {
70116 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH;
70117}
70118
70119static size_t
70120sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
70121 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
70122}
70123
70124static size_t
70125sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) {
70126 return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
70127}
70128
70129static UA_StatusCode
70130sym_encrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
70131 UA_ByteString *data) {
70132 if(cc == NULL || data == NULL)
70133 return UA_STATUSCODE_BADINTERNALERROR;
70134
70135 if(cc->localSymIv.length != UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE)
70136 return UA_STATUSCODE_BADINTERNALERROR;
70137
70138 size_t plainTextBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE;
70139
70140 if(data->length % plainTextBlockSize != 0)
70141 return UA_STATUSCODE_BADINTERNALERROR;
70142
70143 /* Keylength in bits */
70144 unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8);
70145 mbedtls_aes_context aesContext;
70146 int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength);
70147 if(mbedErr)
70148 return UA_STATUSCODE_BADINTERNALERROR;
70149
70150 UA_ByteString ivCopy;
70151 UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy);
70152 if(retval != UA_STATUSCODE_GOOD)
70153 return retval;
70154
70155 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length,
70156 ivCopy.data, data->data, data->data);
70157 if(mbedErr)
70158 retval = UA_STATUSCODE_BADINTERNALERROR;
70159 UA_ByteString_clear(&ivCopy);
70160 return retval;
70161}
70162
70163static UA_StatusCode
70164sym_decrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
70165 UA_ByteString *data) {
70166 if(cc == NULL || data == NULL)
70167 return UA_STATUSCODE_BADINTERNALERROR;
70168
70169 size_t encryptionBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE;
70170
70171 if(cc->remoteSymIv.length != encryptionBlockSize)
70172 return UA_STATUSCODE_BADINTERNALERROR;
70173
70174 if(data->length % encryptionBlockSize != 0)
70175 return UA_STATUSCODE_BADINTERNALERROR;
70176
70177 unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8);
70178 mbedtls_aes_context aesContext;
70179 int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength);
70180 if(mbedErr)
70181 return UA_STATUSCODE_BADINTERNALERROR;
70182
70183 UA_ByteString ivCopy;
70184 UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy);
70185 if(retval != UA_STATUSCODE_GOOD)
70186 return retval;
70187
70188 mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length,
70189 ivCopy.data, data->data, data->data);
70190 if(mbedErr)
70191 retval = UA_STATUSCODE_BADINTERNALERROR;
70192 UA_ByteString_clear(&ivCopy);
70193 return retval;
70194}
70195
70196static UA_StatusCode
70197sym_generateKey_sp_aes128sha256rsaoaep(void *policyContext, const UA_ByteString *secret,
70198 const UA_ByteString *seed, UA_ByteString *out) {
70199 if(secret == NULL || seed == NULL || out == NULL)
70200 return UA_STATUSCODE_BADINTERNALERROR;
70201 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
70202 return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out);
70203}
70204
70205static UA_StatusCode
70206sym_generateNonce_sp_aes128sha256rsaoaep(void *policyContext, UA_ByteString *out) {
70207 if(out == NULL)
70208 return UA_STATUSCODE_BADINTERNALERROR;
70209 Aes128Sha256PsaOaep_PolicyContext *pc =
70210 (Aes128Sha256PsaOaep_PolicyContext *)policyContext;
70211 int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length);
70212 if(mbedErr)
70213 return UA_STATUSCODE_BADUNEXPECTEDERROR;
70214 return UA_STATUSCODE_GOOD;
70215}
70216
70217/*****************/
70218/* ChannelModule */
70219/*****************/
70220
70221/* Assumes that the certificate has been verified externally */
70222static UA_StatusCode
70223parseRemoteCertificate_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70224 const UA_ByteString *remoteCertificate) {
70225 if(remoteCertificate == NULL || cc == NULL)
70226 return UA_STATUSCODE_BADINTERNALERROR;
70227
70228 /* Parse the certificate */
70229 int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data,
70230 remoteCertificate->length);
70231 if(mbedErr)
70232 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70233
70234 /* Check the key length */
70235#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
70236 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk);
70237 if(rsaContext->len < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
70238 rsaContext->len > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
70239#else
70240 size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk));
70241 if(keylen < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH ||
70242 keylen > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH)
70243#endif
70244 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
70245
70246 return UA_STATUSCODE_GOOD;
70247}
70248
70249static void
70250channelContext_deleteContext_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc) {
70251 UA_ByteString_clear(&cc->localSymSigningKey);
70252 UA_ByteString_clear(&cc->localSymEncryptingKey);
70253 UA_ByteString_clear(&cc->localSymIv);
70254
70255 UA_ByteString_clear(&cc->remoteSymSigningKey);
70256 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
70257 UA_ByteString_clear(&cc->remoteSymIv);
70258
70259 mbedtls_x509_crt_free(&cc->remoteCertificate);
70260
70261 UA_free(cc);
70262}
70263
70264static UA_StatusCode
70265channelContext_newContext_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy,
70266 const UA_ByteString *remoteCertificate,
70267 void **pp_contextData) {
70268 if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL)
70269 return UA_STATUSCODE_BADINTERNALERROR;
70270
70271 /* Allocate the channel context */
70272 *pp_contextData = UA_malloc(sizeof(Aes128Sha256PsaOaep_ChannelContext));
70273 if(*pp_contextData == NULL)
70274 return UA_STATUSCODE_BADOUTOFMEMORY;
70275
70276 Aes128Sha256PsaOaep_ChannelContext *cc = (Aes128Sha256PsaOaep_ChannelContext *)*pp_contextData;
70277
70278 /* Initialize the channel context */
70279 cc->policyContext = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext;
70280
70281 UA_ByteString_init(&cc->localSymSigningKey);
70282 UA_ByteString_init(&cc->localSymEncryptingKey);
70283 UA_ByteString_init(&cc->localSymIv);
70284
70285 UA_ByteString_init(&cc->remoteSymSigningKey);
70286 UA_ByteString_init(&cc->remoteSymEncryptingKey);
70287 UA_ByteString_init(&cc->remoteSymIv);
70288
70289 mbedtls_x509_crt_init(&cc->remoteCertificate);
70290
70291 // TODO: this can be optimized so that we dont allocate memory before parsing the certificate
70292 UA_StatusCode retval = parseRemoteCertificate_sp_aes128sha256rsaoaep(cc, remoteCertificate);
70293 if(retval != UA_STATUSCODE_GOOD) {
70294 channelContext_deleteContext_sp_aes128sha256rsaoaep(cc);
70295 *pp_contextData = NULL;
70296 }
70297 return retval;
70298}
70299
70300static UA_StatusCode
70301channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70302 const UA_ByteString *key) {
70303 if(key == NULL || cc == NULL)
70304 return UA_STATUSCODE_BADINTERNALERROR;
70305
70306 UA_ByteString_clear(&cc->localSymEncryptingKey);
70307 return UA_ByteString_copy(key, &cc->localSymEncryptingKey);
70308}
70309
70310static UA_StatusCode
70311channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70312 const UA_ByteString *key) {
70313 if(key == NULL || cc == NULL)
70314 return UA_STATUSCODE_BADINTERNALERROR;
70315
70316 UA_ByteString_clear(&cc->localSymSigningKey);
70317 return UA_ByteString_copy(key, &cc->localSymSigningKey);
70318}
70319
70320
70321static UA_StatusCode
70322channelContext_setLocalSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70323 const UA_ByteString *iv) {
70324 if(iv == NULL || cc == NULL)
70325 return UA_STATUSCODE_BADINTERNALERROR;
70326
70327 UA_ByteString_clear(&cc->localSymIv);
70328 return UA_ByteString_copy(iv, &cc->localSymIv);
70329}
70330
70331static UA_StatusCode
70332channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70333 const UA_ByteString *key) {
70334 if(key == NULL || cc == NULL)
70335 return UA_STATUSCODE_BADINTERNALERROR;
70336
70337 UA_ByteString_clear(&cc->remoteSymEncryptingKey);
70338 return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey);
70339}
70340
70341static UA_StatusCode
70342channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70343 const UA_ByteString *key) {
70344 if(key == NULL || cc == NULL)
70345 return UA_STATUSCODE_BADINTERNALERROR;
70346
70347 UA_ByteString_clear(&cc->remoteSymSigningKey);
70348 return UA_ByteString_copy(key, &cc->remoteSymSigningKey);
70349}
70350
70351static UA_StatusCode
70352channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc,
70353 const UA_ByteString *iv) {
70354 if(iv == NULL || cc == NULL)
70355 return UA_STATUSCODE_BADINTERNALERROR;
70356
70357 UA_ByteString_clear(&cc->remoteSymIv);
70358 return UA_ByteString_copy(iv, &cc->remoteSymIv);
70359}
70360
70361static UA_StatusCode
70362channelContext_compareCertificate_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc,
70363 const UA_ByteString *certificate) {
70364 if(cc == NULL || certificate == NULL)
70365 return UA_STATUSCODE_BADINTERNALERROR;
70366
70367 mbedtls_x509_crt cert;
70368 mbedtls_x509_crt_init(&cert);
70369 int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length);
70370 if(mbedErr)
70371 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70372
70373 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70374 if(cert.raw.len != cc->remoteCertificate.raw.len ||
70375 memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0)
70376 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70377
70378 mbedtls_x509_crt_free(&cert);
70379 return retval;
70380}
70381
70382static void
70383clear_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy) {
70384 if(securityPolicy == NULL)
70385 return;
70386
70387 UA_ByteString_clear(&securityPolicy->localCertificate);
70388
70389 if(securityPolicy->policyContext == NULL)
70390 return;
70391
70392 /* delete all allocated members in the context */
70393 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
70394 securityPolicy->policyContext;
70395
70396 mbedtls_ctr_drbg_free(&pc->drbgContext);
70397 mbedtls_entropy_free(&pc->entropyContext);
70398 mbedtls_pk_free(&pc->localPrivateKey);
70399 mbedtls_md_free(&pc->sha256MdContext);
70400 UA_ByteString_clear(&pc->localCertThumbprint);
70401
70402 UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70403 "Deleted members of EndpointContext for sp_aes128sha256rsaoaep");
70404
70405 UA_free(pc);
70406 securityPolicy->policyContext = NULL;
70407}
70408
70409static UA_StatusCode
70410updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
70411 const UA_ByteString newCertificate,
70412 const UA_ByteString newPrivateKey) {
70413 if(securityPolicy == NULL)
70414 return UA_STATUSCODE_BADINTERNALERROR;
70415
70416 if(securityPolicy->policyContext == NULL)
70417 return UA_STATUSCODE_BADINTERNALERROR;
70418
70419 Aes128Sha256PsaOaep_PolicyContext *pc =
70420 (Aes128Sha256PsaOaep_PolicyContext *) securityPolicy->policyContext;
70421
70422 UA_ByteString_clear(&securityPolicy->localCertificate);
70423
70424 UA_StatusCode retval = UA_ByteString_allocBuffer(&securityPolicy->localCertificate,
70425 newCertificate.length + 1);
70426 if(retval != UA_STATUSCODE_GOOD)
70427 return retval;
70428 memcpy(securityPolicy->localCertificate.data, newCertificate.data, newCertificate.length);
70429 securityPolicy->localCertificate.data[newCertificate.length] = '\0';
70430 securityPolicy->localCertificate.length--;
70431
70432 /* Set the new private key */
70433 mbedtls_pk_free(&pc->localPrivateKey);
70434 mbedtls_pk_init(&pc->localPrivateKey);
70435#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
70436 int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
70437 newPrivateKey.length, NULL, 0);
70438#else
70439 int mbedErr = mbedtls_pk_parse_key(&pc->localPrivateKey, newPrivateKey.data,
70440 newPrivateKey.length, NULL, 0, mbedtls_entropy_func, &pc->drbgContext);
70441#endif
70442 if(mbedErr) {
70443 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70444 goto error;
70445 }
70446
70447 retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
70448 &securityPolicy->localCertificate,
70449 &pc->localCertThumbprint);
70450 if(retval != UA_STATUSCODE_GOOD)
70451 goto error;
70452
70453 return retval;
70454
70455 error:
70456 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70457 "Could not update certificate and private key");
70458 if(securityPolicy->policyContext != NULL)
70459 clear_sp_aes128sha256rsaoaep(securityPolicy);
70460 return retval;
70461}
70462
70463static UA_StatusCode
70464policyContext_newContext_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy,
70465 const UA_ByteString localPrivateKey) {
70466 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70467 if(securityPolicy == NULL)
70468 return UA_STATUSCODE_BADINTERNALERROR;
70469
70470 if (localPrivateKey.length == 0) {
70471 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70472 "Can not initialize security policy. Private key is empty.");
70473 return UA_STATUSCODE_BADINVALIDARGUMENT;
70474 }
70475
70476 Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)
70477 UA_malloc(sizeof(Aes128Sha256PsaOaep_PolicyContext));
70478 securityPolicy->policyContext = (void *)pc;
70479 if(!pc) {
70480 retval = UA_STATUSCODE_BADOUTOFMEMORY;
70481 goto error;
70482 }
70483
70484 /* Initialize the PolicyContext */
70485 memset(pc, 0, sizeof(Aes128Sha256PsaOaep_PolicyContext));
70486 mbedtls_ctr_drbg_init(&pc->drbgContext);
70487 mbedtls_entropy_init(&pc->entropyContext);
70488 mbedtls_pk_init(&pc->localPrivateKey);
70489 mbedtls_md_init(&pc->sha256MdContext);
70490
70491 /* Initialized the message digest */
70492 const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
70493 int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256);
70494 if(mbedErr) {
70495 retval = UA_STATUSCODE_BADOUTOFMEMORY;
70496 goto error;
70497 }
70498
70499 mbedErr = mbedtls_entropy_self_test(0);
70500
70501 if(mbedErr) {
70502 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70503 goto error;
70504 }
70505
70506 /* Seed the RNG */
70507 char *personalization = "open62541-drbg";
70508 mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func,
70509 &pc->entropyContext,
70510 (const unsigned char *)personalization, 14);
70511 if(mbedErr) {
70512 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70513 goto error;
70514 }
70515
70516 /* Set the private key */
70517 mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext);
70518 if(mbedErr) {
70519 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70520 goto error;
70521 }
70522
70523 /* Set the local certificate thumbprint */
70524 retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH);
70525 if(retval != UA_STATUSCODE_GOOD)
70526 goto error;
70527 retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy,
70528 &securityPolicy->localCertificate,
70529 &pc->localCertThumbprint);
70530 if(retval != UA_STATUSCODE_GOOD)
70531 goto error;
70532
70533 return UA_STATUSCODE_GOOD;
70534
70535error:
70536 UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY,
70537 "Could not create securityContext: %s", UA_StatusCode_name(retval));
70538 if(securityPolicy->policyContext != NULL)
70539 clear_sp_aes128sha256rsaoaep(securityPolicy);
70540 return retval;
70541}
70542
70543UA_StatusCode
70544UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
70545 const UA_ByteString localPrivateKey, const UA_Logger *logger) {
70546 memset(policy, 0, sizeof(UA_SecurityPolicy));
70547 policy->logger = logger;
70548
70549 policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep");
70550
70551 UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule;
70552 UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule;
70553 UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule;
70554
70555 UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
70556
70557 if (retval != UA_STATUSCODE_GOOD)
70558 return retval;
70559
70560 /* AsymmetricModule */
70561 UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm =
70562 &asymmetricModule->cryptoModule.signatureAlgorithm;
70563 asym_signatureAlgorithm->uri =
70564 UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0");
70565 asym_signatureAlgorithm->verify =
70566 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_aes128sha256rsaoaep;
70567 asym_signatureAlgorithm->sign =
70568 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_aes128sha256rsaoaep;
70569 asym_signatureAlgorithm->getLocalSignatureSize =
70570 (size_t (*)(const void *))asym_getLocalSignatureSize_sp_aes128sha256rsaoaep;
70571 asym_signatureAlgorithm->getRemoteSignatureSize =
70572 (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep;
70573 asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function
70574 asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function
70575
70576 UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm =
70577 &asymmetricModule->cryptoModule.encryptionAlgorithm;
70578 asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0");
70579 asym_encryptionAlgorithm->encrypt =
70580 (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_aes128sha256rsaoaep;
70581 asym_encryptionAlgorithm->decrypt =
70582 (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_aes128sha256rsaoaep;
70583 asym_encryptionAlgorithm->getLocalKeyLength =
70584 (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep;
70585 asym_encryptionAlgorithm->getRemoteKeyLength =
70586 (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep;
70587 asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const void *))asym_getRemoteBlockSize_sp_aes128sha256rsaoaep;
70588 asym_encryptionAlgorithm->getRemotePlainTextBlockSize =
70589 (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep;
70590
70591 asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_aes128sha256rsaoaep;
70592 asymmetricModule->compareCertificateThumbprint =
70593 asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep;
70594
70595 /* SymmetricModule */
70596 symmetricModule->generateKey = sym_generateKey_sp_aes128sha256rsaoaep;
70597 symmetricModule->generateNonce = sym_generateNonce_sp_aes128sha256rsaoaep;
70598
70599 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
70600 &symmetricModule->cryptoModule.signatureAlgorithm;
70601 sym_signatureAlgorithm->uri =
70602 UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0");
70603 sym_signatureAlgorithm->verify =
70604 (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_aes128sha256rsaoaep;
70605 sym_signatureAlgorithm->sign =
70606 (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_aes128sha256rsaoaep;
70607 sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
70608 sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep;
70609 sym_signatureAlgorithm->getLocalKeyLength =
70610 (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
70611 sym_signatureAlgorithm->getRemoteKeyLength =
70612 (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep;
70613
70614 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
70615 &symmetricModule->cryptoModule.encryptionAlgorithm;
70616 sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
70617 sym_encryptionAlgorithm->encrypt =
70618 (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_aes128sha256rsaoaep;
70619 sym_encryptionAlgorithm->decrypt =
70620 (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_aes128sha256rsaoaep;
70621 sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
70622 sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep;
70623 sym_encryptionAlgorithm->getRemoteBlockSize =
70624 (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep;
70625 sym_encryptionAlgorithm->getRemotePlainTextBlockSize =
70626 (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep;
70627 symmetricModule->secureChannelNonceLength = 32;
70628
70629 // Use the same signature algorithm as the asymmetric component for certificate signing (see standard)
70630 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
70631
70632 /* ChannelModule */
70633 channelModule->newContext = channelContext_newContext_sp_aes128sha256rsaoaep;
70634 channelModule->deleteContext = (void (*)(void *))
70635 channelContext_deleteContext_sp_aes128sha256rsaoaep;
70636
70637 channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70638 channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep;
70639 channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70640 channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep;
70641 channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
70642 channelContext_setLocalSymIv_sp_aes128sha256rsaoaep;
70643
70644 channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70645 channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep;
70646 channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *))
70647 channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep;
70648 channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *))
70649 channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep;
70650
70651 channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *))
70652 channelContext_compareCertificate_sp_aes128sha256rsaoaep;
70653
70654 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep;
70655 policy->clear = clear_sp_aes128sha256rsaoaep;
70656
70657 UA_StatusCode res = policyContext_newContext_sp_aes128sha256rsaoaep(policy, localPrivateKey);
70658 if(res != UA_STATUSCODE_GOOD)
70659 clear_sp_aes128sha256rsaoaep(policy);
70660
70661 return res;
70662}
70663
70664#endif
70665
70666/**** amalgamated original file "/plugins/crypto/mbedtls/ua_pki_mbedtls.c" ****/
70667
70668/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
70669 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
70670 *
70671 * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB
70672 * Copyright 2019 (c) Kalycito Infotech Private Limited
70673 * Copyright 2019 (c) Julius Pfrommer, Fraunhofer IOSB
70674 */
70675
70676
70677#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
70678
70679#include <mbedtls/x509.h>
70680#include <mbedtls/x509_crt.h>
70681#include <mbedtls/error.h>
70682#include <mbedtls/version.h>
70683
70684#define REMOTECERTIFICATETRUSTED 1
70685#define ISSUERKNOWN 2
70686#define DUALPARENT 3
70687#define PARENTFOUND 4
70688
70689/* Find binary substring. Taken and adjusted from
70690 * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */
70691
70692static const unsigned char *
70693bstrchr(const unsigned char *s, const unsigned char ch, size_t l) {
70694 /* find first occurrence of c in char s[] for length l*/
70695 for(; l > 0; ++s, --l) {
70696 if(*s == ch)
70697 return s;
70698 }
70699 return NULL;
70700}
70701
70702static const unsigned char *
70703UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) {
70704 /* find first occurrence of s2[] in s1[] for length l1*/
70705 const unsigned char *ss1 = s1;
70706 const unsigned char *ss2 = s2;
70707 /* handle special case */
70708 if(l1 == 0)
70709 return (NULL);
70710 if(l2 == 0)
70711 return s1;
70712
70713 /* match prefix */
70714 for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL &&
70715 (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) {
70716
70717 /* match rest of prefix */
70718 const unsigned char *sc1, *sc2;
70719 for (sc1 = s1, sc2 = s2; ;)
70720 if (++sc2 >= ss2+l2)
70721 return s1;
70722 else if (*++sc1 != *sc2)
70723 break;
70724 }
70725 return NULL;
70726}
70727
70728// mbedTLS expects PEM data to be null terminated
70729// The data length parameter must include the null terminator
70730static UA_ByteString copyDataFormatAware(const UA_ByteString *data)
70731{
70732 UA_ByteString result;
70733 UA_ByteString_init(&result);
70734
70735 if (!data->length)
70736 return result;
70737
70738 if (data->length && data->data[0] == '-') {
70739 UA_ByteString_allocBuffer(&result, data->length + 1);
70740 memcpy(result.data, data->data, data->length);
70741 result.data[data->length] = '\0';
70742 } else {
70743 UA_ByteString_copy(data, &result);
70744 }
70745
70746 return result;
70747}
70748
70749typedef struct {
70750 /* If the folders are defined, we use them to reload the certificates during
70751 * runtime */
70752 UA_String trustListFolder;
70753 UA_String issuerListFolder;
70754 UA_String revocationListFolder;
70755
70756 mbedtls_x509_crt certificateTrustList;
70757 mbedtls_x509_crt certificateIssuerList;
70758 mbedtls_x509_crl certificateRevocationList;
70759} CertInfo;
70760
70761#ifdef __linux__ /* Linux only so far */
70762
70763#include <dirent.h>
70764#include <limits.h>
70765
70766static UA_StatusCode
70767fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **paths) {
70768 char buf[PATH_MAX + 1];
70769 if(folder->length > PATH_MAX)
70770 return UA_STATUSCODE_BADINTERNALERROR;
70771
70772 memcpy(buf, folder->data, folder->length);
70773 buf[folder->length] = 0;
70774
70775 DIR *dir = opendir(buf);
70776 if(!dir)
70777 return UA_STATUSCODE_BADINTERNALERROR;
70778
70779 *paths = (UA_String*)UA_Array_new(256, &UA_TYPES[UA_TYPES_STRING]);
70780 if(*paths == NULL) {
70781 closedir(dir);
70782 return UA_STATUSCODE_BADOUTOFMEMORY;
70783 }
70784
70785 struct dirent *ent;
70786 char buf2[PATH_MAX + 1];
70787 char *res = realpath(buf, buf2);
70788 if(!res) {
70789 closedir(dir);
70790 return UA_STATUSCODE_BADINTERNALERROR;
70791 }
70792 size_t pathlen = strlen(buf2);
70793 *pathsSize = 0;
70794 while((ent = readdir (dir)) != NULL && *pathsSize < 256) {
70795 if(ent->d_type != DT_REG)
70796 continue;
70797 buf2[pathlen] = '/';
70798 buf2[pathlen+1] = 0;
70799 strcat(buf2, ent->d_name);
70800 (*paths)[*pathsSize] = UA_STRING_ALLOC(buf2);
70801 *pathsSize += 1;
70802 }
70803 closedir(dir);
70804
70805 if(*pathsSize == 0) {
70806 UA_free(*paths);
70807 *paths = NULL;
70808 }
70809 return UA_STATUSCODE_GOOD;
70810}
70811
70812static UA_StatusCode
70813reloadCertificates(CertInfo *ci) {
70814 UA_StatusCode retval = UA_STATUSCODE_GOOD;
70815 int err = 0;
70816 int internalErrorFlag = 0;
70817
70818 /* Load the trustlists */
70819 if(ci->trustListFolder.length > 0) {
70820 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the trust-list");
70821 mbedtls_x509_crt_free(&ci->certificateTrustList);
70822 mbedtls_x509_crt_init(&ci->certificateTrustList);
70823
70824 char f[PATH_MAX];
70825 memcpy(f, ci->trustListFolder.data, ci->trustListFolder.length);
70826 f[ci->trustListFolder.length] = 0;
70827 err = mbedtls_x509_crt_parse_path(&ci->certificateTrustList, f);
70828 if(err == 0) {
70829 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70830 "Loaded certificate from %s", f);
70831 } else {
70832 char errBuff[300];
70833 mbedtls_strerror(err, errBuff, 300);
70834 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70835 "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)", f, errBuff, err);
70836 internalErrorFlag = 1;
70837 }
70838 }
70839
70840 /* Load the revocationlists */
70841 if(ci->revocationListFolder.length > 0) {
70842 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list");
70843 size_t pathsSize = 0;
70844 UA_String *paths = NULL;
70845 retval = fileNamesFromFolder(&ci->revocationListFolder, &pathsSize, &paths);
70846 if(retval != UA_STATUSCODE_GOOD)
70847 return retval;
70848 mbedtls_x509_crl_free(&ci->certificateRevocationList);
70849 mbedtls_x509_crl_init(&ci->certificateRevocationList);
70850 for(size_t i = 0; i < pathsSize; i++) {
70851 char f[PATH_MAX];
70852 memcpy(f, paths[i].data, paths[i].length);
70853 f[paths[i].length] = 0;
70854 err = mbedtls_x509_crl_parse_file(&ci->certificateRevocationList, f);
70855 if(err == 0) {
70856 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70857 "Loaded certificate from %.*s",
70858 (int)paths[i].length, paths[i].data);
70859 } else {
70860 char errBuff[300];
70861 mbedtls_strerror(err, errBuff, 300);
70862 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70863 "Failed to load certificate from %.*s, mbedTLS error: %s (error code: %d)",
70864 (int)paths[i].length, paths[i].data, errBuff, err);
70865 internalErrorFlag = 1;
70866 }
70867 }
70868 UA_Array_delete(paths, pathsSize, &UA_TYPES[UA_TYPES_STRING]);
70869 paths = NULL;
70870 pathsSize = 0;
70871 }
70872
70873 /* Load the issuerlists */
70874 if(ci->issuerListFolder.length > 0) {
70875 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list");
70876 mbedtls_x509_crt_free(&ci->certificateIssuerList);
70877 mbedtls_x509_crt_init(&ci->certificateIssuerList);
70878 char f[PATH_MAX];
70879 memcpy(f, ci->issuerListFolder.data, ci->issuerListFolder.length);
70880 f[ci->issuerListFolder.length] = 0;
70881 err = mbedtls_x509_crt_parse_path(&ci->certificateIssuerList, f);
70882 if(err == 0) {
70883 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70884 "Loaded certificate from %s", f);
70885 } else {
70886 char errBuff[300];
70887 mbedtls_strerror(err, errBuff, 300);
70888 UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70889 "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)",
70890 f, errBuff, err);
70891 internalErrorFlag = 1;
70892 }
70893 }
70894
70895 if(internalErrorFlag) {
70896 retval = UA_STATUSCODE_BADINTERNALERROR;
70897 }
70898 return retval;
70899}
70900
70901#endif
70902
70903static UA_StatusCode
70904certificateVerification_verify(void *verificationContext,
70905 const UA_ByteString *certificate) {
70906 CertInfo *ci = (CertInfo*)verificationContext;
70907 if(!ci)
70908 return UA_STATUSCODE_BADINTERNALERROR;
70909
70910#ifdef __linux__ /* Reload certificates if folder paths are specified */
70911 UA_StatusCode certFlag = reloadCertificates(ci);
70912 if(certFlag != UA_STATUSCODE_GOOD) {
70913 return certFlag;
70914 }
70915#endif
70916
70917 if(ci->trustListFolder.length == 0 &&
70918 ci->issuerListFolder.length == 0 &&
70919 ci->revocationListFolder.length == 0 &&
70920 ci->certificateTrustList.raw.len == 0 &&
70921 ci->certificateIssuerList.raw.len == 0 &&
70922 ci->certificateRevocationList.raw.len == 0) {
70923 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
70924 "PKI plugin unconfigured. Accepting the certificate.");
70925 return UA_STATUSCODE_GOOD;
70926 }
70927
70928 /* Parse the certificate */
70929 mbedtls_x509_crt remoteCertificate;
70930
70931 /* Temporary Object to parse the trustList */
70932 mbedtls_x509_crt *tempCert = NULL;
70933
70934 /* Temporary Object to parse the revocationList */
70935 mbedtls_x509_crl *tempCrl = NULL;
70936
70937 /* Temporary Object to identify the parent CA when there is no intermediate CA */
70938 mbedtls_x509_crt *parentCert = NULL;
70939
70940 /* Temporary Object to identify the parent CA when there is intermediate CA */
70941 mbedtls_x509_crt *parentCert_2 = NULL;
70942
70943 /* Flag value to identify if the issuer certificate is found */
70944 int issuerKnown = 0;
70945
70946 /* Flag value to identify if the parent certificate found */
70947 int parentFound = 0;
70948
70949 mbedtls_x509_crt_init(&remoteCertificate);
70950 int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
70951 certificate->length);
70952 if(mbedErr) {
70953 /* char errBuff[300]; */
70954 /* mbedtls_strerror(mbedErr, errBuff, 300); */
70955 /* UA_LOG_WARNING(data->policyContext->securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, */
70956 /* "Could not parse the remote certificate with error: %s", errBuff); */
70957 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
70958 }
70959
70960 /* Verify */
70961 mbedtls_x509_crt_profile crtProfile = {
70962 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
70963 0xFFFFFF, 0x000000, 128 * 8 // in bits
70964 }; // TODO: remove magic numbers
70965
70966 uint32_t flags = 0;
70967 mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
70968 &ci->certificateTrustList,
70969 &ci->certificateRevocationList,
70970 &crtProfile, NULL, &flags, NULL, NULL);
70971
70972 /* Flag to check if the remote certificate is trusted or not */
70973 int TRUSTED = 0;
70974
70975 /* Check if the remoteCertificate is present in the trustList while mbedErr value is not zero */
70976 if(mbedErr && !(flags & MBEDTLS_X509_BADCERT_EXPIRED) && !(flags & MBEDTLS_X509_BADCERT_FUTURE)) {
70977 for(tempCert = &ci->certificateTrustList; tempCert != NULL; tempCert = tempCert->next) {
70978 if(remoteCertificate.raw.len == tempCert->raw.len &&
70979 memcmp(remoteCertificate.raw.p, tempCert->raw.p, remoteCertificate.raw.len) == 0) {
70980 TRUSTED = REMOTECERTIFICATETRUSTED;
70981 break;
70982 }
70983 }
70984 }
70985
70986 /* If the remote certificate is present in the trustList then check if the issuer certificate
70987 * of remoteCertificate is present in issuerList */
70988 if(TRUSTED && mbedErr) {
70989 mbedErr = mbedtls_x509_crt_verify_with_profile(&remoteCertificate,
70990 &ci->certificateIssuerList,
70991 &ci->certificateRevocationList,
70992 &crtProfile, NULL, &flags, NULL, NULL);
70993
70994 /* Check if the parent certificate has a CRL file available */
70995 if(!mbedErr) {
70996 /* Flag value to identify if that there is an intermediate CA present */
70997 int dualParent = 0;
70998
70999 /* Identify the topmost parent certificate for the remoteCertificate */
71000 for(parentCert = &ci->certificateIssuerList; parentCert != NULL; parentCert = parentCert->next ) {
71001 if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
71002 for(parentCert_2 = &ci->certificateTrustList; parentCert_2 != NULL; parentCert_2 = parentCert_2->next) {
71003 if(memcmp(parentCert->issuer_raw.p, parentCert_2->subject_raw.p, parentCert_2->subject_raw.len) == 0) {
71004 dualParent = DUALPARENT;
71005 break;
71006 }
71007 }
71008 parentFound = PARENTFOUND;
71009 }
71010
71011 if(parentFound == PARENTFOUND)
71012 break;
71013 }
71014
71015 /* Check if there is an intermediate certificate between the topmost parent
71016 * certificate and child certificate
71017 * If yes the topmost parent certificate is to be checked whether it has a
71018 * CRL file avaiable */
71019 if(dualParent == DUALPARENT && parentFound == PARENTFOUND) {
71020 parentCert = parentCert_2;
71021 }
71022
71023 /* If a parent certificate is found traverse the revocationList and identify
71024 * if there is any CRL file that corresponds to the parentCertificate */
71025 if(parentFound == PARENTFOUND) {
71026 tempCrl = &ci->certificateRevocationList;
71027 while(tempCrl != NULL) {
71028 if(tempCrl->version != 0 &&
71029 tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
71030 memcmp(tempCrl->issuer_raw.p,
71031 parentCert->subject_raw.p,
71032 tempCrl->issuer_raw.len) == 0) {
71033 issuerKnown = ISSUERKNOWN;
71034 break;
71035 }
71036
71037 tempCrl = tempCrl->next;
71038 }
71039
71040 /* If the CRL file corresponding to the parent certificate is not present
71041 * then return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN */
71042 if(!issuerKnown) {
71043 return UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN;
71044 }
71045
71046 }
71047
71048 }
71049
71050 }
71051 else if(!mbedErr && !TRUSTED) {
71052 /* This else if section is to identify if the parent certificate which is present in trustList
71053 * has CRL file corresponding to it */
71054
71055 /* Identify the parent certificate of the remoteCertificate */
71056 for(parentCert = &ci->certificateTrustList; parentCert != NULL; parentCert = parentCert->next) {
71057 if(memcmp(remoteCertificate.issuer_raw.p, parentCert->subject_raw.p, parentCert->subject_raw.len) == 0) {
71058 parentFound = PARENTFOUND;
71059 break;
71060 }
71061
71062 }
71063
71064 /* If the parent certificate is found traverse the revocationList and identify
71065 * if there is any CRL file that corresponds to the parentCertificate */
71066 if(parentFound == PARENTFOUND &&
71067 memcmp(remoteCertificate.issuer_raw.p, remoteCertificate.subject_raw.p, remoteCertificate.subject_raw.len) != 0) {
71068 tempCrl = &ci->certificateRevocationList;
71069 while(tempCrl != NULL) {
71070 if(tempCrl->version != 0 &&
71071 tempCrl->issuer_raw.len == parentCert->subject_raw.len &&
71072 memcmp(tempCrl->issuer_raw.p,
71073 parentCert->subject_raw.p,
71074 tempCrl->issuer_raw.len) == 0) {
71075 issuerKnown = ISSUERKNOWN;
71076 break;
71077 }
71078
71079 tempCrl = tempCrl->next;
71080 }
71081
71082 /* If the CRL file corresponding to the parent certificate is not present
71083 * then return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN */
71084 if(!issuerKnown) {
71085 return UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN;
71086 }
71087
71088 }
71089
71090 }
71091
71092 // TODO: Extend verification
71093
71094 /* This condition will check whether the certificate is a User certificate
71095 * or a CA certificate. If the MBEDTLS_X509_KU_KEY_CERT_SIGN and
71096 * MBEDTLS_X509_KU_CRL_SIGN of key_usage are set, then the certificate
71097 * shall be condidered as CA Certificate and cannot be used to establish a
71098 * connection. Refer the test case CTT/Security/Security Certificate Validation/029.js
71099 * for more details */
71100#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71101 if((remoteCertificate.key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
71102 (remoteCertificate.key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
71103 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
71104 }
71105#else
71106 if((remoteCertificate.private_key_usage & MBEDTLS_X509_KU_KEY_CERT_SIGN) &&
71107 (remoteCertificate.private_key_usage & MBEDTLS_X509_KU_CRL_SIGN)) {
71108 return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED;
71109 }
71110#endif
71111
71112
71113 UA_StatusCode retval = UA_STATUSCODE_GOOD;
71114 if(mbedErr) {
71115#if UA_LOGLEVEL <= 400
71116 char buff[100];
71117 int len = mbedtls_x509_crt_verify_info(buff, 100, "", flags);
71118 UA_LOG_WARNING(UA_Log_Stdout, UA_LOGCATEGORY_SECURITYPOLICY,
71119 "Verifying the certificate failed with error: %.*s", len-1, buff);
71120#endif
71121 if(flags & (uint32_t)MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
71122 retval = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED;
71123 } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_FUTURE ||
71124 flags & (uint32_t)MBEDTLS_X509_BADCERT_EXPIRED) {
71125 retval = UA_STATUSCODE_BADCERTIFICATETIMEINVALID;
71126 } else if(flags & (uint32_t)MBEDTLS_X509_BADCERT_REVOKED ||
71127 flags & (uint32_t)MBEDTLS_X509_BADCRL_EXPIRED) {
71128 retval = UA_STATUSCODE_BADCERTIFICATEREVOKED;
71129 } else {
71130 retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71131 }
71132 }
71133
71134 mbedtls_x509_crt_free(&remoteCertificate);
71135 return retval;
71136}
71137
71138static UA_StatusCode
71139certificateVerification_verifyApplicationURI(void *verificationContext,
71140 const UA_ByteString *certificate,
71141 const UA_String *applicationURI) {
71142 CertInfo *ci = (CertInfo*)verificationContext;
71143 if(!ci)
71144 return UA_STATUSCODE_BADINTERNALERROR;
71145
71146 /* Parse the certificate */
71147 mbedtls_x509_crt remoteCertificate;
71148 mbedtls_x509_crt_init(&remoteCertificate);
71149 int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data,
71150 certificate->length);
71151 if(mbedErr)
71152 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71153
71154 /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields
71155 * of the Alternative Subject Name. Instead test whether the URI-string is
71156 * present in the v3_ext field in general.
71157 *
71158 * TODO: Improve parsing of the Alternative Subject Name */
71159 UA_StatusCode retval = UA_STATUSCODE_GOOD;
71160 if(UA_Bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len,
71161 applicationURI->data, applicationURI->length) == NULL)
71162 retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID;
71163
71164 mbedtls_x509_crt_free(&remoteCertificate);
71165 return retval;
71166}
71167
71168static void
71169certificateVerification_clear(UA_CertificateVerification *cv) {
71170 CertInfo *ci = (CertInfo*)cv->context;
71171 if(!ci)
71172 return;
71173 mbedtls_x509_crt_free(&ci->certificateTrustList);
71174 mbedtls_x509_crl_free(&ci->certificateRevocationList);
71175 mbedtls_x509_crt_free(&ci->certificateIssuerList);
71176 UA_String_clear(&ci->trustListFolder);
71177 UA_String_clear(&ci->issuerListFolder);
71178 UA_String_clear(&ci->revocationListFolder);
71179 UA_free(ci);
71180 cv->context = NULL;
71181}
71182
71183UA_StatusCode
71184UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv,
71185 const UA_ByteString *certificateTrustList,
71186 size_t certificateTrustListSize,
71187 const UA_ByteString *certificateIssuerList,
71188 size_t certificateIssuerListSize,
71189 const UA_ByteString *certificateRevocationList,
71190 size_t certificateRevocationListSize) {
71191 CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
71192 if(!ci)
71193 return UA_STATUSCODE_BADOUTOFMEMORY;
71194 memset(ci, 0, sizeof(CertInfo));
71195 mbedtls_x509_crt_init(&ci->certificateTrustList);
71196 mbedtls_x509_crl_init(&ci->certificateRevocationList);
71197 mbedtls_x509_crt_init(&ci->certificateIssuerList);
71198
71199 cv->context = (void*)ci;
71200 cv->verifyCertificate = certificateVerification_verify;
71201 cv->clear = certificateVerification_clear;
71202 cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
71203
71204 int err;
71205 UA_ByteString data;
71206 UA_ByteString_init(&data);
71207
71208 for(size_t i = 0; i < certificateTrustListSize; i++) {
71209 data = copyDataFormatAware(&certificateTrustList[i]);
71210 err = mbedtls_x509_crt_parse(&ci->certificateTrustList,
71211 data.data,
71212 data.length);
71213 UA_ByteString_clear(&data);
71214 if(err)
71215 goto error;
71216 }
71217 for(size_t i = 0; i < certificateIssuerListSize; i++) {
71218 data = copyDataFormatAware(&certificateIssuerList[i]);
71219 err = mbedtls_x509_crt_parse(&ci->certificateIssuerList,
71220 data.data,
71221 data.length);
71222 UA_ByteString_clear(&data);
71223 if(err)
71224 goto error;
71225 }
71226 for(size_t i = 0; i < certificateRevocationListSize; i++) {
71227 data = copyDataFormatAware(&certificateRevocationList[i]);
71228 err = mbedtls_x509_crl_parse(&ci->certificateRevocationList,
71229 data.data,
71230 data.length);
71231 UA_ByteString_clear(&data);
71232 if(err)
71233 goto error;
71234 }
71235
71236 return UA_STATUSCODE_GOOD;
71237error:
71238 certificateVerification_clear(cv);
71239 return UA_STATUSCODE_BADINTERNALERROR;
71240}
71241
71242#ifdef __linux__ /* Linux only so far */
71243
71244UA_StatusCode
71245UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv,
71246 const char *trustListFolder,
71247 const char *issuerListFolder,
71248 const char *revocationListFolder) {
71249 CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo));
71250 if(!ci)
71251 return UA_STATUSCODE_BADOUTOFMEMORY;
71252 memset(ci, 0, sizeof(CertInfo));
71253 mbedtls_x509_crt_init(&ci->certificateTrustList);
71254 mbedtls_x509_crl_init(&ci->certificateRevocationList);
71255 mbedtls_x509_crt_init(&ci->certificateIssuerList);
71256
71257 /* Only set the folder paths. They will be reloaded during runtime.
71258 * TODO: Add a more efficient reloading of only the changes */
71259 ci->trustListFolder = UA_STRING_ALLOC(trustListFolder);
71260 ci->issuerListFolder = UA_STRING_ALLOC(issuerListFolder);
71261 ci->revocationListFolder = UA_STRING_ALLOC(revocationListFolder);
71262
71263 reloadCertificates(ci);
71264
71265 cv->context = (void*)ci;
71266 cv->verifyCertificate = certificateVerification_verify;
71267 cv->clear = certificateVerification_clear;
71268 cv->verifyApplicationURI = certificateVerification_verifyApplicationURI;
71269
71270 return UA_STATUSCODE_GOOD;
71271}
71272
71273#endif
71274#endif
71275
71276/**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.c" ****/
71277
71278
71279#if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION)
71280
71281
71282#include <mbedtls/aes.h>
71283#include <mbedtls/ctr_drbg.h>
71284#include <mbedtls/entropy.h>
71285#include <mbedtls/error.h>
71286#include <mbedtls/md.h>
71287#include <mbedtls/sha1.h>
71288#include <mbedtls/version.h>
71289#include <mbedtls/x509_crt.h>
71290
71291void
71292swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) {
71293 UA_ByteString tmp = *bufA;
71294 *bufA = *bufB;
71295 *bufB = tmp;
71296}
71297
71298void
71299mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key,
71300 const UA_ByteString *in, unsigned char *out) {
71301 mbedtls_md_hmac_starts(context, key->data, key->length);
71302 mbedtls_md_hmac_update(context, in->data, in->length);
71303 mbedtls_md_hmac_finish(context, out);
71304}
71305
71306UA_StatusCode
71307mbedtls_generateKey(mbedtls_md_context_t *context,
71308 const UA_ByteString *secret, const UA_ByteString *seed,
71309 UA_ByteString *out) {
71310#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71311 size_t hashLen = (size_t)mbedtls_md_get_size(context->md_info);
71312#else
71313 size_t hashLen = (size_t)mbedtls_md_get_size(context->private_md_info);
71314#endif
71315
71316 UA_ByteString A_and_seed;
71317 UA_ByteString_allocBuffer(&A_and_seed, hashLen + seed->length);
71318 memcpy(A_and_seed.data + hashLen, seed->data, seed->length);
71319
71320 UA_ByteString ANext_and_seed;
71321 UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length);
71322 memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length);
71323
71324 UA_ByteString A = {
71325 hashLen,
71326 A_and_seed.data
71327 };
71328
71329 UA_ByteString ANext = {
71330 hashLen,
71331 ANext_and_seed.data
71332 };
71333
71334 mbedtls_hmac(context, secret, seed, A.data);
71335
71336 UA_StatusCode retval = 0;
71337 for(size_t offset = 0; offset < out->length; offset += hashLen) {
71338 UA_ByteString outSegment = {
71339 hashLen,
71340 out->data + offset
71341 };
71342 UA_Boolean bufferAllocated = UA_FALSE;
71343 // Not enough room in out buffer to write the hash.
71344 if(offset + hashLen > out->length) {
71345 outSegment.data = NULL;
71346 outSegment.length = 0;
71347 retval = UA_ByteString_allocBuffer(&outSegment, hashLen);
71348 if(retval != UA_STATUSCODE_GOOD) {
71349 UA_ByteString_clear(&A_and_seed);
71350 UA_ByteString_clear(&ANext_and_seed);
71351 return retval;
71352 }
71353 bufferAllocated = UA_TRUE;
71354 }
71355
71356 mbedtls_hmac(context, secret, &A_and_seed, outSegment.data);
71357 mbedtls_hmac(context, secret, &A, ANext.data);
71358
71359 if(retval != UA_STATUSCODE_GOOD) {
71360 if(bufferAllocated)
71361 UA_ByteString_clear(&outSegment);
71362 UA_ByteString_clear(&A_and_seed);
71363 UA_ByteString_clear(&ANext_and_seed);
71364 return retval;
71365 }
71366
71367 if(bufferAllocated) {
71368 memcpy(out->data + offset, outSegment.data, out->length - offset);
71369 UA_ByteString_clear(&outSegment);
71370 }
71371
71372 swapBuffers(&ANext_and_seed, &A_and_seed);
71373 swapBuffers(&ANext, &A);
71374 }
71375
71376 UA_ByteString_clear(&A_and_seed);
71377 UA_ByteString_clear(&ANext_and_seed);
71378 return UA_STATUSCODE_GOOD;
71379}
71380
71381UA_StatusCode
71382mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message,
71383 const UA_ByteString *signature) {
71384 /* Compute the sha1 hash */
71385 unsigned char hash[UA_SHA1_LENGTH];
71386#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71387 mbedtls_sha1_ret(message->data, message->length, hash);
71388#else
71389 mbedtls_sha1(message->data, message->length, hash);
71390#endif
71391
71392 /* Set the RSA settings */
71393 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(certificate->pk);
71394 if(!rsaContext)
71395 return UA_STATUSCODE_BADINTERNALERROR;
71396 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
71397
71398 /* Verify */
71399 int mbedErr = mbedtls_pk_verify(&certificate->pk,
71400 MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH,
71401 signature->data, signature->length);
71402 if(mbedErr)
71403 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71404 return UA_STATUSCODE_GOOD;
71405}
71406
71407UA_StatusCode
71408mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey,
71409 mbedtls_ctr_drbg_context *drbgContext,
71410 const UA_ByteString *message,
71411 UA_ByteString *signature) {
71412 unsigned char hash[UA_SHA1_LENGTH];
71413#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71414 mbedtls_sha1_ret(message->data, message->length, hash);
71415#else
71416 mbedtls_sha1(message->data, message->length, hash);
71417#endif
71418
71419 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
71420 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE);
71421
71422 size_t sigLen = 0;
71423 int mbedErr = mbedtls_pk_sign(localPrivateKey, MBEDTLS_MD_SHA1, hash,
71424 UA_SHA1_LENGTH, signature->data,
71425#if MBEDTLS_VERSION_NUMBER >= 0x03000000
71426 signature->length,
71427#endif
71428 &sigLen,
71429 mbedtls_ctr_drbg_random, drbgContext);
71430 if(mbedErr)
71431 return UA_STATUSCODE_BADINTERNALERROR;
71432 return UA_STATUSCODE_GOOD;
71433}
71434
71435UA_StatusCode
71436mbedtls_thumbprint_sha1(const UA_ByteString *certificate,
71437 UA_ByteString *thumbprint) {
71438 if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL))
71439 return UA_STATUSCODE_BADINTERNALERROR;
71440
71441 if(thumbprint->length != UA_SHA1_LENGTH)
71442 return UA_STATUSCODE_BADINTERNALERROR;
71443
71444 /* The certificate thumbprint is always a 20 bit sha1 hash, see Part 4 of the Specification. */
71445#if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71446 mbedtls_sha1_ret(certificate->data, certificate->length, thumbprint->data);
71447#else
71448 mbedtls_sha1(certificate->data, certificate->length, thumbprint->data);
71449#endif
71450 return UA_STATUSCODE_GOOD;
71451}
71452
71453UA_StatusCode
71454mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context,
71455 mbedtls_ctr_drbg_context *drbgContext,
71456 UA_ByteString *data, const size_t plainTextBlockSize) {
71457 if(data->length % plainTextBlockSize != 0)
71458 return UA_STATUSCODE_BADINTERNALERROR;
71459
71460 size_t max_blocks = data->length / plainTextBlockSize;
71461
71462
71463 UA_ByteString encrypted;
71464#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71465 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * context->len);
71466#else
71467 size_t keylen = mbedtls_rsa_get_len(context);
71468 UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * keylen);
71469
71470#endif
71471
71472 if(retval != UA_STATUSCODE_GOOD)
71473 return retval;
71474
71475 size_t lenDataToEncrypt = data->length;
71476 size_t inOffset = 0;
71477 size_t offset = 0;
71478 const unsigned char *label = NULL;
71479 while(lenDataToEncrypt >= plainTextBlockSize) {
71480#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71481 int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
71482 drbgContext, MBEDTLS_RSA_PUBLIC,
71483 label, 0, plainTextBlockSize,
71484 data->data + inOffset, encrypted.data + offset);
71485#else
71486 int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random,
71487 drbgContext, label, 0, plainTextBlockSize,
71488 data->data + inOffset, encrypted.data + offset);
71489#endif
71490
71491 if(mbedErr) {
71492 UA_ByteString_clear(&encrypted);
71493 return UA_STATUSCODE_BADINTERNALERROR;
71494 }
71495
71496 inOffset += plainTextBlockSize;
71497#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71498 offset += context->len;
71499#else
71500 offset += keylen;
71501#endif
71502 lenDataToEncrypt -= plainTextBlockSize;
71503 }
71504
71505 memcpy(data->data, encrypted.data, offset);
71506 UA_ByteString_clear(&encrypted);
71507 return UA_STATUSCODE_GOOD;
71508}
71509
71510UA_StatusCode
71511mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey,
71512 mbedtls_ctr_drbg_context *drbgContext,
71513 UA_ByteString *data) {
71514 mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey);
71515 mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1);
71516#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71517 if(data->length % rsaContext->len != 0)
71518 return UA_STATUSCODE_BADINTERNALERROR;
71519#else
71520 size_t keylen = mbedtls_rsa_get_len(rsaContext);
71521 if(data->length % keylen != 0)
71522 return UA_STATUSCODE_BADINTERNALERROR;
71523#endif
71524
71525 size_t inOffset = 0;
71526 size_t outOffset = 0;
71527 size_t outLength = 0;
71528 unsigned char buf[512];
71529
71530 while(inOffset < data->length) {
71531#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71532 int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
71533 drbgContext, MBEDTLS_RSA_PRIVATE,
71534 NULL, 0, &outLength,
71535 data->data + inOffset,
71536 buf, 512);
71537#else
71538 int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random,
71539 drbgContext,
71540 NULL, 0, &outLength,
71541 data->data + inOffset,
71542 buf, 512);
71543#endif
71544
71545 if(mbedErr)
71546 return UA_STATUSCODE_BADSECURITYCHECKSFAILED;
71547
71548 memcpy(data->data + outOffset, buf, outLength);
71549#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71550 inOffset += rsaContext->len;
71551#else
71552 inOffset += keylen;
71553#endif
71554 outOffset += outLength;
71555 }
71556
71557 data->length = outOffset;
71558 return UA_STATUSCODE_GOOD;
71559}
71560
71561int
71562UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng) {
71563 UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(key);
71564#if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000
71565 int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0);
71566#else
71567 int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0, mbedtls_entropy_func, p_rng);
71568#endif
71569 UA_ByteString_clear(&data);
71570 return mbedErr;
71571}
71572
71573UA_StatusCode
71574UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData,
71575 UA_ByteString *target) {
71576 UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(certData);
71577
71578 mbedtls_x509_crt cert;
71579 mbedtls_x509_crt_init(&cert);
71580
71581 int mbedErr = mbedtls_x509_crt_parse(&cert, data.data, data.length);
71582
71583 UA_StatusCode result = UA_STATUSCODE_BADINVALIDARGUMENT;
71584
71585 if (!mbedErr) {
71586 UA_ByteString tmp;
71587 tmp.data = cert.raw.p;
71588 tmp.length = cert.raw.len;
71589
71590 result = UA_ByteString_copy(&tmp, target);
71591 } else {
71592 UA_ByteString_init(target);
71593 }
71594
71595 UA_ByteString_clear(&data);
71596 mbedtls_x509_crt_free(&cert);
71597 return result;
71598}
71599
71600// mbedTLS expects PEM data to be null terminated
71601// The data length parameter must include the null terminator
71602UA_ByteString
71603UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data) {
71604 UA_ByteString result;
71605 UA_ByteString_init(&result);
71606
71607 if (!data->length)
71608 return result;
71609
71610 if (data->length && data->data[0] == '-') {
71611 UA_ByteString_allocBuffer(&result, data->length + 1);
71612 memcpy(result.data, data->data, data->length);
71613 result.data[data->length] = '\0';
71614 } else {
71615 UA_ByteString_copy(data, &result);
71616 }
71617
71618 return result;
71619}
71620
71621#endif
71622
71623/**** amalgamated original file "/plugins/ua_log_stdout.c" ****/
71624
71625/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
71626 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
71627 *
71628 * Copyright 2016-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
71629 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
71630 */
71631
71632
71633#include <stdio.h>
71634
71635/* ANSI escape sequences for color output taken from here:
71636 * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
71637
71638#ifdef UA_ENABLE_LOG_COLORS
71639# define ANSI_COLOR_RED "\x1b[31m"
71640# define ANSI_COLOR_GREEN "\x1b[32m"
71641# define ANSI_COLOR_YELLOW "\x1b[33m"
71642# define ANSI_COLOR_BLUE "\x1b[34m"
71643# define ANSI_COLOR_MAGENTA "\x1b[35m"
71644# define ANSI_COLOR_CYAN "\x1b[36m"
71645# define ANSI_COLOR_RESET "\x1b[0m"
71646#else
71647# define ANSI_COLOR_RED ""
71648# define ANSI_COLOR_GREEN ""
71649# define ANSI_COLOR_YELLOW ""
71650# define ANSI_COLOR_BLUE ""
71651# define ANSI_COLOR_MAGENTA ""
71652# define ANSI_COLOR_CYAN ""
71653# define ANSI_COLOR_RESET ""
71654#endif
71655
71656static
71657const char *logLevelNames[6] = {"trace", "debug",
71658 ANSI_COLOR_GREEN "info",
71659 ANSI_COLOR_YELLOW "warn",
71660 ANSI_COLOR_RED "error",
71661 ANSI_COLOR_MAGENTA "fatal"};
71662static
71663const char *logCategoryNames[7] = {"network", "channel", "session", "server",
71664 "client", "userland", "securitypolicy"};
71665
71666typedef struct {
71667 UA_LogLevel minlevel;
71668#if UA_MULTITHREADING >= 100
71669 UA_Lock lock;
71670#endif
71671} LogContext;
71672
71673#ifdef __clang__
71674__attribute__((__format__(__printf__, 4 , 0)))
71675#endif
71676static void
71677UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category,
71678 const char *msg, va_list args) {
71679 LogContext *logContext = (LogContext*)context;
71680 if(logContext) {
71681 if(logContext->minlevel > level)
71682 return;
71683 UA_LOCK(&logContext->lock);
71684 }
71685
71686 UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset();
71687 UA_DateTimeStruct dts = UA_DateTime_toStruct(t: UA_DateTime_now() + tOffset);
71688
71689 printf(format: "[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t",
71690 dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec,
71691 (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[level],
71692 logCategoryNames[category]);
71693 vprintf(format: msg, arg: args);
71694 printf(format: "\n");
71695 fflush(stdout);
71696
71697 if(logContext) {
71698 UA_UNLOCK(&logContext->lock);
71699 }
71700}
71701
71702static void
71703UA_Log_Stdout_clear(void *context) {
71704 if(!context)
71705 return;
71706 UA_LOCK_DESTROY(&((LogContext*)context)->lock);
71707 UA_free(ptr: context);
71708}
71709
71710const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, UA_Log_Stdout_clear};
71711const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_;
71712
71713UA_Logger
71714UA_Log_Stdout_withLevel(UA_LogLevel minlevel) {
71715 LogContext *context = (LogContext*)UA_calloc(nmemb: 1, size: sizeof(LogContext));
71716 if(context) {
71717 UA_LOCK_INIT(&context->lock);
71718 context->minlevel = minlevel;
71719 }
71720
71721 UA_Logger logger = {UA_Log_Stdout_log, (void*)context, UA_Log_Stdout_clear};
71722 return logger;
71723}
71724
71725/**** amalgamated original file "/plugins/ua_accesscontrol_default.c" ****/
71726
71727/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
71728 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
71729 *
71730 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
71731 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
71732 * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
71733 */
71734
71735
71736/* Example access control management. Anonymous and username / password login.
71737 * The access rights are maximally permissive.
71738 *
71739 * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS
71740 * PERMISSIVE ACCESS CONTROL.
71741 *
71742 * For TransferSubscriptions, we check whether the transfer happens between
71743 * Sessions for the same user. */
71744
71745typedef struct {
71746 UA_Boolean allowAnonymous;
71747 size_t usernamePasswordLoginSize;
71748 UA_UsernamePasswordLogin *usernamePasswordLogin;
71749 UA_UsernamePasswordLoginCallback loginCallback;
71750 void *loginContext;
71751 UA_CertificateVerification verifyX509;
71752} AccessControlContext;
71753
71754#define ANONYMOUS_POLICY "open62541-anonymous-policy"
71755#define CERTIFICATE_POLICY "open62541-certificate-policy"
71756#define USERNAME_POLICY "open62541-username-policy"
71757const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY);
71758const UA_String certificate_policy = UA_STRING_STATIC(CERTIFICATE_POLICY);
71759const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY);
71760
71761/************************/
71762/* Access Control Logic */
71763/************************/
71764
71765static UA_StatusCode
71766activateSession_default(UA_Server *server, UA_AccessControl *ac,
71767 const UA_EndpointDescription *endpointDescription,
71768 const UA_ByteString *secureChannelRemoteCertificate,
71769 const UA_NodeId *sessionId,
71770 const UA_ExtensionObject *userIdentityToken,
71771 void **sessionContext) {
71772 AccessControlContext *context = (AccessControlContext*)ac->context;
71773
71774 /* The empty token is interpreted as anonymous */
71775 if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
71776 if(!context->allowAnonymous)
71777 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71778
71779 /* No userdata atm */
71780 *sessionContext = NULL;
71781 return UA_STATUSCODE_GOOD;
71782 }
71783
71784 /* Could the token be decoded? */
71785 if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
71786 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71787
71788 /* Anonymous login */
71789 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
71790 if(!context->allowAnonymous)
71791 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71792
71793 const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
71794 userIdentityToken->content.decoded.data;
71795
71796 /* Compatibility notice: Siemens OPC Scout v10 provides an empty
71797 * policyId. This is not compliant. For compatibility, assume that empty
71798 * policyId == ANONYMOUS_POLICY */
71799 if(token->policyId.data && !UA_String_equal(s1: &token->policyId, s2: &anonymous_policy))
71800 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71801
71802 /* No userdata atm */
71803 *sessionContext = NULL;
71804 return UA_STATUSCODE_GOOD;
71805 }
71806
71807 /* Username and password */
71808 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
71809 const UA_UserNameIdentityToken *userToken =
71810 (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data;
71811
71812 if(!UA_String_equal(s1: &userToken->policyId, s2: &username_policy))
71813 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71814
71815 /* The userToken has been decrypted by the server before forwarding
71816 * it to the plugin. This information can be used here. */
71817 /* if(userToken->encryptionAlgorithm.length > 0) {} */
71818
71819 /* Empty username and password */
71820 if(userToken->userName.length == 0 && userToken->password.length == 0)
71821 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71822
71823 /* Try to match username/pw */
71824 UA_Boolean match = false;
71825 if(context->loginCallback) {
71826 if(context->loginCallback(&userToken->userName, &userToken->password,
71827 context->usernamePasswordLoginSize, context->usernamePasswordLogin,
71828 sessionContext, context->loginContext) == UA_STATUSCODE_GOOD)
71829 match = true;
71830 } else {
71831 for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
71832 if(UA_String_equal(s1: &userToken->userName, s2: &context->usernamePasswordLogin[i].username) &&
71833 UA_String_equal(s1: &userToken->password, s2: &context->usernamePasswordLogin[i].password)) {
71834 match = true;
71835 break;
71836 }
71837 }
71838 }
71839 if(!match)
71840 return UA_STATUSCODE_BADUSERACCESSDENIED;
71841
71842 /* For the CTT, recognize whether two sessions are */
71843 UA_ByteString *username = UA_ByteString_new();
71844 if(username)
71845 UA_ByteString_copy(src: &userToken->userName, dst: username);
71846 *sessionContext = username;
71847 return UA_STATUSCODE_GOOD;
71848 }
71849
71850 /* x509 certificate */
71851 if(userIdentityToken->content.decoded.type == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
71852 const UA_X509IdentityToken *userToken = (UA_X509IdentityToken*)
71853 userIdentityToken->content.decoded.data;
71854
71855 if(!UA_String_equal(s1: &userToken->policyId, s2: &certificate_policy))
71856 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71857
71858 if(!context->verifyX509.verifyCertificate)
71859 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71860
71861 return context->verifyX509.
71862 verifyCertificate(context->verifyX509.context,
71863 &userToken->certificateData);
71864 }
71865
71866 /* Unsupported token type */
71867 return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
71868}
71869
71870static void
71871closeSession_default(UA_Server *server, UA_AccessControl *ac,
71872 const UA_NodeId *sessionId, void *sessionContext) {
71873 if(sessionContext)
71874 UA_ByteString_delete(p: (UA_ByteString*)sessionContext);
71875}
71876
71877static UA_UInt32
71878getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
71879 const UA_NodeId *sessionId, void *sessionContext,
71880 const UA_NodeId *nodeId, void *nodeContext) {
71881 return 0xFFFFFFFF;
71882}
71883
71884static UA_Byte
71885getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
71886 const UA_NodeId *sessionId, void *sessionContext,
71887 const UA_NodeId *nodeId, void *nodeContext) {
71888 return 0xFF;
71889}
71890
71891static UA_Boolean
71892getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
71893 const UA_NodeId *sessionId, void *sessionContext,
71894 const UA_NodeId *methodId, void *methodContext) {
71895 return true;
71896}
71897
71898static UA_Boolean
71899getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
71900 const UA_NodeId *sessionId, void *sessionContext,
71901 const UA_NodeId *methodId, void *methodContext,
71902 const UA_NodeId *objectId, void *objectContext) {
71903 return true;
71904}
71905
71906static UA_Boolean
71907allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
71908 const UA_NodeId *sessionId, void *sessionContext,
71909 const UA_AddNodesItem *item) {
71910 return true;
71911}
71912
71913static UA_Boolean
71914allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
71915 const UA_NodeId *sessionId, void *sessionContext,
71916 const UA_AddReferencesItem *item) {
71917 return true;
71918}
71919
71920static UA_Boolean
71921allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
71922 const UA_NodeId *sessionId, void *sessionContext,
71923 const UA_DeleteNodesItem *item) {
71924 return true;
71925}
71926
71927static UA_Boolean
71928allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
71929 const UA_NodeId *sessionId, void *sessionContext,
71930 const UA_DeleteReferencesItem *item) {
71931 return true;
71932}
71933
71934static UA_Boolean
71935allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
71936 const UA_NodeId *sessionId, void *sessionContext,
71937 const UA_NodeId *nodeId, void *nodeContext) {
71938 return true;
71939}
71940
71941#ifdef UA_ENABLE_SUBSCRIPTIONS
71942static UA_Boolean
71943allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac,
71944 const UA_NodeId *oldSessionId, void *oldSessionContext,
71945 const UA_NodeId *newSessionId, void *newSessionContext) {
71946 if(oldSessionContext == newSessionContext)
71947 return true;
71948 if(oldSessionContext && newSessionContext)
71949 return UA_ByteString_equal(string1: (UA_ByteString*)oldSessionContext,
71950 string2: (UA_ByteString*)newSessionContext);
71951 return false;
71952}
71953#endif
71954
71955#ifdef UA_ENABLE_HISTORIZING
71956static UA_Boolean
71957allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
71958 const UA_NodeId *sessionId, void *sessionContext,
71959 const UA_NodeId *nodeId,
71960 UA_PerformUpdateType performInsertReplace,
71961 const UA_DataValue *value) {
71962 return true;
71963}
71964
71965static UA_Boolean
71966allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
71967 const UA_NodeId *sessionId, void *sessionContext,
71968 const UA_NodeId *nodeId,
71969 UA_DateTime startTimestamp,
71970 UA_DateTime endTimestamp,
71971 bool isDeleteModified) {
71972 return true;
71973}
71974#endif
71975
71976/***************************************/
71977/* Create Delete Access Control Plugin */
71978/***************************************/
71979
71980static void clear_default(UA_AccessControl *ac) {
71981 UA_Array_delete(p: (void*)(uintptr_t)ac->userTokenPolicies,
71982 size: ac->userTokenPoliciesSize,
71983 type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
71984 ac->userTokenPolicies = NULL;
71985 ac->userTokenPoliciesSize = 0;
71986
71987 AccessControlContext *context = (AccessControlContext*)ac->context;
71988
71989 if (context) {
71990 for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
71991 UA_String_clear(p: &context->usernamePasswordLogin[i].username);
71992 UA_String_clear(p: &context->usernamePasswordLogin[i].password);
71993 }
71994 if(context->usernamePasswordLoginSize > 0)
71995 UA_free(ptr: context->usernamePasswordLogin);
71996
71997 if(context->verifyX509.clear)
71998 context->verifyX509.clear(&context->verifyX509);
71999
72000 UA_free(ptr: ac->context);
72001 ac->context = NULL;
72002 }
72003}
72004
72005UA_StatusCode
72006UA_AccessControl_default(UA_ServerConfig *config,
72007 UA_Boolean allowAnonymous,
72008 UA_CertificateVerification *verifyX509,
72009 const UA_ByteString *userTokenPolicyUri,
72010 size_t usernamePasswordLoginSize,
72011 const UA_UsernamePasswordLogin *usernamePasswordLogin) {
72012 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
72013 msg: "AccessControl: Unconfigured AccessControl. Users have all permissions.");
72014 UA_AccessControl *ac = &config->accessControl;
72015
72016 if(ac->clear)
72017 clear_default(ac);
72018
72019 ac->clear = clear_default;
72020 ac->activateSession = activateSession_default;
72021 ac->closeSession = closeSession_default;
72022 ac->getUserRightsMask = getUserRightsMask_default;
72023 ac->getUserAccessLevel = getUserAccessLevel_default;
72024 ac->getUserExecutable = getUserExecutable_default;
72025 ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
72026 ac->allowAddNode = allowAddNode_default;
72027 ac->allowAddReference = allowAddReference_default;
72028 ac->allowBrowseNode = allowBrowseNode_default;
72029
72030#ifdef UA_ENABLE_SUBSCRIPTIONS
72031 ac->allowTransferSubscription = allowTransferSubscription_default;
72032#endif
72033
72034#ifdef UA_ENABLE_HISTORIZING
72035 ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
72036 ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
72037#endif
72038
72039 ac->allowDeleteNode = allowDeleteNode_default;
72040 ac->allowDeleteReference = allowDeleteReference_default;
72041
72042 AccessControlContext *context = (AccessControlContext*)
72043 UA_malloc(size: sizeof(AccessControlContext));
72044 if(!context)
72045 return UA_STATUSCODE_BADOUTOFMEMORY;
72046 memset(s: context, c: 0, n: sizeof(AccessControlContext));
72047 ac->context = context;
72048
72049 /* Allow anonymous? */
72050 context->allowAnonymous = allowAnonymous;
72051 if(allowAnonymous) {
72052 UA_LOG_INFO(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
72053 msg: "AccessControl: Anonymous login is enabled");
72054 }
72055
72056 /* Allow x509 certificates? Move the plugin over. */
72057 if(verifyX509) {
72058 context->verifyX509 = *verifyX509;
72059 memset(s: verifyX509, c: 0, n: sizeof(UA_CertificateVerification));
72060 } else {
72061 memset(s: &context->verifyX509, c: 0, n: sizeof(UA_CertificateVerification));
72062 UA_LOG_INFO(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
72063 msg: "AccessControl: x509 certificate user authentication is enabled");
72064 }
72065
72066 /* Copy username/password to the access control plugin */
72067 if(usernamePasswordLoginSize > 0) {
72068 context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
72069 UA_malloc(size: usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
72070 if(!context->usernamePasswordLogin)
72071 return UA_STATUSCODE_BADOUTOFMEMORY;
72072 context->usernamePasswordLoginSize = usernamePasswordLoginSize;
72073 for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
72074 UA_String_copy(src: &usernamePasswordLogin[i].username,
72075 dst: &context->usernamePasswordLogin[i].username);
72076 UA_String_copy(src: &usernamePasswordLogin[i].password,
72077 dst: &context->usernamePasswordLogin[i].password);
72078 }
72079 }
72080
72081 /* Set the allowed policies */
72082 size_t policies = 0;
72083 if(allowAnonymous)
72084 policies++;
72085 if(verifyX509)
72086 policies++;
72087 if(usernamePasswordLoginSize > 0)
72088 policies++;
72089 ac->userTokenPoliciesSize = 0;
72090 ac->userTokenPolicies = (UA_UserTokenPolicy *)
72091 UA_Array_new(size: policies, type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
72092 if(!ac->userTokenPolicies)
72093 return UA_STATUSCODE_BADOUTOFMEMORY;
72094 ac->userTokenPoliciesSize = policies;
72095
72096 policies = 0;
72097 if(allowAnonymous) {
72098 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
72099 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
72100 policies++;
72101 }
72102
72103 if(verifyX509) {
72104 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE;
72105 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY);
72106#if UA_LOGLEVEL <= 400
72107 if(UA_ByteString_equal(string1: userTokenPolicyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
72108 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
72109 msg: "x509 Certificate Authentication configured, "
72110 "but no encrypting SecurityPolicy. "
72111 "This can leak credentials on the network.");
72112 }
72113#endif
72114 UA_ByteString_copy(src: userTokenPolicyUri,
72115 dst: &ac->userTokenPolicies[policies].securityPolicyUri);
72116 policies++;
72117 }
72118
72119 if(usernamePasswordLoginSize > 0) {
72120 ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
72121 ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
72122#if UA_LOGLEVEL <= 400
72123 if(UA_ByteString_equal(string1: userTokenPolicyUri, string2: &UA_SECURITY_POLICY_NONE_URI)) {
72124 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_SERVER,
72125 msg: "Username/Password Authentication configured, "
72126 "but no encrypting SecurityPolicy. "
72127 "This can leak credentials on the network.");
72128 }
72129#endif
72130 UA_ByteString_copy(src: userTokenPolicyUri,
72131 dst: &ac->userTokenPolicies[policies].securityPolicyUri);
72132 }
72133 return UA_STATUSCODE_GOOD;
72134}
72135
72136UA_StatusCode
72137UA_AccessControl_defaultWithLoginCallback(UA_ServerConfig *config,
72138 UA_Boolean allowAnonymous, UA_CertificateVerification *verifyX509,
72139 const UA_ByteString *userTokenPolicyUri, size_t usernamePasswordLoginSize,
72140 const UA_UsernamePasswordLogin *usernamePasswordLogin,
72141 UA_UsernamePasswordLoginCallback loginCallback, void *loginContext)
72142{
72143 AccessControlContext *context;
72144 UA_StatusCode sc;
72145
72146 sc = UA_AccessControl_default(config, allowAnonymous, verifyX509,
72147 userTokenPolicyUri, usernamePasswordLoginSize, usernamePasswordLogin);
72148 if (sc != UA_STATUSCODE_GOOD)
72149 return sc;
72150
72151 context = (AccessControlContext *)config->accessControl.context;
72152 context->loginCallback = loginCallback;
72153 context->loginContext = loginContext;
72154
72155 return UA_STATUSCODE_GOOD;
72156}
72157
72158/**** amalgamated original file "/plugins/ua_nodestore_ziptree.c" ****/
72159
72160/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
72161 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
72162 *
72163 * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
72164 * Copyright 2017 (c) Julian Grothoff
72165 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
72166 */
72167
72168
72169#ifndef container_of
72170#define container_of(ptr, type, member) \
72171 (type *)((uintptr_t)ptr - offsetof(type,member))
72172#endif
72173
72174struct NodeEntry;
72175typedef struct NodeEntry NodeEntry;
72176
72177struct NodeEntry {
72178 ZIP_ENTRY(NodeEntry) zipfields;
72179 UA_UInt32 nodeIdHash;
72180 UA_UInt16 refCount; /* How many consumers have a reference to the node? */
72181 UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
72182 NodeEntry *orig; /* If a copy is made to replace a node, track that we
72183 * replace only the node from which the copy was made.
72184 * Important for concurrent operations. */
72185 UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */
72186};
72187
72188/* Absolute ordering for NodeIds */
72189static enum ZIP_CMP
72190cmpNodeId(const void *a, const void *b) {
72191 const NodeEntry *aa = (const NodeEntry*)a;
72192 const NodeEntry *bb = (const NodeEntry*)b;
72193
72194 /* Compare hash */
72195 if(aa->nodeIdHash < bb->nodeIdHash)
72196 return ZIP_CMP_LESS;
72197 if(aa->nodeIdHash > bb->nodeIdHash)
72198 return ZIP_CMP_MORE;
72199
72200 /* Compore nodes in detail */
72201 return (enum ZIP_CMP)UA_NodeId_order(n1: &aa->nodeId, n2: &bb->nodeId);
72202}
72203
72204ZIP_HEAD(NodeTree, NodeEntry);
72205typedef struct NodeTree NodeTree;
72206
72207typedef struct {
72208 NodeTree root;
72209
72210 /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
72211 UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
72212 UA_Byte referenceTypeCounter;
72213} ZipContext;
72214
72215ZIP_FUNCTIONS(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId)
72216
72217static NodeEntry *
72218newEntry(UA_NodeClass nodeClass) {
72219 size_t size = sizeof(NodeEntry) - sizeof(UA_NodeId);
72220 switch(nodeClass) {
72221 case UA_NODECLASS_OBJECT:
72222 size += sizeof(UA_ObjectNode);
72223 break;
72224 case UA_NODECLASS_VARIABLE:
72225 size += sizeof(UA_VariableNode);
72226 break;
72227 case UA_NODECLASS_METHOD:
72228 size += sizeof(UA_MethodNode);
72229 break;
72230 case UA_NODECLASS_OBJECTTYPE:
72231 size += sizeof(UA_ObjectTypeNode);
72232 break;
72233 case UA_NODECLASS_VARIABLETYPE:
72234 size += sizeof(UA_VariableTypeNode);
72235 break;
72236 case UA_NODECLASS_REFERENCETYPE:
72237 size += sizeof(UA_ReferenceTypeNode);
72238 break;
72239 case UA_NODECLASS_DATATYPE:
72240 size += sizeof(UA_DataTypeNode);
72241 break;
72242 case UA_NODECLASS_VIEW:
72243 size += sizeof(UA_ViewNode);
72244 break;
72245 default:
72246 return NULL;
72247 }
72248 NodeEntry *entry = (NodeEntry*)UA_calloc(nmemb: 1, size: size);
72249 if(!entry)
72250 return NULL;
72251 UA_Node *node = (UA_Node*)&entry->nodeId;
72252 node->head.nodeClass = nodeClass;
72253 return entry;
72254}
72255
72256static void
72257deleteEntry(NodeEntry *entry) {
72258 UA_Node_clear(node: (UA_Node*)&entry->nodeId);
72259 UA_free(ptr: entry);
72260}
72261
72262static void
72263cleanupEntry(NodeEntry *entry) {
72264 if(entry->refCount > 0)
72265 return;
72266 if(entry->deleted) {
72267 deleteEntry(entry);
72268 return;
72269 }
72270 UA_NodeHead *head = (UA_NodeHead*)&entry->nodeId;
72271 for(size_t i = 0; i < head->referencesSize; i++) {
72272 UA_NodeReferenceKind *rk = &head->references[i];
72273 if(rk->targetsSize > 16 && !rk->hasRefTree)
72274 UA_NodeReferenceKind_switch(rk);
72275 }
72276}
72277
72278/***********************/
72279/* Interface functions */
72280/***********************/
72281
72282/* Not yet inserted into the ZipContext */
72283static UA_Node *
72284zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) {
72285 NodeEntry *entry = newEntry(nodeClass);
72286 if(!entry)
72287 return NULL;
72288 return (UA_Node*)&entry->nodeId;
72289}
72290
72291/* Not yet inserted into the ZipContext */
72292static void
72293zipNsDeleteNode(void *nsCtx, UA_Node *node) {
72294 deleteEntry(container_of(node, NodeEntry, nodeId));
72295}
72296
72297static const UA_Node *
72298zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId) {
72299 ZipContext *ns = (ZipContext*)nsCtx;
72300 NodeEntry dummy;
72301 dummy.nodeIdHash = UA_NodeId_hash(n: nodeId);
72302 dummy.nodeId = *nodeId;
72303 NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
72304 if(!entry)
72305 return NULL;
72306 ++entry->refCount;
72307 return (const UA_Node*)&entry->nodeId;
72308}
72309
72310static void
72311zipNsReleaseNode(void *nsCtx, const UA_Node *node) {
72312 if(!node)
72313 return;
72314 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72315 UA_assert(entry->refCount > 0);
72316 --entry->refCount;
72317 cleanupEntry(entry);
72318}
72319
72320static UA_StatusCode
72321zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId,
72322 UA_Node **outNode) {
72323 /* Find the node */
72324 const UA_Node *node = zipNsGetNode(nsCtx, nodeId);
72325 if(!node)
72326 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72327
72328 /* Create the new entry */
72329 NodeEntry *ne = newEntry(nodeClass: node->head.nodeClass);
72330 if(!ne) {
72331 zipNsReleaseNode(nsCtx, node);
72332 return UA_STATUSCODE_BADOUTOFMEMORY;
72333 }
72334
72335 /* Copy the node content */
72336 UA_Node *nnode = (UA_Node*)&ne->nodeId;
72337 UA_StatusCode retval = UA_Node_copy(src: node, dst: nnode);
72338 zipNsReleaseNode(nsCtx, node);
72339 if(retval != UA_STATUSCODE_GOOD) {
72340 deleteEntry(entry: ne);
72341 return retval;
72342 }
72343
72344 ne->orig = container_of(node, NodeEntry, nodeId);
72345 *outNode = nnode;
72346 return UA_STATUSCODE_GOOD;
72347}
72348
72349static UA_StatusCode
72350zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) {
72351 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72352 ZipContext *ns = (ZipContext*)nsCtx;
72353
72354 /* Ensure that the NodeId is unique */
72355 NodeEntry dummy;
72356 memset(s: &dummy, c: 0, n: sizeof(NodeEntry));
72357 dummy.nodeId = node->head.nodeId;
72358 if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
72359 node->head.nodeId.identifier.numeric == 0) {
72360 do { /* Create a random nodeid until we find an unoccupied id */
72361 UA_UInt32 numId = UA_UInt32_random();
72362#if SIZE_MAX <= UA_UINT32_MAX
72363 /* The compressed "immediate" representation of nodes does not
72364 * support the full range on 32bit systems. Generate smaller
72365 * identifiers as they can be stored more compactly. */
72366 if(numId >= (0x01 << 24))
72367 numId = numId % (0x01 << 24);
72368#endif
72369 node->head.nodeId.identifier.numeric = numId;
72370 dummy.nodeId.identifier.numeric = numId;
72371 dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72372 } while(ZIP_FIND(NodeTree, &ns->root, &dummy));
72373 } else {
72374 dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72375 if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */
72376 deleteEntry(entry);
72377 return UA_STATUSCODE_BADNODEIDEXISTS;
72378 }
72379 }
72380
72381 /* Copy the NodeId */
72382 if(addedNodeId) {
72383 UA_StatusCode retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId);
72384 if(retval != UA_STATUSCODE_GOOD) {
72385 deleteEntry(entry);
72386 return retval;
72387 }
72388 }
72389
72390 /* For new ReferencetypeNodes add to the index map */
72391 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
72392 UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
72393 if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
72394 deleteEntry(entry);
72395 return UA_STATUSCODE_BADINTERNALERROR;
72396 }
72397
72398 UA_StatusCode retval =
72399 UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]);
72400 if(retval != UA_STATUSCODE_GOOD) {
72401 deleteEntry(entry);
72402 return UA_STATUSCODE_BADINTERNALERROR;
72403 }
72404
72405 /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
72406 refNode->referenceTypeIndex = ns->referenceTypeCounter;
72407 refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter);
72408
72409 ns->referenceTypeCounter++;
72410 }
72411
72412 /* Insert the node */
72413 entry->nodeIdHash = dummy.nodeIdHash;
72414 ZIP_INSERT(NodeTree, &ns->root, entry, UA_UInt32_random());
72415 return UA_STATUSCODE_GOOD;
72416}
72417
72418static UA_StatusCode
72419zipNsReplaceNode(void *nsCtx, UA_Node *node) {
72420 /* Find the node */
72421 const UA_Node *oldNode = zipNsGetNode(nsCtx, nodeId: &node->head.nodeId);
72422 if(!oldNode) {
72423 deleteEntry(container_of(node, NodeEntry, nodeId));
72424 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72425 }
72426
72427 /* Test if the copy is current */
72428 NodeEntry *entry = container_of(node, NodeEntry, nodeId);
72429 NodeEntry *oldEntry = container_of(oldNode, NodeEntry, nodeId);
72430 if(oldEntry != entry->orig) {
72431 /* The node was already updated since the copy was made */
72432 deleteEntry(entry);
72433 zipNsReleaseNode(nsCtx, node: oldNode);
72434 return UA_STATUSCODE_BADINTERNALERROR;
72435 }
72436
72437 /* Replace */
72438 ZipContext *ns = (ZipContext*)nsCtx;
72439 ZIP_REMOVE(NodeTree, &ns->root, oldEntry);
72440 entry->nodeIdHash = oldEntry->nodeIdHash;
72441 ZIP_INSERT(NodeTree, &ns->root, entry, ZIP_RANK(entry, zipfields));
72442 oldEntry->deleted = true;
72443
72444 zipNsReleaseNode(nsCtx, node: oldNode);
72445 return UA_STATUSCODE_GOOD;
72446}
72447
72448static UA_StatusCode
72449zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) {
72450 ZipContext *ns = (ZipContext*)nsCtx;
72451 NodeEntry dummy;
72452 dummy.nodeIdHash = UA_NodeId_hash(n: nodeId);
72453 dummy.nodeId = *nodeId;
72454 NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy);
72455 if(!entry)
72456 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72457 ZIP_REMOVE(NodeTree, &ns->root, entry);
72458 entry->deleted = true;
72459 cleanupEntry(entry);
72460 return UA_STATUSCODE_GOOD;
72461}
72462
72463static const UA_NodeId *
72464zipNsGetReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
72465 ZipContext *ns = (ZipContext*)nsCtx;
72466 if(refTypeIndex >= ns->referenceTypeCounter)
72467 return NULL;
72468 return &ns->referenceTypeIds[refTypeIndex];
72469}
72470
72471struct VisitorData {
72472 UA_NodestoreVisitor visitor;
72473 void *visitorContext;
72474};
72475
72476static void
72477nodeVisitor(NodeEntry *entry, void *data) {
72478 struct VisitorData *d = (struct VisitorData*)data;
72479 d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId);
72480}
72481
72482static void
72483zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor,
72484 void *visitorCtx) {
72485 struct VisitorData d;
72486 d.visitor = visitor;
72487 d.visitorContext = visitorCtx;
72488 ZipContext *ns = (ZipContext*)nsCtx;
72489 ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d);
72490}
72491
72492static void
72493deleteNodeVisitor(NodeEntry *entry, void *data) {
72494 deleteEntry(entry);
72495}
72496
72497/***********************/
72498/* Nodestore Lifecycle */
72499/***********************/
72500
72501static void
72502zipNsClear(void *nsCtx) {
72503 if (!nsCtx)
72504 return;
72505 ZipContext *ns = (ZipContext*)nsCtx;
72506 ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL);
72507
72508 /* Clean up the ReferenceTypes index array */
72509 for(size_t i = 0; i < ns->referenceTypeCounter; i++)
72510 UA_NodeId_clear(p: &ns->referenceTypeIds[i]);
72511
72512 UA_free(ptr: ns);
72513}
72514
72515UA_StatusCode
72516UA_Nodestore_ZipTree(UA_Nodestore *ns) {
72517 /* Allocate and initialize the context */
72518 ZipContext *ctx = (ZipContext*)UA_malloc(size: sizeof(ZipContext));
72519 if(!ctx)
72520 return UA_STATUSCODE_BADOUTOFMEMORY;
72521
72522 ZIP_INIT(&ctx->root);
72523 ctx->referenceTypeCounter = 0;
72524
72525 /* Populate the nodestore */
72526 ns->context = (void*)ctx;
72527 ns->clear = zipNsClear;
72528 ns->newNode = zipNsNewNode;
72529 ns->deleteNode = zipNsDeleteNode;
72530 ns->getNode = zipNsGetNode;
72531 ns->releaseNode = zipNsReleaseNode;
72532 ns->getNodeCopy = zipNsGetNodeCopy;
72533 ns->insertNode = zipNsInsertNode;
72534 ns->replaceNode = zipNsReplaceNode;
72535 ns->removeNode = zipNsRemoveNode;
72536 ns->getReferenceTypeId = zipNsGetReferenceTypeId;
72537 ns->iterate = zipNsIterate;
72538
72539 return UA_STATUSCODE_GOOD;
72540}
72541
72542/**** amalgamated original file "/plugins/ua_nodestore_hashmap.c" ****/
72543
72544/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
72545 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
72546 *
72547 * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
72548 * Copyright 2017 (c) Julian Grothoff
72549 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
72550 */
72551
72552
72553#ifndef container_of
72554#define container_of(ptr, type, member) \
72555 (type *)((uintptr_t)ptr - offsetof(type,member))
72556#endif
72557
72558/* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an
72559 * entry, iterate over candidate positions according to the NodeId hash.
72560 *
72561 * - Tombstone or non-matching NodeId: continue searching
72562 * - Matching NodeId: Return the entry
72563 * - NULL: Abort the search */
72564
72565typedef struct UA_NodeMapEntry {
72566 struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */
72567 UA_UInt16 refCount; /* How many consumers have a reference to the node? */
72568 UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */
72569 UA_Node node;
72570} UA_NodeMapEntry;
72571
72572#define UA_NODEMAP_MINSIZE 64
72573#define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01)
72574
72575typedef struct {
72576 UA_NodeMapEntry *entry;
72577 UA_UInt32 nodeIdHash;
72578} UA_NodeMapSlot;
72579
72580typedef struct {
72581 UA_NodeMapSlot *slots;
72582 UA_UInt32 size;
72583 UA_UInt32 count;
72584 UA_UInt32 sizePrimeIndex;
72585
72586 /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */
72587 UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX];
72588 UA_Byte referenceTypeCounter;
72589} UA_NodeMap;
72590
72591/*********************/
72592/* HashMap Utilities */
72593/*********************/
72594
72595/* The size of the hash-map is always a prime number. They are chosen to be
72596 * close to the next power of 2. So the size ca. doubles with each prime. */
72597static UA_UInt32 const primes[] = {
72598 7, 13, 31, 61, 127, 251,
72599 509, 1021, 2039, 4093, 8191, 16381,
72600 32749, 65521, 131071, 262139, 524287, 1048573,
72601 2097143, 4194301, 8388593, 16777213, 33554393, 67108859,
72602 134217689, 268435399, 536870909, 1073741789, 2147483647, 4294967291
72603};
72604
72605static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; }
72606static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); }
72607
72608static UA_UInt16
72609higher_prime_index(UA_UInt32 n) {
72610 UA_UInt16 low = 0;
72611 UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32));
72612 while(low != high) {
72613 UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2));
72614 if(n > primes[mid])
72615 low = (UA_UInt16)(mid + 1);
72616 else
72617 high = mid;
72618 }
72619 return low;
72620}
72621
72622/* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */
72623static UA_NodeMapSlot *
72624findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
72625 UA_UInt32 h = UA_NodeId_hash(n: nodeid);
72626 UA_UInt32 size = ns->size;
72627 UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
72628 UA_UInt32 startIdx = (UA_UInt32)idx;
72629 UA_UInt32 hash2 = mod2(h, size);
72630
72631 UA_NodeMapSlot *candidate = NULL;
72632 do {
72633 UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx];
72634
72635 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72636 /* A Node with the NodeId does already exist */
72637 if(slot->nodeIdHash == h &&
72638 UA_NodeId_equal(n1: &slot->entry->node.head.nodeId, n2: nodeid))
72639 return NULL;
72640 } else {
72641 /* Found a candidate node */
72642 if(!candidate)
72643 candidate = slot;
72644 /* No matching node can come afterwards */
72645 if(slot->entry == NULL)
72646 return candidate;
72647 }
72648
72649 idx += hash2;
72650 if(idx >= size)
72651 idx -= size;
72652 } while((UA_UInt32)idx != startIdx);
72653
72654 return candidate;
72655}
72656
72657/* The occupancy of the table after the call will be about 50% */
72658static UA_StatusCode
72659expand(UA_NodeMap *ns) {
72660 UA_UInt32 osize = ns->size;
72661 UA_UInt32 count = ns->count;
72662 /* Resize only when table after removal of unused elements is either too
72663 full or too empty */
72664 if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE))
72665 return UA_STATUSCODE_GOOD;
72666
72667 UA_NodeMapSlot *oslots = ns->slots;
72668 UA_UInt32 nindex = higher_prime_index(n: count * 2);
72669 UA_UInt32 nsize = primes[nindex];
72670 UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nmemb: nsize, size: sizeof(UA_NodeMapSlot));
72671 if(!nslots)
72672 return UA_STATUSCODE_BADOUTOFMEMORY;
72673
72674 ns->slots = nslots;
72675 ns->size = nsize;
72676 ns->sizePrimeIndex = nindex;
72677
72678 /* recompute the position of every entry and insert the pointer */
72679 for(size_t i = 0, j = 0; i < osize && j < count; ++i) {
72680 if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE)
72681 continue;
72682 UA_NodeMapSlot *s = findFreeSlot(ns, nodeid: &oslots[i].entry->node.head.nodeId);
72683 UA_assert(s);
72684 *s = oslots[i];
72685 ++j;
72686 }
72687
72688 UA_free(ptr: oslots);
72689 return UA_STATUSCODE_GOOD;
72690}
72691
72692static UA_NodeMapEntry *
72693createEntry(UA_NodeClass nodeClass) {
72694 size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node);
72695 switch(nodeClass) {
72696 case UA_NODECLASS_OBJECT:
72697 size += sizeof(UA_ObjectNode);
72698 break;
72699 case UA_NODECLASS_VARIABLE:
72700 size += sizeof(UA_VariableNode);
72701 break;
72702 case UA_NODECLASS_METHOD:
72703 size += sizeof(UA_MethodNode);
72704 break;
72705 case UA_NODECLASS_OBJECTTYPE:
72706 size += sizeof(UA_ObjectTypeNode);
72707 break;
72708 case UA_NODECLASS_VARIABLETYPE:
72709 size += sizeof(UA_VariableTypeNode);
72710 break;
72711 case UA_NODECLASS_REFERENCETYPE:
72712 size += sizeof(UA_ReferenceTypeNode);
72713 break;
72714 case UA_NODECLASS_DATATYPE:
72715 size += sizeof(UA_DataTypeNode);
72716 break;
72717 case UA_NODECLASS_VIEW:
72718 size += sizeof(UA_ViewNode);
72719 break;
72720 default:
72721 return NULL;
72722 }
72723 UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(nmemb: 1, size: size);
72724 if(!entry)
72725 return NULL;
72726 entry->node.head.nodeClass = nodeClass;
72727 return entry;
72728}
72729
72730static void
72731deleteNodeMapEntry(UA_NodeMapEntry *entry) {
72732 UA_Node_clear(node: &entry->node);
72733 UA_free(ptr: entry);
72734}
72735
72736static void
72737cleanupNodeMapEntry(UA_NodeMapEntry *entry) {
72738 if(entry->refCount > 0)
72739 return;
72740 if(entry->deleted) {
72741 deleteNodeMapEntry(entry);
72742 return;
72743 }
72744 for(size_t i = 0; i < entry->node.head.referencesSize; i++) {
72745 UA_NodeReferenceKind *rk = &entry->node.head.references[i];
72746 if(rk->targetsSize > 16 && !rk->hasRefTree)
72747 UA_NodeReferenceKind_switch(rk);
72748 }
72749}
72750
72751static UA_NodeMapSlot *
72752findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) {
72753 UA_UInt32 h = UA_NodeId_hash(n: nodeid);
72754 UA_UInt32 size = ns->size;
72755 UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */
72756 UA_UInt32 hash2 = mod2(h, size);
72757 UA_UInt32 startIdx = (UA_UInt32)idx;
72758
72759 do {
72760 UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx];
72761 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72762 if(slot->nodeIdHash == h &&
72763 UA_NodeId_equal(n1: &slot->entry->node.head.nodeId, n2: nodeid))
72764 return slot;
72765 } else {
72766 if(slot->entry == NULL)
72767 return NULL; /* No further entry possible */
72768 }
72769
72770 idx += hash2;
72771 if(idx >= size)
72772 idx -= size;
72773 } while((UA_UInt32)idx != startIdx);
72774
72775 return NULL;
72776}
72777
72778/***********************/
72779/* Interface functions */
72780/***********************/
72781
72782static UA_Node *
72783UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) {
72784 UA_NodeMapEntry *entry = createEntry(nodeClass);
72785 if(!entry)
72786 return NULL;
72787 return &entry->node;
72788}
72789
72790static void
72791UA_NodeMap_deleteNode(void *context, UA_Node *node) {
72792 UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
72793 UA_assert(&entry->node == node);
72794 deleteNodeMapEntry(entry);
72795}
72796
72797static const UA_Node *
72798UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid) {
72799 UA_NodeMap *ns = (UA_NodeMap*)context;
72800 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72801 if(!slot)
72802 return NULL;
72803 ++slot->entry->refCount;
72804 return &slot->entry->node;
72805}
72806
72807static void
72808UA_NodeMap_releaseNode(void *context, const UA_Node *node) {
72809 if (!node)
72810 return;
72811 UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node);
72812 UA_assert(&entry->node == node);
72813 UA_assert(entry->refCount > 0);
72814 --entry->refCount;
72815 cleanupNodeMapEntry(entry);
72816}
72817
72818static UA_StatusCode
72819UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid,
72820 UA_Node **outNode) {
72821 UA_NodeMap *ns = (UA_NodeMap*)context;
72822 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72823 if(!slot)
72824 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72825 UA_NodeMapEntry *entry = slot->entry;
72826 UA_NodeMapEntry *newItem = createEntry(nodeClass: entry->node.head.nodeClass);
72827 if(!newItem)
72828 return UA_STATUSCODE_BADOUTOFMEMORY;
72829 UA_StatusCode retval = UA_Node_copy(src: &entry->node, dst: &newItem->node);
72830 if(retval == UA_STATUSCODE_GOOD) {
72831 newItem->orig = entry; /* Store the pointer to the original */
72832 *outNode = &newItem->node;
72833 } else {
72834 deleteNodeMapEntry(entry: newItem);
72835 }
72836 return retval;
72837}
72838
72839static UA_StatusCode
72840UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) {
72841 UA_NodeMap *ns = (UA_NodeMap*)context;
72842 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid);
72843 if(!slot)
72844 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72845
72846 UA_NodeMapEntry *entry = slot->entry;
72847 slot->entry = UA_NODEMAP_TOMBSTONE;
72848 UA_atomic_sync(); /* Set the tombstone before cleaning up. E.g. if the
72849 * nodestore is accessed from an interrupt. */
72850 entry->deleted = true;
72851 cleanupNodeMapEntry(entry);
72852 --ns->count;
72853 /* Downsize the hashmap if it is very empty */
72854 if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE)
72855 expand(ns); /* Can fail. Just continue with the bigger hashmap. */
72856 return UA_STATUSCODE_GOOD;
72857}
72858
72859/*
72860 * If this function fails in any way, the node parameter is deleted here,
72861 * so the caller function does not need to take care of it anymore
72862 */
72863static UA_StatusCode
72864UA_NodeMap_insertNode(void *context, UA_Node *node,
72865 UA_NodeId *addedNodeId) {
72866 UA_NodeMap *ns = (UA_NodeMap*)context;
72867 if(ns->size * 3 <= ns->count * 4) {
72868 if(expand(ns) != UA_STATUSCODE_GOOD){
72869 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72870 return UA_STATUSCODE_BADINTERNALERROR;
72871 }
72872 }
72873
72874 UA_NodeMapSlot *slot;
72875 if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC &&
72876 node->head.nodeId.identifier.numeric == 0) {
72877 /* Create a random nodeid: Start at least with 50,000 to make sure we
72878 * don not conflict with nodes from the spec. If we find a conflict, we
72879 * just try another identifier until we have tried all possible
72880 * identifiers. Since the size is prime and we don't change the increase
72881 * val, we will reach the starting id again. E.g. adding a nodeset will
72882 * create children while there are still other nodes which need to be
72883 * created. Thus the node ids may collide. */
72884 UA_UInt32 size = ns->size;
72885 UA_UInt64 identifier = mod(h: 50000 + size+1, UA_UINT32_MAX); /* Use 64bit to
72886 * avoid overflow */
72887 UA_UInt32 increase = mod2(h: ns->count+1, size);
72888 UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id
72889 * is a valid 32 bit integer */
72890
72891 do {
72892 node->head.nodeId.identifier.numeric = (UA_UInt32)identifier;
72893 slot = findFreeSlot(ns, nodeid: &node->head.nodeId);
72894 if(slot)
72895 break;
72896 identifier += increase;
72897 if(identifier >= size)
72898 identifier -= size;
72899#if SIZE_MAX <= UA_UINT32_MAX
72900 /* The compressed "immediate" representation of nodes does not
72901 * support the full range on 32bit systems. Generate smaller
72902 * identifiers as they can be stored more compactly. */
72903 if(identifier >= (0x01 << 24))
72904 identifier = identifier % (0x01 << 24);
72905#endif
72906 } while((UA_UInt32)identifier != startId);
72907 } else {
72908 slot = findFreeSlot(ns, nodeid: &node->head.nodeId);
72909 }
72910
72911 if(!slot) {
72912 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72913 return UA_STATUSCODE_BADNODEIDEXISTS;
72914 }
72915
72916 /* Copy the NodeId */
72917 UA_StatusCode retval = UA_STATUSCODE_GOOD;
72918 if(addedNodeId) {
72919 retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId);
72920 if(retval != UA_STATUSCODE_GOOD) {
72921 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72922 return retval;
72923 }
72924 }
72925
72926 /* For new ReferencetypeNodes add to the index map */
72927 if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) {
72928 UA_ReferenceTypeNode *refNode = &node->referenceTypeNode;
72929 if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) {
72930 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72931 return UA_STATUSCODE_BADINTERNALERROR;
72932 }
72933
72934 retval = UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]);
72935 if(retval != UA_STATUSCODE_GOOD) {
72936 deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node));
72937 return UA_STATUSCODE_BADINTERNALERROR;
72938 }
72939
72940 /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */
72941 refNode->referenceTypeIndex = ns->referenceTypeCounter;
72942 refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter);
72943
72944 ns->referenceTypeCounter++;
72945 }
72946
72947 /* Insert the node */
72948 UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
72949 slot->nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId);
72950 UA_atomic_sync(); /* Set the hash first */
72951 slot->entry = newEntry;
72952 ++ns->count;
72953 return retval;
72954}
72955
72956static UA_StatusCode
72957UA_NodeMap_replaceNode(void *context, UA_Node *node) {
72958 UA_NodeMap *ns = (UA_NodeMap*)context;
72959 UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node);
72960
72961 /* Find the node */
72962 UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid: &node->head.nodeId);
72963 if(!slot) {
72964 deleteNodeMapEntry(entry: newEntry);
72965 return UA_STATUSCODE_BADNODEIDUNKNOWN;
72966 }
72967
72968 /* The node was already updated since the copy was made? */
72969 UA_NodeMapEntry *oldEntry = slot->entry;
72970 if(oldEntry != newEntry->orig) {
72971 deleteNodeMapEntry(entry: newEntry);
72972 return UA_STATUSCODE_BADINTERNALERROR;
72973 }
72974
72975 /* Replace the entry */
72976 slot->entry = newEntry;
72977 UA_atomic_sync();
72978 oldEntry->deleted = true;
72979 cleanupNodeMapEntry(entry: oldEntry);
72980 return UA_STATUSCODE_GOOD;
72981}
72982
72983static const UA_NodeId *
72984UA_NodeMap_getReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) {
72985 UA_NodeMap *ns = (UA_NodeMap*)nsCtx;
72986 if(refTypeIndex >= ns->referenceTypeCounter)
72987 return NULL;
72988 return &ns->referenceTypeIds[refTypeIndex];
72989}
72990
72991static void
72992UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor,
72993 void *visitorContext) {
72994 UA_NodeMap *ns = (UA_NodeMap*)context;
72995 for(UA_UInt32 i = 0; i < ns->size; ++i) {
72996 UA_NodeMapSlot *slot = &ns->slots[i];
72997 if(slot->entry > UA_NODEMAP_TOMBSTONE) {
72998 /* The visitor can delete the node. So refcount here. */
72999 slot->entry->refCount++;
73000 visitor(visitorContext, &slot->entry->node);
73001 slot->entry->refCount--;
73002 cleanupNodeMapEntry(entry: slot->entry);
73003 }
73004 }
73005}
73006
73007static void
73008UA_NodeMap_delete(void *context) {
73009 /* Already cleaned up? */
73010 if(!context)
73011 return;
73012
73013 UA_NodeMap *ns = (UA_NodeMap*)context;
73014 UA_UInt32 size = ns->size;
73015 UA_NodeMapSlot *slots = ns->slots;
73016 for(UA_UInt32 i = 0; i < size; ++i) {
73017 if(slots[i].entry > UA_NODEMAP_TOMBSTONE) {
73018 /* On debugging builds, check that all nodes were release */
73019 UA_assert(slots[i].entry->refCount == 0);
73020 /* Delete the node */
73021 deleteNodeMapEntry(entry: slots[i].entry);
73022 }
73023 }
73024 UA_free(ptr: ns->slots);
73025
73026 /* Clean up the ReferenceTypes index array */
73027 for(size_t i = 0; i < ns->referenceTypeCounter; i++)
73028 UA_NodeId_clear(p: &ns->referenceTypeIds[i]);
73029
73030 UA_free(ptr: ns);
73031}
73032
73033UA_StatusCode
73034UA_Nodestore_HashMap(UA_Nodestore *ns) {
73035 /* Allocate and initialize the nodemap */
73036 UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(size: sizeof(UA_NodeMap));
73037 if(!nodemap)
73038 return UA_STATUSCODE_BADOUTOFMEMORY;
73039 nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE);
73040 nodemap->size = primes[nodemap->sizePrimeIndex];
73041 nodemap->count = 0;
73042 nodemap->slots = (UA_NodeMapSlot*)
73043 UA_calloc(nmemb: nodemap->size, size: sizeof(UA_NodeMapSlot));
73044 if(!nodemap->slots) {
73045 UA_free(ptr: nodemap);
73046 return UA_STATUSCODE_BADOUTOFMEMORY;
73047 }
73048
73049 nodemap->referenceTypeCounter = 0;
73050
73051 /* Populate the nodestore */
73052 ns->context = nodemap;
73053 ns->clear = UA_NodeMap_delete;
73054 ns->newNode = UA_NodeMap_newNode;
73055 ns->deleteNode = UA_NodeMap_deleteNode;
73056 ns->getNode = UA_NodeMap_getNode;
73057 ns->releaseNode = UA_NodeMap_releaseNode;
73058 ns->getNodeCopy = UA_NodeMap_getNodeCopy;
73059 ns->insertNode = UA_NodeMap_insertNode;
73060 ns->replaceNode = UA_NodeMap_replaceNode;
73061 ns->removeNode = UA_NodeMap_removeNode;
73062 ns->getReferenceTypeId = UA_NodeMap_getReferenceTypeId;
73063 ns->iterate = UA_NodeMap_iterate;
73064 return UA_STATUSCODE_GOOD;
73065}
73066
73067/**** amalgamated original file "/plugins/ua_config_default.c" ****/
73068
73069/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73070 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73071 *
73072 * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
73073 * Copyright 2017 (c) Julian Grothoff
73074 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
73075 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
73076 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
73077 * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG
73078 * Copyright 2018 (c) Fabian Arndt, Root-Core
73079 * Copyright 2019 (c) Kalycito Infotech Private Limited
73080 * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
73081 * Copyright 2020 (c) Wind River Systems, Inc.
73082 */
73083
73084#ifdef UA_ENABLE_WEBSOCKET_SERVER
73085#endif
73086
73087/* Struct initialization works across ANSI C/C99/C++ if it is done when the
73088 * variable is first declared. Assigning values to existing structs is
73089 * heterogeneous across the three. */
73090static UA_INLINE UA_UInt32Range
73091UA_UINT32RANGE(UA_UInt32 min, UA_UInt32 max) {
73092 UA_UInt32Range range = {min, max};
73093 return range;
73094}
73095
73096static UA_INLINE UA_DurationRange
73097UA_DURATIONRANGE(UA_Duration min, UA_Duration max) {
73098 UA_DurationRange range = {min, max};
73099 return range;
73100}
73101
73102UA_Server *
73103UA_Server_new(void) {
73104 UA_ServerConfig config;
73105 memset(s: &config, c: 0, n: sizeof(UA_ServerConfig));
73106 /* Set a default logger and NodeStore for the initialization */
73107 config.logger = UA_Log_Stdout_;
73108 if(UA_STATUSCODE_GOOD != UA_Nodestore_HashMap(ns: &config.nodestore)) {
73109 return NULL;
73110 }
73111
73112 return UA_Server_newWithConfig(config: &config);
73113}
73114
73115/*******************************/
73116/* Default Connection Settings */
73117/*******************************/
73118
73119const UA_ConnectionConfig UA_ConnectionConfig_default = {
73120 0, /* .protocolVersion */
73121 2 << 16, /* .sendBufferSize, 64k per chunk */
73122 2 << 16, /* .recvBufferSize, 64k per chunk */
73123 2 << 29, /* .localMaxMessageSize, 512 MB */
73124 2 << 29, /* .remoteMaxMessageSize, 512 MB */
73125 2 << 14, /* .localMaxChunkCount, 16k */
73126 2 << 14 /* .remoteMaxChunkCount, 16k */
73127};
73128
73129/***************************/
73130/* Default Server Settings */
73131/***************************/
73132
73133#define MANUFACTURER_NAME "open62541"
73134#define PRODUCT_NAME "open62541 OPC UA Server"
73135#define PRODUCT_URI "http://open62541.org"
73136#define APPLICATION_NAME "open62541-based OPC UA Application"
73137#define APPLICATION_URI "urn:unconfigured:application"
73138#define APPLICATION_URI_SERVER "urn:open62541.server.application"
73139
73140#define STRINGIFY(arg) #arg
73141#define VERSION(MAJOR, MINOR, PATCH, LABEL) \
73142 STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL
73143
73144static UA_StatusCode
73145createEndpoint(UA_ServerConfig *conf, UA_EndpointDescription *endpoint,
73146 const UA_SecurityPolicy *securityPolicy,
73147 UA_MessageSecurityMode securityMode) {
73148 UA_EndpointDescription_init(p: endpoint);
73149
73150 endpoint->securityMode = securityMode;
73151 UA_String_copy(src: &securityPolicy->policyUri, dst: &endpoint->securityPolicyUri);
73152 endpoint->transportProfileUri =
73153 UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary");
73154
73155 /* Add security level value for the corresponding message security mode */
73156 endpoint->securityLevel = (UA_Byte) securityMode;
73157
73158 /* Enable all login mechanisms from the access control plugin */
73159 UA_StatusCode retval = UA_Array_copy(src: conf->accessControl.userTokenPolicies,
73160 size: conf->accessControl.userTokenPoliciesSize,
73161 dst: (void **)&endpoint->userIdentityTokens,
73162 type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
73163 if(retval != UA_STATUSCODE_GOOD){
73164 UA_String_clear(p: &endpoint->securityPolicyUri);
73165 UA_String_clear(p: &endpoint->transportProfileUri);
73166 return retval;
73167 }
73168 endpoint->userIdentityTokensSize = conf->accessControl.userTokenPoliciesSize;
73169
73170 UA_String_copy(src: &securityPolicy->localCertificate, dst: &endpoint->serverCertificate);
73171 UA_ApplicationDescription_copy(src: &conf->applicationDescription, dst: &endpoint->server);
73172
73173 return UA_STATUSCODE_GOOD;
73174}
73175
73176static const size_t usernamePasswordsSize = 2;
73177static UA_UsernamePasswordLogin usernamePasswords[2] = {
73178 {UA_STRING_STATIC("user1"), UA_STRING_STATIC("password")},
73179 {UA_STRING_STATIC("user2"), UA_STRING_STATIC("password1")}};
73180
73181static UA_StatusCode
73182setDefaultConfig(UA_ServerConfig *conf) {
73183 if(!conf)
73184 return UA_STATUSCODE_BADINVALIDARGUMENT;
73185
73186 if(conf->nodestore.context == NULL)
73187 UA_Nodestore_HashMap(ns: &conf->nodestore);
73188
73189 /* --> Start setting the default static config <-- */
73190 /* Allow user to set his own logger */
73191 if(!conf->logger.log)
73192 conf->logger = UA_Log_Stdout_withLevel(minlevel: UA_LOGLEVEL_INFO);
73193
73194 conf->shutdownDelay = 0.0;
73195
73196 /* Server Description */
73197 UA_BuildInfo_clear(p: &conf->buildInfo);
73198 conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI);
73199 conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME);
73200 conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME);
73201 conf->buildInfo.softwareVersion =
73202 UA_STRING_ALLOC(VERSION(UA_OPEN62541_VER_MAJOR, UA_OPEN62541_VER_MINOR,
73203 UA_OPEN62541_VER_PATCH, UA_OPEN62541_VER_LABEL));
73204#ifdef UA_PACK_DEBIAN
73205 conf->buildInfo.buildNumber = UA_STRING_ALLOC("deb");
73206#else
73207 conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__ " " __TIME__);
73208#endif
73209 conf->buildInfo.buildDate = UA_DateTime_now();
73210
73211 UA_ApplicationDescription_clear(p: &conf->applicationDescription);
73212 conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER);
73213 conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI);
73214 conf->applicationDescription.applicationName =
73215 UA_LOCALIZEDTEXT_ALLOC(locale: "en", APPLICATION_NAME);
73216 conf->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER;
73217 /* conf->applicationDescription.gatewayServerUri = UA_STRING_NULL; */
73218 /* conf->applicationDescription.discoveryProfileUri = UA_STRING_NULL; */
73219 /* conf->applicationDescription.discoveryUrlsSize = 0; */
73220 /* conf->applicationDescription.discoveryUrls = NULL; */
73221
73222#ifdef UA_ENABLE_DISCOVERY_MULTICAST
73223 UA_MdnsDiscoveryConfiguration_clear(&conf->mdnsConfig);
73224 conf->mdnsInterfaceIP = UA_STRING_NULL;
73225# if !defined(UA_HAS_GETIFADDR)
73226 conf->mdnsIpAddressList = NULL;
73227 conf->mdnsIpAddressListSize = 0;
73228# endif
73229#endif
73230
73231 /* Custom DataTypes */
73232 /* conf->customDataTypesSize = 0; */
73233 /* conf->customDataTypes = NULL; */
73234
73235 /* Networking */
73236 /* conf->networkLayersSize = 0; */
73237 /* conf->networkLayers = NULL; */
73238 /* conf->customHostname = UA_STRING_NULL; */
73239
73240 /* Endpoints */
73241 /* conf->endpoints = {0, NULL}; */
73242
73243 /* Certificate Verification that accepts every certificate. Can be
73244 * overwritten when the policy is specialized. */
73245 UA_CertificateVerification_AcceptAll(cv: &conf->certificateVerification);
73246
73247 /* * Global Node Lifecycle * */
73248 /* conf->nodeLifecycle.constructor = NULL; */
73249 /* conf->nodeLifecycle.destructor = NULL; */
73250 /* conf->nodeLifecycle.createOptionalChild = NULL; */
73251 /* conf->nodeLifecycle.generateChildNodeId = NULL; */
73252 conf->modellingRulesOnInstances = UA_TRUE;
73253
73254 /* Limits for SecureChannels */
73255 conf->maxSecureChannels = 40;
73256 conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */
73257
73258 /* Limits for Sessions */
73259 conf->maxSessions = 100;
73260 conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */
73261
73262#ifdef UA_ENABLE_SUBSCRIPTIONS
73263 /* Limits for Subscriptions */
73264 conf->publishingIntervalLimits = UA_DURATIONRANGE(min: 100.0, max: 3600.0 * 1000.0);
73265 conf->lifeTimeCountLimits = UA_UINT32RANGE(min: 3, max: 15000);
73266 conf->keepAliveCountLimits = UA_UINT32RANGE(min: 1, max: 100);
73267 conf->maxNotificationsPerPublish = 1000;
73268 conf->enableRetransmissionQueue = true;
73269 conf->maxRetransmissionQueueSize = 0; /* unlimited */
73270# ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS
73271 conf->maxEventsPerNode = 0; /* unlimited */
73272# endif
73273
73274 /* Limits for MonitoredItems */
73275 conf->samplingIntervalLimits = UA_DURATIONRANGE(min: 50.0, max: 24.0 * 3600.0 * 1000.0);
73276 conf->queueSizeLimits = UA_UINT32RANGE(min: 1, max: 100);
73277#endif
73278
73279#ifdef UA_ENABLE_DISCOVERY
73280 conf->discoveryCleanupTimeout = 60 * 60;
73281#endif
73282
73283#ifdef UA_ENABLE_HISTORIZING
73284 /* conf->accessHistoryDataCapability = UA_FALSE; */
73285 /* conf->maxReturnDataValues = 0; */
73286
73287 /* conf->accessHistoryEventsCapability = UA_FALSE; */
73288 /* conf->maxReturnEventValues = 0; */
73289
73290 /* conf->insertDataCapability = UA_FALSE; */
73291 /* conf->insertEventCapability = UA_FALSE; */
73292 /* conf->insertAnnotationsCapability = UA_FALSE; */
73293
73294 /* conf->replaceDataCapability = UA_FALSE; */
73295 /* conf->replaceEventCapability = UA_FALSE; */
73296
73297 /* conf->updateDataCapability = UA_FALSE; */
73298 /* conf->updateEventCapability = UA_FALSE; */
73299
73300 /* conf->deleteRawCapability = UA_FALSE; */
73301 /* conf->deleteEventCapability = UA_FALSE; */
73302 /* conf->deleteAtTimeDataCapability = UA_FALSE; */
73303#endif
73304
73305#if UA_MULTITHREADING >= 100
73306 conf->maxAsyncOperationQueueSize = 0;
73307 conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */
73308#endif
73309
73310 /* --> Finish setting the default static config <-- */
73311
73312 return UA_STATUSCODE_GOOD;
73313}
73314
73315UA_EXPORT UA_StatusCode
73316UA_ServerConfig_setBasics(UA_ServerConfig* conf) {
73317 UA_StatusCode res = setDefaultConfig(conf);
73318 UA_LOG_WARNING(logger: &conf->logger, category: UA_LOGCATEGORY_USERLAND,
73319 msg: "AcceptAll Certificate Verification. "
73320 "Any remote certificate will be accepted.");
73321 return res;
73322}
73323
73324static UA_StatusCode
73325addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber,
73326 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
73327 return UA_ServerConfig_addNetworkLayerTCP(conf, portNumber, sendBufferSize, recvBufferSize);
73328}
73329
73330#ifdef UA_ENABLE_WEBSOCKET_SERVER
73331UA_EXPORT UA_StatusCode
73332UA_ServerConfig_addNetworkLayerWS(UA_ServerConfig *conf, UA_UInt16 portNumber,
73333 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize, const UA_ByteString* certificate, const UA_ByteString* privateKey) {
73334 /* Add a network layer */
73335 UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
73336 UA_realloc(conf->networkLayers,
73337 sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
73338 if(!tmp)
73339 return UA_STATUSCODE_BADOUTOFMEMORY;
73340 conf->networkLayers = tmp;
73341
73342 UA_ConnectionConfig config = UA_ConnectionConfig_default;
73343 if(sendBufferSize > 0)
73344 config.sendBufferSize = sendBufferSize;
73345 if(recvBufferSize > 0)
73346 config.recvBufferSize = recvBufferSize;
73347
73348 conf->networkLayers[conf->networkLayersSize] =
73349 UA_ServerNetworkLayerWS(config, portNumber, certificate, privateKey);
73350 if(!conf->networkLayers[conf->networkLayersSize].handle)
73351 return UA_STATUSCODE_BADOUTOFMEMORY;
73352 conf->networkLayersSize++;
73353
73354 return UA_STATUSCODE_GOOD;
73355}
73356#endif
73357
73358UA_EXPORT UA_StatusCode
73359UA_ServerConfig_addNetworkLayerTCP(UA_ServerConfig *conf, UA_UInt16 portNumber,
73360 UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
73361 /* Add a network layer */
73362 UA_ServerNetworkLayer *tmp = (UA_ServerNetworkLayer *)
73363 UA_realloc(ptr: conf->networkLayers,
73364 size: sizeof(UA_ServerNetworkLayer) * (1 + conf->networkLayersSize));
73365 if(!tmp)
73366 return UA_STATUSCODE_BADOUTOFMEMORY;
73367 conf->networkLayers = tmp;
73368
73369 UA_ConnectionConfig config = UA_ConnectionConfig_default;
73370 if (sendBufferSize > 0)
73371 config.sendBufferSize = sendBufferSize;
73372 if (recvBufferSize > 0)
73373 config.recvBufferSize = recvBufferSize;
73374
73375 conf->networkLayers[conf->networkLayersSize] =
73376 UA_ServerNetworkLayerTCP(config, port: portNumber, maxConnections: 0);
73377 if (!conf->networkLayers[conf->networkLayersSize].handle)
73378 return UA_STATUSCODE_BADOUTOFMEMORY;
73379 conf->networkLayersSize++;
73380
73381 return UA_STATUSCODE_GOOD;
73382}
73383
73384UA_EXPORT UA_StatusCode
73385UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config,
73386 const UA_ByteString *certificate) {
73387 /* Allocate the SecurityPolicies */
73388 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73389 UA_realloc(ptr: config->securityPolicies,
73390 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73391 if(!tmp)
73392 return UA_STATUSCODE_BADOUTOFMEMORY;
73393 config->securityPolicies = tmp;
73394
73395 /* Populate the SecurityPolicies */
73396 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73397 if(certificate)
73398 localCertificate = *certificate;
73399 UA_StatusCode retval =
73400 UA_SecurityPolicy_None(policy: &config->securityPolicies[config->securityPoliciesSize],
73401 localCertificate, logger: &config->logger);
73402 if(retval != UA_STATUSCODE_GOOD) {
73403 if(config->securityPoliciesSize == 0) {
73404 UA_free(ptr: config->securityPolicies);
73405 config->securityPolicies = NULL;
73406 }
73407 return retval;
73408 }
73409
73410 config->securityPoliciesSize++;
73411 return UA_STATUSCODE_GOOD;
73412}
73413
73414UA_EXPORT UA_StatusCode
73415UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri,
73416 UA_MessageSecurityMode securityMode) {
73417 /* Allocate the endpoint */
73418 UA_EndpointDescription *tmp = (UA_EndpointDescription *)
73419 UA_realloc(ptr: config->endpoints,
73420 size: sizeof(UA_EndpointDescription) * (1 + config->endpointsSize));
73421 if(!tmp) {
73422 return UA_STATUSCODE_BADOUTOFMEMORY;
73423 }
73424 config->endpoints = tmp;
73425
73426 /* Lookup the security policy */
73427 const UA_SecurityPolicy *policy = NULL;
73428 for (size_t i = 0; i < config->securityPoliciesSize; ++i) {
73429 if (UA_String_equal(s1: &securityPolicyUri, s2: &config->securityPolicies[i].policyUri)) {
73430 policy = &config->securityPolicies[i];
73431 break;
73432 }
73433 }
73434 if (!policy)
73435 return UA_STATUSCODE_BADINVALIDARGUMENT;
73436
73437 /* Populate the endpoint */
73438 UA_StatusCode retval =
73439 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73440 securityPolicy: policy, securityMode);
73441 if(retval != UA_STATUSCODE_GOOD)
73442 return retval;
73443 config->endpointsSize++;
73444
73445 return UA_STATUSCODE_GOOD;
73446}
73447
73448UA_EXPORT UA_StatusCode
73449UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) {
73450 /* Allocate the endpoints */
73451 UA_EndpointDescription * tmp = (UA_EndpointDescription *)
73452 UA_realloc(ptr: config->endpoints,
73453 size: sizeof(UA_EndpointDescription) *
73454 (2 * config->securityPoliciesSize + config->endpointsSize));
73455 if(!tmp) {
73456 return UA_STATUSCODE_BADOUTOFMEMORY;
73457 }
73458 config->endpoints = tmp;
73459
73460 /* Populate the endpoints */
73461 for(size_t i = 0; i < config->securityPoliciesSize; ++i) {
73462 if(UA_String_equal(s1: &UA_SECURITY_POLICY_NONE_URI, s2: &config->securityPolicies[i].policyUri)) {
73463 UA_StatusCode retval =
73464 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73465 securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_NONE);
73466 if(retval != UA_STATUSCODE_GOOD)
73467 return retval;
73468 config->endpointsSize++;
73469 } else {
73470 UA_StatusCode retval =
73471 createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73472 securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_SIGN);
73473 if(retval != UA_STATUSCODE_GOOD)
73474 return retval;
73475 config->endpointsSize++;
73476
73477 retval = createEndpoint(conf: config, endpoint: &config->endpoints[config->endpointsSize],
73478 securityPolicy: &config->securityPolicies[i],
73479 securityMode: UA_MESSAGESECURITYMODE_SIGNANDENCRYPT);
73480 if(retval != UA_STATUSCODE_GOOD)
73481 return retval;
73482 config->endpointsSize++;
73483 }
73484 }
73485
73486 return UA_STATUSCODE_GOOD;
73487}
73488
73489UA_EXPORT UA_StatusCode
73490UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNumber,
73491 const UA_ByteString *certificate,
73492 UA_UInt32 sendBufferSize,
73493 UA_UInt32 recvBufferSize) {
73494 if(!config)
73495 return UA_STATUSCODE_BADINVALIDARGUMENT;
73496
73497 UA_StatusCode retval = setDefaultConfig(config);
73498 if(retval != UA_STATUSCODE_GOOD) {
73499 UA_ServerConfig_clean(config);
73500 return retval;
73501 }
73502
73503 retval = addDefaultNetworkLayers(conf: config, portNumber, sendBufferSize, recvBufferSize);
73504 if(retval != UA_STATUSCODE_GOOD) {
73505 UA_ServerConfig_clean(config);
73506 return retval;
73507 }
73508
73509 /* Allocate the SecurityPolicies */
73510 retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate);
73511 if(retval != UA_STATUSCODE_GOOD) {
73512 UA_ServerConfig_clean(config);
73513 return retval;
73514 }
73515
73516 /* Initialize the Access Control plugin */
73517 retval = UA_AccessControl_default(config, true, NULL,
73518 userTokenPolicyUri: &config->securityPolicies[config->securityPoliciesSize-1].policyUri,
73519 usernamePasswordLoginSize: usernamePasswordsSize, usernamePasswordLogin: usernamePasswords);
73520 if(retval != UA_STATUSCODE_GOOD) {
73521 UA_ServerConfig_clean(config);
73522 return retval;
73523 }
73524
73525 /* Allocate the endpoint */
73526 retval = UA_ServerConfig_addEndpoint(config, securityPolicyUri: UA_SECURITY_POLICY_NONE_URI,
73527 securityMode: UA_MESSAGESECURITYMODE_NONE);
73528 if(retval != UA_STATUSCODE_GOOD) {
73529 UA_ServerConfig_clean(config);
73530 return retval;
73531 }
73532
73533 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73534 msg: "AcceptAll Certificate Verification. "
73535 "Any remote certificate will be accepted.");
73536
73537 return UA_STATUSCODE_GOOD;
73538}
73539
73540#ifdef UA_ENABLE_ENCRYPTION
73541
73542UA_EXPORT UA_StatusCode
73543UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config,
73544 const UA_ByteString *certificate,
73545 const UA_ByteString *privateKey) {
73546 /* Allocate the SecurityPolicies */
73547 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73548 UA_realloc(ptr: config->securityPolicies,
73549 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73550 if(!tmp)
73551 return UA_STATUSCODE_BADOUTOFMEMORY;
73552 config->securityPolicies = tmp;
73553
73554 /* Populate the SecurityPolicies */
73555 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73556 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73557 if(certificate)
73558 localCertificate = *certificate;
73559 if(privateKey)
73560 localPrivateKey = *privateKey;
73561 UA_StatusCode retval =
73562 UA_SecurityPolicy_Basic128Rsa15(policy: &config->securityPolicies[config->securityPoliciesSize],
73563 localCertificate, localPrivateKey, logger: &config->logger);
73564 if(retval != UA_STATUSCODE_GOOD) {
73565 if(config->securityPoliciesSize == 0) {
73566 UA_free(ptr: config->securityPolicies);
73567 config->securityPolicies = NULL;
73568 }
73569 return retval;
73570 }
73571
73572 config->securityPoliciesSize++;
73573 return UA_STATUSCODE_GOOD;
73574}
73575
73576UA_EXPORT UA_StatusCode
73577UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config,
73578 const UA_ByteString *certificate,
73579 const UA_ByteString *privateKey) {
73580 /* Allocate the SecurityPolicies */
73581 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73582 UA_realloc(ptr: config->securityPolicies,
73583 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73584 if(!tmp)
73585 return UA_STATUSCODE_BADOUTOFMEMORY;
73586 config->securityPolicies = tmp;
73587
73588 /* Populate the SecurityPolicies */
73589 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73590 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73591 if(certificate)
73592 localCertificate = *certificate;
73593 if(privateKey)
73594 localPrivateKey = *privateKey;
73595 UA_StatusCode retval =
73596 UA_SecurityPolicy_Basic256(policy: &config->securityPolicies[config->securityPoliciesSize],
73597 localCertificate, localPrivateKey, logger: &config->logger);
73598 if(retval != UA_STATUSCODE_GOOD) {
73599 if(config->securityPoliciesSize == 0) {
73600 UA_free(ptr: config->securityPolicies);
73601 config->securityPolicies = NULL;
73602 }
73603 return retval;
73604 }
73605
73606 config->securityPoliciesSize++;
73607 return UA_STATUSCODE_GOOD;
73608}
73609
73610UA_EXPORT UA_StatusCode
73611UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config,
73612 const UA_ByteString *certificate,
73613 const UA_ByteString *privateKey) {
73614 /* Allocate the SecurityPolicies */
73615 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73616 UA_realloc(ptr: config->securityPolicies,
73617 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73618 if(!tmp)
73619 return UA_STATUSCODE_BADOUTOFMEMORY;
73620 config->securityPolicies = tmp;
73621
73622 /* Populate the SecurityPolicies */
73623 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73624 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73625 if(certificate)
73626 localCertificate = *certificate;
73627 if(privateKey)
73628 localPrivateKey = *privateKey;
73629 UA_StatusCode retval =
73630 UA_SecurityPolicy_Basic256Sha256(policy: &config->securityPolicies[config->securityPoliciesSize],
73631 localCertificate, localPrivateKey, logger: &config->logger);
73632 if(retval != UA_STATUSCODE_GOOD) {
73633 if(config->securityPoliciesSize == 0) {
73634 UA_free(ptr: config->securityPolicies);
73635 config->securityPolicies = NULL;
73636 }
73637 return retval;
73638 }
73639
73640 config->securityPoliciesSize++;
73641 return UA_STATUSCODE_GOOD;
73642}
73643
73644UA_EXPORT UA_StatusCode
73645UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(UA_ServerConfig *config,
73646 const UA_ByteString *certificate,
73647 const UA_ByteString *privateKey) {
73648 /* Allocate the SecurityPolicies */
73649 UA_SecurityPolicy *tmp = (UA_SecurityPolicy *)
73650 UA_realloc(ptr: config->securityPolicies,
73651 size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize));
73652 if(!tmp)
73653 return UA_STATUSCODE_BADOUTOFMEMORY;
73654 config->securityPolicies = tmp;
73655
73656 /* Populate the SecurityPolicies */
73657 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73658 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73659 if(certificate)
73660 localCertificate = *certificate;
73661 if(privateKey)
73662 localPrivateKey = *privateKey;
73663 UA_StatusCode retval =
73664 UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &config->securityPolicies[config->securityPoliciesSize],
73665 localCertificate, localPrivateKey, logger: &config->logger);
73666 if(retval != UA_STATUSCODE_GOOD) {
73667 if(config->securityPoliciesSize == 0) {
73668 UA_free(ptr: config->securityPolicies);
73669 config->securityPolicies = NULL;
73670 }
73671 return retval;
73672 }
73673
73674 config->securityPoliciesSize++;
73675 return UA_STATUSCODE_GOOD;
73676}
73677
73678/* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */
73679UA_EXPORT UA_StatusCode
73680UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config,
73681 const UA_ByteString *certificate,
73682 const UA_ByteString *privateKey) {
73683 /* Populate the SecurityPolicies */
73684 UA_ByteString localCertificate = UA_BYTESTRING_NULL;
73685 UA_ByteString localPrivateKey = UA_BYTESTRING_NULL;
73686 if(certificate)
73687 localCertificate = *certificate;
73688 if(privateKey)
73689 localPrivateKey = *privateKey;
73690
73691 UA_StatusCode retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate: &localCertificate);
73692 if(retval != UA_STATUSCODE_GOOD) {
73693 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73694 msg: "Could not add SecurityPolicy#None with error code %s",
73695 UA_StatusCode_name(code: retval));
73696 }
73697
73698 retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73699 if(retval != UA_STATUSCODE_GOOD) {
73700 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73701 msg: "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
73702 UA_StatusCode_name(code: retval));
73703 }
73704
73705 retval = UA_ServerConfig_addSecurityPolicyBasic256(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73706 if(retval != UA_STATUSCODE_GOOD) {
73707 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73708 msg: "Could not add SecurityPolicy#Basic256 with error code %s",
73709 UA_StatusCode_name(code: retval));
73710 }
73711
73712 retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73713 if(retval != UA_STATUSCODE_GOOD) {
73714 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73715 msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
73716 UA_StatusCode_name(code: retval));
73717 }
73718
73719 retval = UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(config, certificate: &localCertificate, privateKey: &localPrivateKey);
73720 if(retval != UA_STATUSCODE_GOOD) {
73721 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73722 msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
73723 UA_StatusCode_name(code: retval));
73724 }
73725
73726 return UA_STATUSCODE_GOOD;
73727}
73728
73729UA_EXPORT UA_StatusCode
73730UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf,
73731 UA_UInt16 portNumber,
73732 const UA_ByteString *certificate,
73733 const UA_ByteString *privateKey,
73734 const UA_ByteString *trustList,
73735 size_t trustListSize,
73736 const UA_ByteString *issuerList,
73737 size_t issuerListSize,
73738 const UA_ByteString *revocationList,
73739 size_t revocationListSize) {
73740 UA_StatusCode retval = setDefaultConfig(conf);
73741 if(retval != UA_STATUSCODE_GOOD) {
73742 UA_ServerConfig_clean(config: conf);
73743 return retval;
73744 }
73745
73746 retval = UA_CertificateVerification_Trustlist(cv: &conf->certificateVerification,
73747 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73748 certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize,
73749 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73750 if (retval != UA_STATUSCODE_GOOD)
73751 return retval;
73752
73753 retval = addDefaultNetworkLayers(conf, portNumber, sendBufferSize: 0, recvBufferSize: 0);
73754 if(retval != UA_STATUSCODE_GOOD) {
73755 UA_ServerConfig_clean(config: conf);
73756 return retval;
73757 }
73758
73759 retval = UA_ServerConfig_addAllSecurityPolicies(config: conf, certificate, privateKey);
73760 if(retval != UA_STATUSCODE_GOOD) {
73761 UA_ServerConfig_clean(config: conf);
73762 return retval;
73763 }
73764
73765 UA_CertificateVerification accessControlVerification;
73766 retval = UA_CertificateVerification_Trustlist(cv: &accessControlVerification,
73767 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73768 certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize,
73769 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73770 retval |= UA_AccessControl_default(config: conf, true, verifyX509: &accessControlVerification,
73771 userTokenPolicyUri: &conf->securityPolicies[conf->securityPoliciesSize-1].policyUri,
73772 usernamePasswordLoginSize: usernamePasswordsSize, usernamePasswordLogin: usernamePasswords);
73773 if(retval != UA_STATUSCODE_GOOD) {
73774 UA_ServerConfig_clean(config: conf);
73775 return retval;
73776 }
73777
73778 retval = UA_ServerConfig_addAllEndpoints(config: conf);
73779 if(retval != UA_STATUSCODE_GOOD) {
73780 UA_ServerConfig_clean(config: conf);
73781 return retval;
73782 }
73783
73784 return UA_STATUSCODE_GOOD;
73785}
73786
73787#endif
73788
73789/***************************/
73790/* Default Client Settings */
73791/***************************/
73792
73793UA_Client * UA_Client_new(void) {
73794 UA_ClientConfig config;
73795 memset(s: &config, c: 0, n: sizeof(UA_ClientConfig));
73796 config.logger = UA_Log_Stdout_withLevel(minlevel: UA_LOGLEVEL_INFO);
73797 return UA_Client_newWithConfig(config: &config);
73798}
73799
73800UA_StatusCode
73801UA_ClientConfig_setDefault(UA_ClientConfig *config) {
73802 config->timeout = 5000;
73803 config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */
73804
73805 if(!config->logger.log) {
73806 config->logger = UA_Log_Stdout_withLevel(minlevel: UA_LOGLEVEL_INFO);
73807 }
73808
73809 if (config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) {
73810 UA_Array_delete(p: config->sessionLocaleIds, size: config->sessionLocaleIdsSize, type: &UA_TYPES[UA_TYPES_LOCALEID]);
73811 }
73812 config->sessionLocaleIds = NULL;
73813 config->sessionLocaleIds = 0;
73814
73815 config->localConnectionConfig = UA_ConnectionConfig_default;
73816
73817 /* Certificate Verification that accepts every certificate. Can be
73818 * overwritten when the policy is specialized. */
73819 UA_CertificateVerification_AcceptAll(cv: &config->certificateVerification);
73820 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73821 msg: "AcceptAll Certificate Verification. "
73822 "Any remote certificate will be accepted.");
73823
73824 /* With encryption enabled, the applicationUri needs to match the URI from
73825 * the certificate */
73826 config->clientDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI);
73827 config->clientDescription.applicationType = UA_APPLICATIONTYPE_CLIENT;
73828
73829 if(config->securityPoliciesSize > 0) {
73830 UA_LOG_ERROR(logger: &config->logger, category: UA_LOGCATEGORY_NETWORK,
73831 msg: "Could not initialize a config that already has SecurityPolicies");
73832 return UA_STATUSCODE_BADINTERNALERROR;
73833 }
73834
73835 config->securityPolicies = (UA_SecurityPolicy*)UA_malloc(size: sizeof(UA_SecurityPolicy));
73836 if(!config->securityPolicies)
73837 return UA_STATUSCODE_BADOUTOFMEMORY;
73838 UA_StatusCode retval = UA_SecurityPolicy_None(policy: config->securityPolicies,
73839 localCertificate: UA_BYTESTRING_NULL, logger: &config->logger);
73840 if(retval != UA_STATUSCODE_GOOD) {
73841 UA_free(ptr: config->securityPolicies);
73842 config->securityPolicies = NULL;
73843 return retval;
73844 }
73845 config->securityPoliciesSize = 1;
73846
73847 config->initConnectionFunc = UA_ClientConnectionTCP_init; /* for async client */
73848 config->pollConnectionFunc = UA_ClientConnectionTCP_poll; /* for async connection */
73849
73850 config->customDataTypes = NULL;
73851 config->stateCallback = NULL;
73852 config->connectivityCheckInterval = 0;
73853
73854 config->requestedSessionTimeout = 1200000; /* requestedSessionTimeout */
73855
73856 config->inactivityCallback = NULL;
73857 config->clientContext = NULL;
73858
73859#ifdef UA_ENABLE_SUBSCRIPTIONS
73860 config->outStandingPublishRequests = 10;
73861 config->subscriptionInactivityCallback = NULL;
73862#endif
73863
73864 return UA_STATUSCODE_GOOD;
73865}
73866
73867#ifdef UA_ENABLE_ENCRYPTION
73868UA_StatusCode
73869UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config,
73870 UA_ByteString localCertificate, UA_ByteString privateKey,
73871 const UA_ByteString *trustList, size_t trustListSize,
73872 const UA_ByteString *revocationList, size_t revocationListSize) {
73873 UA_StatusCode retval = UA_ClientConfig_setDefault(config);
73874 if(retval != UA_STATUSCODE_GOOD)
73875 return retval;
73876
73877 retval = UA_CertificateVerification_Trustlist(cv: &config->certificateVerification,
73878 certificateTrustList: trustList, certificateTrustListSize: trustListSize,
73879 NULL, certificateIssuerListSize: 0,
73880 certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize);
73881 if(retval != UA_STATUSCODE_GOOD)
73882 return retval;
73883
73884 /* Populate SecurityPolicies */
73885 UA_SecurityPolicy *sp = (UA_SecurityPolicy*)
73886 UA_realloc(ptr: config->securityPolicies, size: sizeof(UA_SecurityPolicy) * 5);
73887 if(!sp)
73888 return UA_STATUSCODE_BADOUTOFMEMORY;
73889 config->securityPolicies = sp;
73890
73891 retval = UA_SecurityPolicy_Basic128Rsa15(policy: &config->securityPolicies[config->securityPoliciesSize],
73892 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73893 if(retval == UA_STATUSCODE_GOOD) {
73894 ++config->securityPoliciesSize;
73895 } else {
73896 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73897 msg: "Could not add SecurityPolicy#Basic128Rsa15 with error code %s",
73898 UA_StatusCode_name(code: retval));
73899 }
73900
73901 retval = UA_SecurityPolicy_Basic256(policy: &config->securityPolicies[config->securityPoliciesSize],
73902 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73903 if(retval == UA_STATUSCODE_GOOD) {
73904 ++config->securityPoliciesSize;
73905 } else {
73906 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73907 msg: "Could not add SecurityPolicy#Basic256 with error code %s",
73908 UA_StatusCode_name(code: retval));
73909 }
73910
73911 retval = UA_SecurityPolicy_Basic256Sha256(policy: &config->securityPolicies[config->securityPoliciesSize],
73912 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73913 if(retval == UA_STATUSCODE_GOOD) {
73914 ++config->securityPoliciesSize;
73915 } else {
73916 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73917 msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s",
73918 UA_StatusCode_name(code: retval));
73919 }
73920
73921 retval = UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &config->securityPolicies[config->securityPoliciesSize],
73922 localCertificate, localPrivateKey: privateKey, logger: &config->logger);
73923 if(retval == UA_STATUSCODE_GOOD) {
73924 ++config->securityPoliciesSize;
73925 } else {
73926 UA_LOG_WARNING(logger: &config->logger, category: UA_LOGCATEGORY_USERLAND,
73927 msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s",
73928 UA_StatusCode_name(code: retval));
73929 }
73930
73931 if(config->securityPoliciesSize == 0) {
73932 UA_free(ptr: config->securityPolicies);
73933 config->securityPolicies = NULL;
73934 }
73935
73936 return UA_STATUSCODE_GOOD;
73937}
73938#endif
73939
73940/**** amalgamated original file "/plugins/crypto/ua_pki_none.c" ****/
73941
73942/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73943 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73944 *
73945 * Copyright 2020 (c) Julius Pfrommer, Fraunhofer IOSB
73946 */
73947
73948
73949static UA_StatusCode
73950verifyCertificateAllowAll(void *verificationContext,
73951 const UA_ByteString *certificate) {
73952 return UA_STATUSCODE_GOOD;
73953}
73954
73955static UA_StatusCode
73956verifyApplicationURIAllowAll(void *verificationContext,
73957 const UA_ByteString *certificate,
73958 const UA_String *applicationURI) {
73959 return UA_STATUSCODE_GOOD;
73960}
73961
73962static void
73963clearVerifyAllowAll(UA_CertificateVerification *cv) {
73964
73965}
73966
73967void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) {
73968 cv->verifyCertificate = verifyCertificateAllowAll;
73969 cv->verifyApplicationURI = verifyApplicationURIAllowAll;
73970 cv->clear = clearVerifyAllowAll;
73971}
73972
73973/**** amalgamated original file "/plugins/crypto/ua_securitypolicy_none.c" ****/
73974
73975/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
73976 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
73977 *
73978 * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
73979 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
73980 */
73981
73982
73983#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
73984#endif
73985
73986#if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
73987#endif
73988
73989static UA_StatusCode
73990verify_none(void *channelContext,
73991 const UA_ByteString *message,
73992 const UA_ByteString *signature) {
73993 return UA_STATUSCODE_GOOD;
73994}
73995
73996static UA_StatusCode
73997sign_none(void *channelContext, const UA_ByteString *message,
73998 UA_ByteString *signature) {
73999 return UA_STATUSCODE_GOOD;
74000}
74001
74002static size_t
74003length_none(const void *channelContext) {
74004 return 0;
74005}
74006
74007static UA_StatusCode
74008encrypt_none(void *channelContext, UA_ByteString *data) {
74009 return UA_STATUSCODE_GOOD;
74010}
74011
74012static UA_StatusCode
74013decrypt_none(void *channelContext, UA_ByteString *data) {
74014 return UA_STATUSCODE_GOOD;
74015}
74016
74017static UA_StatusCode
74018makeThumbprint_none(const UA_SecurityPolicy *securityPolicy,
74019 const UA_ByteString *certificate,
74020 UA_ByteString *thumbprint) {
74021 return UA_STATUSCODE_GOOD;
74022}
74023
74024static UA_StatusCode
74025compareThumbprint_none(const UA_SecurityPolicy *securityPolicy,
74026 const UA_ByteString *certificateThumbprint) {
74027 return UA_STATUSCODE_GOOD;
74028}
74029
74030static UA_StatusCode
74031generateKey_none(void *policyContext, const UA_ByteString *secret,
74032 const UA_ByteString *seed, UA_ByteString *out) {
74033 return UA_STATUSCODE_GOOD;
74034}
74035
74036/* Use the non-cryptographic RNG to set the nonce */
74037static UA_StatusCode
74038generateNonce_none(void *policyContext, UA_ByteString *out) {
74039 if(out == NULL)
74040 return UA_STATUSCODE_BADINTERNALERROR;
74041
74042 if(out->length == 0)
74043 return UA_STATUSCODE_GOOD;
74044
74045 /* Fill blocks of four byte */
74046 size_t i = 0;
74047 while(i + 3 < out->length) {
74048 UA_UInt32 randNumber = UA_UInt32_random();
74049 memcpy(dest: &out->data[i], src: &randNumber, n: 4);
74050 i = i+4;
74051 }
74052
74053 /* Fill the remaining byte */
74054 UA_UInt32 randNumber = UA_UInt32_random();
74055 memcpy(dest: &out->data[i], src: &randNumber, n: out->length % 4);
74056
74057 return UA_STATUSCODE_GOOD;
74058}
74059
74060static UA_StatusCode
74061newContext_none(const UA_SecurityPolicy *securityPolicy,
74062 const UA_ByteString *remoteCertificate,
74063 void **channelContext) {
74064 return UA_STATUSCODE_GOOD;
74065}
74066
74067static void
74068deleteContext_none(void *channelContext) {
74069}
74070
74071static UA_StatusCode
74072setContextValue_none(void *channelContext,
74073 const UA_ByteString *key) {
74074 return UA_STATUSCODE_GOOD;
74075}
74076
74077static UA_StatusCode
74078compareCertificate_none(const void *channelContext,
74079 const UA_ByteString *certificate) {
74080 return UA_STATUSCODE_GOOD;
74081}
74082
74083static UA_StatusCode
74084updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy,
74085 const UA_ByteString newCertificate,
74086 const UA_ByteString newPrivateKey) {
74087 UA_ByteString_clear(p: &policy->localCertificate);
74088 UA_ByteString_copy(src: &newCertificate, dst: &policy->localCertificate);
74089 return UA_STATUSCODE_GOOD;
74090}
74091
74092
74093static void
74094policy_clear_none(UA_SecurityPolicy *policy) {
74095 UA_ByteString_clear(p: &policy->localCertificate);
74096}
74097
74098UA_StatusCode
74099UA_SecurityPolicy_None(UA_SecurityPolicy *policy, const UA_ByteString localCertificate,
74100 const UA_Logger *logger) {
74101 policy->policyContext = (void *)(uintptr_t)logger;
74102 policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None");
74103 policy->logger = logger;
74104
74105#ifdef UA_ENABLE_ENCRYPTION_MBEDTLS
74106 UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate);
74107#elif defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL)
74108 UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate);
74109#else
74110 UA_ByteString_copy(&localCertificate, &policy->localCertificate);
74111#endif
74112
74113 policy->symmetricModule.generateKey = generateKey_none;
74114 policy->symmetricModule.generateNonce = generateNonce_none;
74115
74116 UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm =
74117 &policy->symmetricModule.cryptoModule.signatureAlgorithm;
74118 sym_signatureAlgorithm->uri = UA_STRING_NULL;
74119 sym_signatureAlgorithm->verify = verify_none;
74120 sym_signatureAlgorithm->sign = sign_none;
74121 sym_signatureAlgorithm->getLocalSignatureSize = length_none;
74122 sym_signatureAlgorithm->getRemoteSignatureSize = length_none;
74123 sym_signatureAlgorithm->getLocalKeyLength = length_none;
74124 sym_signatureAlgorithm->getRemoteKeyLength = length_none;
74125
74126 UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm =
74127 &policy->symmetricModule.cryptoModule.encryptionAlgorithm;
74128 sym_encryptionAlgorithm->uri = UA_STRING_NULL;
74129 sym_encryptionAlgorithm->encrypt = encrypt_none;
74130 sym_encryptionAlgorithm->decrypt = decrypt_none;
74131 sym_encryptionAlgorithm->getLocalKeyLength = length_none;
74132 sym_encryptionAlgorithm->getRemoteKeyLength = length_none;
74133 sym_encryptionAlgorithm->getRemoteBlockSize = length_none;
74134 sym_encryptionAlgorithm->getRemotePlainTextBlockSize = length_none;
74135 policy->symmetricModule.secureChannelNonceLength = 0;
74136
74137 policy->asymmetricModule.makeCertificateThumbprint = makeThumbprint_none;
74138 policy->asymmetricModule.compareCertificateThumbprint = compareThumbprint_none;
74139
74140 // This only works for none since symmetric and asymmetric crypto modules do the same i.e. nothing
74141 policy->asymmetricModule.cryptoModule = policy->symmetricModule.cryptoModule;
74142
74143 // Use the same signing algorithm as for asymmetric signing
74144 policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm;
74145
74146 policy->channelModule.newContext = newContext_none;
74147 policy->channelModule.deleteContext = deleteContext_none;
74148 policy->channelModule.setLocalSymEncryptingKey = setContextValue_none;
74149 policy->channelModule.setLocalSymSigningKey = setContextValue_none;
74150 policy->channelModule.setLocalSymIv = setContextValue_none;
74151 policy->channelModule.setRemoteSymEncryptingKey = setContextValue_none;
74152 policy->channelModule.setRemoteSymSigningKey = setContextValue_none;
74153 policy->channelModule.setRemoteSymIv = setContextValue_none;
74154 policy->channelModule.compareCertificate = compareCertificate_none;
74155 policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none;
74156 policy->clear = policy_clear_none;
74157
74158 return UA_STATUSCODE_GOOD;
74159}
74160
74161/**** amalgamated original file "/plugins/ua_log_syslog.c" ****/
74162
74163/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
74164 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
74165 *
74166 * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
74167 */
74168
74169
74170#if defined(__linux__) || defined(__unix__)
74171
74172#include <syslog.h>
74173
74174const char *syslogLevelNames[6] = {"trace", "debug", "info",
74175 "warn", "error", "fatal"};
74176const char *syslogCategoryNames[7] = {"network", "channel", "session", "server",
74177 "client", "userland", "securitypolicy"};
74178
74179#ifdef __clang__
74180__attribute__((__format__(__printf__, 4 , 0)))
74181#endif
74182static void
74183UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category,
74184 const char *msg, va_list args) {
74185 /* Assume that context is casted to UA_LogLevel */
74186 if(context != NULL && (UA_LogLevel)(uintptr_t)context > level)
74187 return;
74188
74189 int priority = LOG_INFO;
74190 switch(level) {
74191 case UA_LOGLEVEL_DEBUG:
74192 priority = LOG_DEBUG;
74193 break;
74194 case UA_LOGLEVEL_INFO:
74195 priority = LOG_INFO;
74196 break;
74197 case UA_LOGLEVEL_WARNING:
74198 priority = LOG_WARNING;
74199 break;
74200 case UA_LOGLEVEL_ERROR:
74201 priority = LOG_ERR;
74202 break;
74203 case UA_LOGLEVEL_FATAL:
74204 priority = LOG_CRIT;
74205 break;
74206 case UA_LOGLEVEL_TRACE:
74207 default:
74208 return;
74209 }
74210
74211#define LOGBUFSIZE 512
74212 char logbuf[LOGBUFSIZE];
74213 int pos = snprintf(s: logbuf, LOGBUFSIZE, format: "[%s/%s] ",
74214 syslogLevelNames[level], syslogCategoryNames[category]);
74215 if(pos < 0) {
74216 syslog(LOG_WARNING, fmt: "Log message too long for syslog");
74217 return;
74218 }
74219 pos = vsnprintf(s: &logbuf[pos], LOGBUFSIZE - (size_t)pos, format: msg, arg: args);
74220 if(pos < 0) {
74221 syslog(LOG_WARNING, fmt: "Log message too long for syslog");
74222 return;
74223 }
74224
74225 syslog(pri: priority, fmt: "%s", logbuf);
74226}
74227
74228static void
74229UA_Log_Syslog_clear(void *logContext) {
74230 /* closelog is optional. We don't use it as several loggers might be
74231 * instantiated in parallel. */
74232 /* closelog(); */
74233}
74234
74235UA_Logger
74236UA_Log_Syslog(void) {
74237 return UA_Log_Syslog_withLevel(minlevel: UA_LOGLEVEL_TRACE);
74238}
74239
74240UA_Logger
74241UA_Log_Syslog_withLevel(UA_LogLevel minlevel) {
74242 UA_Logger logger = {UA_Log_Syslog_log, (void*)minlevel, UA_Log_Syslog_clear};
74243 return logger;
74244}
74245
74246#endif
74247
74248/**** amalgamated original file "/plugins/historydata/ua_history_data_backend_memory.c" ****/
74249
74250/* This Source Code Form is subject to the terms of the Mozilla Public
74251 * License, v. 2.0. If a copy of the MPL was not distributed with this
74252 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
74253 *
74254 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
74255 */
74256
74257
74258#include <limits.h>
74259#include <string.h>
74260
74261typedef struct {
74262 UA_DateTime timestamp;
74263 UA_DataValue value;
74264} UA_DataValueMemoryStoreItem;
74265
74266static void
74267UA_DataValueMemoryStoreItem_clear(UA_DataValueMemoryStoreItem* item) {
74268 UA_DateTime_clear(p: &item->timestamp);
74269 UA_DataValue_clear(p: &item->value);
74270}
74271
74272typedef struct {
74273 UA_NodeId nodeId;
74274 UA_DataValueMemoryStoreItem **dataStore;
74275 size_t storeEnd;
74276 size_t storeSize;
74277} UA_NodeIdStoreContextItem_backend_memory;
74278
74279static void
74280UA_NodeIdStoreContextItem_clear(UA_NodeIdStoreContextItem_backend_memory* item) {
74281 UA_NodeId_clear(p: &item->nodeId);
74282 for (size_t i = 0; i < item->storeEnd; ++i) {
74283 UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]);
74284 UA_free(ptr: item->dataStore[i]);
74285 }
74286 UA_free(ptr: item->dataStore);
74287}
74288
74289typedef struct {
74290 UA_NodeIdStoreContextItem_backend_memory *dataStore;
74291 size_t storeEnd;
74292 size_t storeSize;
74293 size_t initialStoreSize;
74294} UA_MemoryStoreContext;
74295
74296static void
74297UA_MemoryStoreContext_clear(UA_MemoryStoreContext* ctx) {
74298 for (size_t i = 0; i < ctx->storeEnd; ++i) {
74299 UA_NodeIdStoreContextItem_clear(item: &ctx->dataStore[i]);
74300 }
74301 UA_free(ptr: ctx->dataStore);
74302 memset(s: ctx, c: 0, n: sizeof(UA_MemoryStoreContext));
74303}
74304
74305static UA_NodeIdStoreContextItem_backend_memory *
74306getNewNodeIdContext_backend_memory(UA_MemoryStoreContext* context,
74307 UA_Server *server,
74308 const UA_NodeId *nodeId) {
74309 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)context;
74310 if (ctx->storeEnd >= ctx->storeSize) {
74311 size_t newStoreSize = ctx->storeSize * 2;
74312 if (newStoreSize == 0)
74313 return NULL;
74314 ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_backend_memory)));
74315 if (!ctx->dataStore) {
74316 ctx->storeSize = 0;
74317 return NULL;
74318 }
74319 ctx->storeSize = newStoreSize;
74320 }
74321 UA_NodeIdStoreContextItem_backend_memory *item = &ctx->dataStore[ctx->storeEnd];
74322 UA_NodeId_copy(src: nodeId, dst: &item->nodeId);
74323 UA_DataValueMemoryStoreItem ** store = (UA_DataValueMemoryStoreItem **)UA_calloc(nmemb: ctx->initialStoreSize, size: sizeof(UA_DataValueMemoryStoreItem*));
74324 if (!store) {
74325 UA_NodeIdStoreContextItem_clear(item);
74326 return NULL;
74327 }
74328 item->dataStore = store;
74329 item->storeSize = ctx->initialStoreSize;
74330 item->storeEnd = 0;
74331 ++ctx->storeEnd;
74332 return item;
74333}
74334
74335static UA_NodeIdStoreContextItem_backend_memory *
74336getNodeIdStoreContextItem_backend_memory(UA_MemoryStoreContext* context,
74337 UA_Server *server,
74338 const UA_NodeId *nodeId)
74339{
74340 for (size_t i = 0; i < context->storeEnd; ++i) {
74341 if (UA_NodeId_equal(n1: nodeId, n2: &context->dataStore[i].nodeId)) {
74342 return &context->dataStore[i];
74343 }
74344 }
74345 return getNewNodeIdContext_backend_memory(context, server, nodeId);
74346}
74347
74348static UA_Boolean
74349binarySearch_backend_memory(const UA_NodeIdStoreContextItem_backend_memory* item,
74350 const UA_DateTime timestamp,
74351 size_t *index) {
74352 if (item->storeEnd == 0) {
74353 *index = item->storeEnd;
74354 return false;
74355 }
74356 size_t min = 0;
74357 size_t max = item->storeEnd - 1;
74358 while (min <= max) {
74359 *index = (min + max) / 2;
74360 if (item->dataStore[*index]->timestamp == timestamp) {
74361 return true;
74362 } else if (item->dataStore[*index]->timestamp < timestamp) {
74363 if (*index == item->storeEnd - 1) {
74364 *index = item->storeEnd;
74365 return false;
74366 }
74367 min = *index + 1;
74368 } else {
74369 if (*index == 0)
74370 return false;
74371 max = *index - 1;
74372 }
74373 }
74374 *index = min;
74375 return false;
74376
74377}
74378
74379static size_t
74380resultSize_backend_memory(UA_Server *server,
74381 void *context,
74382 const UA_NodeId *sessionId,
74383 void *sessionContext,
74384 const UA_NodeId * nodeId,
74385 size_t startIndex,
74386 size_t endIndex) {
74387 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74388 if (item->storeEnd == 0
74389 || startIndex == item->storeEnd
74390 || endIndex == item->storeEnd)
74391 return 0;
74392 return endIndex - startIndex + 1;
74393}
74394
74395static size_t
74396getDateTimeMatch_backend_memory(UA_Server *server,
74397 void *context,
74398 const UA_NodeId *sessionId,
74399 void *sessionContext,
74400 const UA_NodeId * nodeId,
74401 const UA_DateTime timestamp,
74402 const MatchStrategy strategy) {
74403 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74404 size_t current;
74405 UA_Boolean retval = binarySearch_backend_memory(item, timestamp, index: &current);
74406
74407 if ((strategy == MATCH_EQUAL
74408 || strategy == MATCH_EQUAL_OR_AFTER
74409 || strategy == MATCH_EQUAL_OR_BEFORE)
74410 && retval)
74411 return current;
74412 switch (strategy) {
74413 case MATCH_AFTER:
74414 if (retval)
74415 return current+1;
74416 return current;
74417 case MATCH_EQUAL_OR_AFTER:
74418 return current;
74419 case MATCH_EQUAL_OR_BEFORE:
74420 // retval == true aka "equal" is handled before
74421 // Fall through if !retval
74422 case MATCH_BEFORE:
74423 if (current > 0)
74424 return current-1;
74425 else
74426 return item->storeEnd;
74427 default:
74428 break;
74429 }
74430 return item->storeEnd;
74431}
74432
74433
74434static UA_StatusCode
74435serverSetHistoryData_backend_memory(UA_Server *server,
74436 void *context,
74437 const UA_NodeId *sessionId,
74438 void *sessionContext,
74439 const UA_NodeId * nodeId,
74440 UA_Boolean historizing,
74441 const UA_DataValue *value)
74442{
74443 UA_NodeIdStoreContextItem_backend_memory *item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74444
74445 if (item->storeEnd >= item->storeSize) {
74446 size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2;
74447 item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*)));
74448 if (!item->dataStore) {
74449 item->storeSize = 0;
74450 return UA_STATUSCODE_BADOUTOFMEMORY;
74451 }
74452 item->storeSize = newStoreSize;
74453 }
74454 UA_DateTime timestamp = 0;
74455 if (value->hasSourceTimestamp) {
74456 timestamp = value->sourceTimestamp;
74457 } else if (value->hasServerTimestamp) {
74458 timestamp = value->serverTimestamp;
74459 } else {
74460 timestamp = UA_DateTime_now();
74461 }
74462 UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem));
74463 newItem->timestamp = timestamp;
74464 UA_DataValue_copy(src: value, dst: &newItem->value);
74465 size_t index = getDateTimeMatch_backend_memory(server,
74466 context,
74467 NULL,
74468 NULL,
74469 nodeId,
74470 timestamp,
74471 strategy: MATCH_EQUAL_OR_AFTER);
74472 if (item->storeEnd > 0 && index < item->storeEnd) {
74473 memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index));
74474 }
74475 item->dataStore[index] = newItem;
74476 ++item->storeEnd;
74477 return UA_STATUSCODE_GOOD;
74478}
74479
74480static void
74481UA_MemoryStoreContext_delete(UA_MemoryStoreContext* ctx) {
74482 UA_MemoryStoreContext_clear(ctx);
74483 UA_free(ptr: ctx);
74484}
74485
74486static size_t
74487getEnd_backend_memory(UA_Server *server,
74488 void *context,
74489 const UA_NodeId *sessionId,
74490 void *sessionContext,
74491 const UA_NodeId * nodeId) {
74492 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74493 return item->storeEnd;
74494}
74495
74496static size_t
74497lastIndex_backend_memory(UA_Server *server,
74498 void *context,
74499 const UA_NodeId *sessionId,
74500 void *sessionContext,
74501 const UA_NodeId * nodeId) {
74502 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74503 if (item->storeEnd == 0)
74504 return 0;
74505 return item->storeEnd - 1;
74506}
74507
74508static size_t
74509firstIndex_backend_memory(UA_Server *server,
74510 void *context,
74511 const UA_NodeId *sessionId,
74512 void *sessionContext,
74513 const UA_NodeId * nodeId) {
74514 return 0;
74515}
74516
74517static UA_Boolean
74518boundSupported_backend_memory(UA_Server *server,
74519 void *context,
74520 const UA_NodeId *sessionId,
74521 void *sessionContext,
74522 const UA_NodeId * nodeId) {
74523 return true;
74524}
74525
74526static UA_Boolean
74527timestampsToReturnSupported_backend_memory(UA_Server *server,
74528 void *context,
74529 const UA_NodeId *sessionId,
74530 void *sessionContext,
74531 const UA_NodeId *nodeId,
74532 const UA_TimestampsToReturn timestampsToReturn) {
74533 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74534 if (item->storeEnd == 0) {
74535 return true;
74536 }
74537 if (timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER
74538 || timestampsToReturn == UA_TIMESTAMPSTORETURN_INVALID
74539 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER
74540 && !item->dataStore[0]->value.hasServerTimestamp)
74541 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SOURCE
74542 && !item->dataStore[0]->value.hasSourceTimestamp)
74543 || (timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH
74544 && !(item->dataStore[0]->value.hasSourceTimestamp
74545 && item->dataStore[0]->value.hasServerTimestamp))) {
74546 return false;
74547 }
74548 return true;
74549}
74550
74551static const UA_DataValue*
74552getDataValue_backend_memory(UA_Server *server,
74553 void *context,
74554 const UA_NodeId *sessionId,
74555 void *sessionContext,
74556 const UA_NodeId * nodeId, size_t index) {
74557 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74558 return &item->dataStore[index]->value;
74559}
74560
74561static UA_StatusCode
74562UA_DataValue_backend_copyRange(const UA_DataValue *src, UA_DataValue *dst,
74563 const UA_NumericRange range)
74564{
74565 memcpy(dest: dst, src: src, n: sizeof(UA_DataValue));
74566 if (src->hasValue)
74567 return UA_Variant_copyRange(src: &src->value, dst: &dst->value, range);
74568 return UA_STATUSCODE_BADDATAUNAVAILABLE;
74569}
74570
74571static UA_StatusCode
74572copyDataValues_backend_memory(UA_Server *server,
74573 void *context,
74574 const UA_NodeId *sessionId,
74575 void *sessionContext,
74576 const UA_NodeId * nodeId,
74577 size_t startIndex,
74578 size_t endIndex,
74579 UA_Boolean reverse,
74580 size_t maxValues,
74581 UA_NumericRange range,
74582 UA_Boolean releaseContinuationPoints,
74583 const UA_ByteString *continuationPoint,
74584 UA_ByteString *outContinuationPoint,
74585 size_t * providedValues,
74586 UA_DataValue * values)
74587{
74588 size_t skip = 0;
74589 if (continuationPoint->length > 0) {
74590 if (continuationPoint->length == sizeof(size_t)) {
74591 skip = *((size_t*)(continuationPoint->data));
74592 } else {
74593 return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
74594 }
74595 }
74596 const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId);
74597 size_t index = startIndex;
74598 size_t counter = 0;
74599 size_t skipedValues = 0;
74600 if (reverse) {
74601 while (index >= endIndex && index < item->storeEnd && counter < maxValues) {
74602 if (skipedValues++ >= skip) {
74603 if (range.dimensionsSize > 0) {
74604 UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range);
74605 } else {
74606 UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]);
74607 }
74608 ++counter;
74609 }
74610 --index;
74611 }
74612 } else {
74613 while (index <= endIndex && counter < maxValues) {
74614 if (skipedValues++ >= skip) {
74615 if (range.dimensionsSize > 0) {
74616 UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range);
74617 } else {
74618 UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]);
74619 }
74620 ++counter;
74621 }
74622 ++index;
74623 }
74624 }
74625
74626 if (providedValues)
74627 *providedValues = counter;
74628
74629 if ((!reverse && (endIndex-startIndex-skip+1) > counter) || (reverse && (startIndex-endIndex-skip+1) > counter)) {
74630 outContinuationPoint->length = sizeof(size_t);
74631 size_t t = sizeof(size_t);
74632 outContinuationPoint->data = (UA_Byte*)UA_malloc(size: t);
74633 *((size_t*)(outContinuationPoint->data)) = skip + counter;
74634 }
74635
74636 return UA_STATUSCODE_GOOD;
74637}
74638
74639static UA_StatusCode
74640insertDataValue_backend_memory(UA_Server *server,
74641 void *hdbContext,
74642 const UA_NodeId *sessionId,
74643 void *sessionContext,
74644 const UA_NodeId *nodeId,
74645 const UA_DataValue *value)
74646{
74647 if (!value->hasSourceTimestamp && !value->hasServerTimestamp)
74648 return UA_STATUSCODE_BADINVALIDTIMESTAMP;
74649 const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp;
74650 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74651
74652 size_t index = getDateTimeMatch_backend_memory(server,
74653 context: hdbContext,
74654 sessionId,
74655 sessionContext,
74656 nodeId,
74657 timestamp,
74658 strategy: MATCH_EQUAL_OR_AFTER);
74659 if (item->storeEnd != index && item->dataStore[index]->timestamp == timestamp)
74660 return UA_STATUSCODE_BADENTRYEXISTS;
74661
74662 if (item->storeEnd >= item->storeSize) {
74663 size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2;
74664 item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*)));
74665 if (!item->dataStore) {
74666 item->storeSize = 0;
74667 return UA_STATUSCODE_BADOUTOFMEMORY;
74668 }
74669 item->storeSize = newStoreSize;
74670 }
74671 UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem));
74672 newItem->timestamp = timestamp;
74673 UA_DataValue_copy(src: value, dst: &newItem->value);
74674 if (item->storeEnd > 0 && index < item->storeEnd) {
74675 memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index));
74676 }
74677 item->dataStore[index] = newItem;
74678 ++item->storeEnd;
74679 return UA_STATUSCODE_GOOD;
74680}
74681
74682static UA_StatusCode
74683replaceDataValue_backend_memory(UA_Server *server,
74684 void *hdbContext,
74685 const UA_NodeId *sessionId,
74686 void *sessionContext,
74687 const UA_NodeId *nodeId,
74688 const UA_DataValue *value)
74689{
74690 if (!value->hasSourceTimestamp && !value->hasServerTimestamp)
74691 return UA_STATUSCODE_BADINVALIDTIMESTAMP;
74692 const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp;
74693 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74694
74695 size_t index = getDateTimeMatch_backend_memory(server,
74696 context: hdbContext,
74697 sessionId,
74698 sessionContext,
74699 nodeId,
74700 timestamp,
74701 strategy: MATCH_EQUAL);
74702 if (index == item->storeEnd)
74703 return UA_STATUSCODE_BADNOENTRYEXISTS;
74704 UA_DataValue_clear(p: &item->dataStore[index]->value);
74705 UA_DataValue_copy(src: value, dst: &item->dataStore[index]->value);
74706 return UA_STATUSCODE_GOOD;
74707}
74708
74709static UA_StatusCode
74710updateDataValue_backend_memory(UA_Server *server,
74711 void *hdbContext,
74712 const UA_NodeId *sessionId,
74713 void *sessionContext,
74714 const UA_NodeId *nodeId,
74715 const UA_DataValue *value)
74716{
74717 // we first try to replace, because it is cheap
74718 UA_StatusCode ret = replaceDataValue_backend_memory(server,
74719 hdbContext,
74720 sessionId,
74721 sessionContext,
74722 nodeId,
74723 value);
74724 if (ret == UA_STATUSCODE_GOOD)
74725 return UA_STATUSCODE_GOODENTRYREPLACED;
74726
74727 ret = insertDataValue_backend_memory(server,
74728 hdbContext,
74729 sessionId,
74730 sessionContext,
74731 nodeId,
74732 value);
74733 if (ret == UA_STATUSCODE_GOOD)
74734 return UA_STATUSCODE_GOODENTRYINSERTED;
74735
74736 return ret;
74737}
74738
74739static UA_StatusCode
74740removeDataValue_backend_memory(UA_Server *server,
74741 void *hdbContext,
74742 const UA_NodeId *sessionId,
74743 void *sessionContext,
74744 const UA_NodeId *nodeId,
74745 UA_DateTime startTimestamp,
74746 UA_DateTime endTimestamp)
74747{
74748 UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId);
74749 size_t storeEnd = item->storeEnd;
74750 // The first index which will be deleted
74751 size_t index1;
74752 // the first index which is not deleted
74753 size_t index2;
74754 if (startTimestamp > endTimestamp) {
74755 return UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED;
74756 }
74757 if (startTimestamp == endTimestamp) {
74758 index1 = getDateTimeMatch_backend_memory(server,
74759 context: hdbContext,
74760 sessionId,
74761 sessionContext,
74762 nodeId,
74763 timestamp: startTimestamp,
74764 strategy: MATCH_EQUAL);
74765 if (index1 == storeEnd)
74766 return UA_STATUSCODE_BADNODATA;
74767 index2 = index1 + 1;
74768 } else {
74769 index1 = getDateTimeMatch_backend_memory(server,
74770 context: hdbContext,
74771 sessionId,
74772 sessionContext,
74773 nodeId,
74774 timestamp: startTimestamp,
74775 strategy: MATCH_EQUAL_OR_AFTER);
74776 index2 = getDateTimeMatch_backend_memory(server,
74777 context: hdbContext,
74778 sessionId,
74779 sessionContext,
74780 nodeId,
74781 timestamp: endTimestamp,
74782 strategy: MATCH_BEFORE);
74783 if (index2 == storeEnd || index1 == storeEnd || index1 > index2 )
74784 return UA_STATUSCODE_BADNODATA;
74785 ++index2;
74786 }
74787#ifndef __clang_analyzer__
74788 for (size_t i = index1; i < index2; ++i) {
74789 UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]);
74790 UA_free(ptr: item->dataStore[i]);
74791 }
74792 memmove(dest: &item->dataStore[index1], src: &item->dataStore[index2], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index2));
74793 item->storeEnd -= index2 - index1;
74794#else
74795 (void)index1;
74796 (void)index2;
74797#endif
74798 return UA_STATUSCODE_GOOD;
74799}
74800
74801static void
74802deleteMembers_backend_memory(UA_HistoryDataBackend *backend)
74803{
74804 if (backend == NULL || backend->context == NULL)
74805 return;
74806 UA_MemoryStoreContext_clear(ctx: (UA_MemoryStoreContext*)backend->context);
74807 UA_free(ptr: backend->context);
74808}
74809
74810
74811
74812UA_HistoryDataBackend
74813UA_HistoryDataBackend_Memory(size_t initialNodeIdStoreSize, size_t initialDataStoreSize) {
74814 if (initialNodeIdStoreSize == 0)
74815 initialNodeIdStoreSize = 1;
74816 if (initialDataStoreSize == 0)
74817 initialDataStoreSize = 1;
74818 UA_HistoryDataBackend result;
74819 memset(s: &result, c: 0, n: sizeof(UA_HistoryDataBackend));
74820 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext *)UA_calloc(nmemb: 1, size: sizeof(UA_MemoryStoreContext));
74821 if (!ctx)
74822 return result;
74823 ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_backend_memory));
74824 ctx->initialStoreSize = initialDataStoreSize;
74825 ctx->storeSize = initialNodeIdStoreSize;
74826 ctx->storeEnd = 0;
74827 result.serverSetHistoryData = &serverSetHistoryData_backend_memory;
74828 result.resultSize = &resultSize_backend_memory;
74829 result.getEnd = &getEnd_backend_memory;
74830 result.lastIndex = &lastIndex_backend_memory;
74831 result.firstIndex = &firstIndex_backend_memory;
74832 result.getDateTimeMatch = &getDateTimeMatch_backend_memory;
74833 result.copyDataValues = &copyDataValues_backend_memory;
74834 result.getDataValue = &getDataValue_backend_memory;
74835 result.boundSupported = &boundSupported_backend_memory;
74836 result.timestampsToReturnSupported = &timestampsToReturnSupported_backend_memory;
74837 result.insertDataValue = &insertDataValue_backend_memory;
74838 result.updateDataValue = &updateDataValue_backend_memory;
74839 result.replaceDataValue = &replaceDataValue_backend_memory;
74840 result.removeDataValue = &removeDataValue_backend_memory;
74841 result.deleteMembers = &deleteMembers_backend_memory;
74842 result.getHistoryData = NULL;
74843 result.context = ctx;
74844 return result;
74845}
74846
74847void
74848UA_HistoryDataBackend_Memory_clear(UA_HistoryDataBackend *backend)
74849{
74850 UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)backend->context;
74851 UA_MemoryStoreContext_delete(ctx);
74852 memset(s: backend, c: 0, n: sizeof(UA_HistoryDataBackend));
74853}
74854
74855/**** amalgamated original file "/plugins/historydata/ua_history_data_gathering_default.c" ****/
74856
74857/* This Source Code Form is subject to the terms of the Mozilla Public
74858 * License, v. 2.0. If a copy of the MPL was not distributed with this
74859 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
74860 *
74861 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
74862 */
74863
74864
74865#include <string.h>
74866
74867typedef struct {
74868 UA_NodeId nodeId;
74869 UA_HistorizingNodeIdSettings setting;
74870 UA_MonitoredItemCreateResult monitoredResult;
74871} UA_NodeIdStoreContextItem_gathering_default;
74872
74873typedef struct {
74874 UA_NodeIdStoreContextItem_gathering_default *dataStore;
74875 size_t storeEnd;
74876 size_t storeSize;
74877} UA_NodeIdStoreContext;
74878
74879static void
74880dataChangeCallback_gathering_default(UA_Server *server,
74881 UA_UInt32 monitoredItemId,
74882 void *monitoredItemContext,
74883 const UA_NodeId *nodeId,
74884 void *nodeContext,
74885 UA_UInt32 attributeId,
74886 const UA_DataValue *value)
74887{
74888 UA_NodeIdStoreContextItem_gathering_default *context = (UA_NodeIdStoreContextItem_gathering_default*)monitoredItemContext;
74889 context->setting.historizingBackend.serverSetHistoryData(server,
74890 context->setting.historizingBackend.context,
74891 NULL,
74892 NULL,
74893 nodeId,
74894 UA_TRUE,
74895 value);
74896}
74897
74898static UA_NodeIdStoreContextItem_gathering_default*
74899getNodeIdStoreContextItem_gathering_default(UA_NodeIdStoreContext *context,
74900 const UA_NodeId *nodeId)
74901{
74902 for (size_t i = 0; i < context->storeEnd; ++i) {
74903 if (UA_NodeId_equal(n1: &context->dataStore[i].nodeId, n2: nodeId)) {
74904 return &context->dataStore[i];
74905 }
74906 }
74907 return NULL;
74908}
74909
74910static UA_StatusCode
74911startPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
74912{
74913 UA_MonitoredItemCreateRequest monitorRequest =
74914 UA_MonitoredItemCreateRequest_default(nodeId: item->nodeId);
74915 monitorRequest.requestedParameters.samplingInterval = (double)item->setting.pollingInterval;
74916 monitorRequest.monitoringMode = UA_MONITORINGMODE_REPORTING;
74917 item->monitoredResult =
74918 UA_Server_createDataChangeMonitoredItem(server,
74919 timestampsToReturn: UA_TIMESTAMPSTORETURN_BOTH,
74920 item: monitorRequest,
74921 monitoredItemContext: item,
74922 callback: &dataChangeCallback_gathering_default);
74923 return item->monitoredResult.statusCode;
74924}
74925
74926static UA_StatusCode
74927stopPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item)
74928{
74929 UA_StatusCode retval = UA_Server_deleteMonitoredItem(server, monitoredItemId: item->monitoredResult.monitoredItemId);
74930 UA_MonitoredItemCreateResult_init(p: &item->monitoredResult);
74931 return retval;
74932}
74933
74934static UA_StatusCode
74935stopPoll_gathering_default(UA_Server *server,
74936 void *context,
74937 const UA_NodeId *nodeId)
74938{
74939 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
74940 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74941 if (!item) {
74942 return UA_STATUSCODE_BADNODEIDUNKNOWN;
74943 }
74944 if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
74945 return UA_STATUSCODE_BADNODEIDINVALID;
74946 if (item->monitoredResult.monitoredItemId == 0)
74947 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
74948 return stopPoll(server, item);
74949}
74950
74951static UA_StatusCode
74952startPoll_gathering_default(UA_Server *server,
74953 void *context,
74954 const UA_NodeId *nodeId)
74955{
74956 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context;
74957 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
74958 if (!item) {
74959 return UA_STATUSCODE_BADNODEIDUNKNOWN;
74960 }
74961 if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL)
74962 return UA_STATUSCODE_BADNODEIDINVALID;
74963 if (item->monitoredResult.monitoredItemId > 0)
74964 return UA_STATUSCODE_BADMONITOREDITEMIDINVALID;
74965 return startPoll(server, item);
74966}
74967
74968static UA_StatusCode
74969registerNodeId_gathering_default(UA_Server *server,
74970 void *context,
74971 const UA_NodeId *nodeId,
74972 const UA_HistorizingNodeIdSettings setting)
74973{
74974 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
74975 if (getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId)) {
74976 return UA_STATUSCODE_BADNODEIDEXISTS;
74977 }
74978 if (ctx->storeEnd >= ctx->storeSize) {
74979 size_t newStoreSize = ctx->storeSize * 2;
74980 ctx->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_gathering_default)));
74981 if (!ctx->dataStore) {
74982 ctx->storeSize = 0;
74983 return UA_STATUSCODE_BADOUTOFMEMORY;
74984 }
74985 memset(s: &ctx->dataStore[ctx->storeSize], c: 0, n: (newStoreSize - ctx->storeSize) * sizeof(UA_NodeIdStoreContextItem_gathering_default));
74986 ctx->storeSize = newStoreSize;
74987 }
74988 UA_NodeId_copy(src: nodeId, dst: &ctx->dataStore[ctx->storeEnd].nodeId);
74989 size_t current = ctx->storeEnd;
74990 ctx->dataStore[current].setting = setting;
74991 ++ctx->storeEnd;
74992 return UA_STATUSCODE_GOOD;
74993}
74994
74995static const UA_HistorizingNodeIdSettings*
74996getHistorizingSetting_gathering_default(UA_Server *server,
74997 void *context,
74998 const UA_NodeId *nodeId)
74999{
75000 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
75001 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
75002 if (item) {
75003 return &item->setting;
75004 }
75005 return NULL;
75006}
75007
75008static void
75009deleteMembers_gathering_default(UA_HistoryDataGathering *gathering)
75010{
75011 if (gathering == NULL || gathering->context == NULL)
75012 return;
75013 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)gathering->context;
75014 for (size_t i = 0; i < ctx->storeEnd; ++i) {
75015 UA_NodeId_clear(p: &ctx->dataStore[i].nodeId);
75016 // There is still a monitored item present for this gathering
75017 // You need to remove it with UA_Server_deleteMonitoredItem
75018 UA_assert(ctx->dataStore[i].monitoredResult.monitoredItemId == 0);
75019 }
75020 UA_free(ptr: ctx->dataStore);
75021 UA_free(ptr: gathering->context);
75022}
75023
75024static UA_Boolean
75025updateNodeIdSetting_gathering_default(UA_Server *server,
75026 void *context,
75027 const UA_NodeId *nodeId,
75028 const UA_HistorizingNodeIdSettings setting)
75029{
75030 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
75031 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
75032 if (!item) {
75033 return false;
75034 }
75035 stopPoll_gathering_default(server, context, nodeId);
75036 item->setting = setting;
75037 return true;
75038}
75039
75040static void
75041setValue_gathering_default(UA_Server *server,
75042 void *context,
75043 const UA_NodeId *sessionId,
75044 void *sessionContext,
75045 const UA_NodeId *nodeId,
75046 UA_Boolean historizing,
75047 const UA_DataValue *value)
75048{
75049 UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context;
75050 UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId);
75051 if (!item) {
75052 return;
75053 }
75054 if (item->setting.historizingUpdateStrategy == UA_HISTORIZINGUPDATESTRATEGY_VALUESET) {
75055 item->setting.historizingBackend.serverSetHistoryData(server,
75056 item->setting.historizingBackend.context,
75057 sessionId,
75058 sessionContext,
75059 nodeId,
75060 historizing,
75061 value);
75062 }
75063}
75064
75065UA_HistoryDataGathering
75066UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize)
75067{
75068 UA_HistoryDataGathering gathering;
75069 memset(s: &gathering, c: 0, n: sizeof(UA_HistoryDataGathering));
75070 gathering.setValue = &setValue_gathering_default;
75071 gathering.getHistorizingSetting = &getHistorizingSetting_gathering_default;
75072 gathering.registerNodeId = &registerNodeId_gathering_default;
75073 gathering.startPoll = &startPoll_gathering_default;
75074 gathering.stopPoll = &stopPoll_gathering_default;
75075 gathering.deleteMembers = &deleteMembers_gathering_default;
75076 gathering.updateNodeIdSetting = &updateNodeIdSetting_gathering_default;
75077 UA_NodeIdStoreContext *context = (UA_NodeIdStoreContext*)UA_calloc(nmemb: 1, size: sizeof(UA_NodeIdStoreContext));
75078 context->storeEnd = 0;
75079 context->storeSize = initialNodeIdStoreSize;
75080 context->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_gathering_default));
75081 gathering.context = context;
75082 return gathering;
75083}
75084
75085/**** amalgamated original file "/plugins/historydata/ua_history_database_default.c" ****/
75086
75087/* This Source Code Form is subject to the terms of the Mozilla Public
75088 * License, v. 2.0. If a copy of the MPL was not distributed with this
75089 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
75090 *
75091 * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler)
75092 */
75093
75094
75095#include <limits.h>
75096
75097typedef struct {
75098 UA_HistoryDataGathering gathering;
75099} UA_HistoryDatabaseContext_default;
75100
75101static size_t
75102getResultSize_service_default(const UA_HistoryDataBackend* backend,
75103 UA_Server *server,
75104 const UA_NodeId *sessionId,
75105 void* sessionContext,
75106 const UA_NodeId *nodeId,
75107 UA_DateTime start,
75108 UA_DateTime end,
75109 UA_UInt32 numValuesPerNode,
75110 UA_Boolean returnBounds,
75111 size_t *startIndex,
75112 size_t *endIndex,
75113 UA_Boolean *addFirst,
75114 UA_Boolean *addLast,
75115 UA_Boolean *reverse)
75116{
75117 size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId);
75118 size_t firstIndex = backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId);
75119 size_t lastIndex = backend->lastIndex(server, backend->context, sessionId, sessionContext, nodeId);
75120 *startIndex = storeEnd;
75121 *endIndex = storeEnd;
75122 *addFirst = false;
75123 *addLast = false;
75124 if (end == LLONG_MIN) {
75125 *reverse = false;
75126 } else if (start == LLONG_MIN) {
75127 *reverse = true;
75128 } else {
75129 *reverse = end < start;
75130 }
75131 UA_Boolean equal = start == end;
75132 size_t size = 0;
75133 if (lastIndex != storeEnd) {
75134 if (equal) {
75135 if (returnBounds) {
75136 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
75137 if (*startIndex == storeEnd) {
75138 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
75139 *addFirst = true;
75140 }
75141 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
75142 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
75143 } else {
75144 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL);
75145 *endIndex = *startIndex;
75146 if (*startIndex == storeEnd)
75147 size = 0;
75148 else
75149 size = 1;
75150 }
75151 } else if (start == LLONG_MIN) {
75152 *endIndex = firstIndex;
75153 if (returnBounds) {
75154 *addLast = true;
75155 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER);
75156 if (*startIndex == storeEnd) {
75157 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
75158 *addFirst = true;
75159 }
75160 } else {
75161 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
75162 }
75163 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex);
75164 } else if (end == LLONG_MIN) {
75165 *endIndex = lastIndex;
75166 if (returnBounds) {
75167 *addLast = true;
75168 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
75169 if (*startIndex == storeEnd) {
75170 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
75171 *addFirst = true;
75172 }
75173 } else {
75174 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
75175 }
75176 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
75177 } else if (*reverse) {
75178 if (returnBounds) {
75179 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
75180 if (*startIndex == storeEnd) {
75181 *addFirst = true;
75182 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_BEFORE);
75183 }
75184 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE);
75185 if (*endIndex == storeEnd) {
75186 *addLast = true;
75187 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER);
75188 }
75189 } else {
75190 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
75191 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER);
75192 }
75193 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex);
75194 } else {
75195 if (returnBounds) {
75196 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE);
75197 if (*startIndex == storeEnd) {
75198 *addFirst = true;
75199 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER);
75200 }
75201 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER);
75202 if (*endIndex == storeEnd) {
75203 *addLast = true;
75204 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE);
75205 }
75206 } else {
75207 *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER);
75208 *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE);
75209 }
75210 size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex);
75211 }
75212 } else if (returnBounds) {
75213 *addLast = true;
75214 *addFirst = true;
75215 }
75216
75217 if (*addLast)
75218 ++size;
75219 if (*addFirst)
75220 ++size;
75221
75222 if (numValuesPerNode > 0 && size > numValuesPerNode) {
75223 size = numValuesPerNode;
75224 *addLast = false;
75225 }
75226 return size;
75227}
75228
75229static UA_StatusCode
75230getHistoryData_service_default(const UA_HistoryDataBackend* backend,
75231 const UA_DateTime start,
75232 const UA_DateTime end,
75233 UA_Server *server,
75234 const UA_NodeId *sessionId,
75235 void *sessionContext,
75236 const UA_NodeId* nodeId,
75237 size_t maxSize,
75238 UA_UInt32 numValuesPerNode,
75239 UA_Boolean returnBounds,
75240 UA_TimestampsToReturn timestampsToReturn,
75241 UA_NumericRange range,
75242 UA_Boolean releaseContinuationPoints,
75243 const UA_ByteString *continuationPoint,
75244 UA_ByteString *outContinuationPoint,
75245 size_t *resultSize,
75246 UA_DataValue ** result)
75247{
75248 size_t skip = 0;
75249 UA_ByteString backendContinuationPoint;
75250 UA_ByteString_init(p: &backendContinuationPoint);
75251 if (continuationPoint->length > 0) {
75252 if (continuationPoint->length >= sizeof(size_t)) {
75253 skip = *((size_t*)(continuationPoint->data));
75254 if (continuationPoint->length > 0) {
75255 backendContinuationPoint.length = continuationPoint->length - sizeof(size_t);
75256 backendContinuationPoint.data = continuationPoint->data + sizeof(size_t);
75257 }
75258 } else {
75259 return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID;
75260 }
75261 }
75262
75263 size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId);
75264 size_t startIndex;
75265 size_t endIndex;
75266 UA_Boolean addFirst;
75267 UA_Boolean addLast;
75268 UA_Boolean reverse;
75269 size_t _resultSize = getResultSize_service_default(backend,
75270 server,
75271 sessionId,
75272 sessionContext,
75273 nodeId,
75274 start,
75275 end,
75276 numValuesPerNode: numValuesPerNode == 0 ? 0 : numValuesPerNode + (UA_UInt32)skip,
75277 returnBounds,
75278 startIndex: &startIndex,
75279 endIndex: &endIndex,
75280 addFirst: &addFirst,
75281 addLast: &addLast,
75282 reverse: &reverse);
75283 *resultSize = _resultSize - skip;
75284 if (*resultSize > maxSize) {
75285 *resultSize = maxSize;
75286 }
75287 UA_DataValue *outResult= (UA_DataValue*)UA_Array_new(size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]);
75288 if (!outResult) {
75289 *resultSize = 0;
75290 return UA_STATUSCODE_BADOUTOFMEMORY;
75291 }
75292 *result = outResult;
75293
75294 size_t counter = 0;
75295 if (addFirst) {
75296 if (skip == 0) {
75297 outResult[counter].hasStatus = true;
75298 outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND;
75299 outResult[counter].hasSourceTimestamp = true;
75300 if (start == LLONG_MIN) {
75301 outResult[counter].sourceTimestamp = end;
75302 } else {
75303 outResult[counter].sourceTimestamp = start;
75304 }
75305 ++counter;
75306 }
75307 }
75308 UA_ByteString backendOutContinuationPoint;
75309 UA_ByteString_init(p: &backendOutContinuationPoint);
75310 if (endIndex != storeEnd && startIndex != storeEnd) {
75311 size_t retval = 0;
75312
75313 size_t valueSize = *resultSize - counter;
75314 if (valueSize + skip > _resultSize - addFirst - addLast) {
75315 if (skip == 0) {
75316 valueSize = _resultSize - addFirst - addLast;
75317 } else {
75318 valueSize = _resultSize - skip - addLast;
75319 }
75320
75321 }
75322
75323 UA_StatusCode ret = UA_STATUSCODE_GOOD;
75324 if (valueSize > 0)
75325 ret = backend->copyDataValues(server,
75326 backend->context,
75327 sessionId,
75328 sessionContext,
75329 nodeId,
75330 startIndex,
75331 endIndex,
75332 reverse,
75333 valueSize,
75334 range,
75335 releaseContinuationPoints,
75336 &backendContinuationPoint,
75337 &backendOutContinuationPoint,
75338 &retval,
75339 &outResult[counter]);
75340 if (ret != UA_STATUSCODE_GOOD) {
75341 UA_Array_delete(p: outResult, size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]);
75342 *result = NULL;
75343 *resultSize = 0;
75344 return ret;
75345 }
75346 counter += retval;
75347 }
75348 if (addLast && counter < *resultSize) {
75349 outResult[counter].hasStatus = true;
75350 outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND;
75351 outResult[counter].hasSourceTimestamp = true;
75352 if (start == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) {
75353 outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp - UA_DATETIME_SEC;
75354 } else if (end == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) {
75355 outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp + UA_DATETIME_SEC;
75356 } else {
75357 outResult[counter].sourceTimestamp = end;
75358 }
75359 }
75360 // there are more values
75361 if (skip + *resultSize < _resultSize
75362 // there are not more values for this request, but there are more values in database
75363 || (backendOutContinuationPoint.length > 0
75364 && numValuesPerNode != 0)
75365 // we deliver just one value which is a FIRST/LAST value
75366 || (skip == 0
75367 && addFirst == true
75368 && *resultSize == 1)) {
75369 if(UA_ByteString_allocBuffer(bs: outContinuationPoint, length: backendOutContinuationPoint.length + sizeof(size_t))
75370 != UA_STATUSCODE_GOOD) {
75371 return UA_STATUSCODE_BADOUTOFMEMORY;
75372 }
75373 *((size_t*)(outContinuationPoint->data)) = skip + *resultSize;
75374 if(backendOutContinuationPoint.length > 0)
75375 memcpy(dest: outContinuationPoint->data + sizeof(size_t), src: backendOutContinuationPoint.data, n: backendOutContinuationPoint.length);
75376 }
75377 UA_ByteString_clear(p: &backendOutContinuationPoint);
75378 return UA_STATUSCODE_GOOD;
75379}
75380
75381static void
75382updateData_service_default(UA_Server *server,
75383 void *hdbContext,
75384 const UA_NodeId *sessionId,
75385 void *sessionContext,
75386 const UA_RequestHeader *requestHeader,
75387 const UA_UpdateDataDetails *details,
75388 UA_HistoryUpdateResult *result)
75389{
75390 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext;
75391 UA_Byte accessLevel = 0;
75392 UA_Server_readAccessLevel(server,
75393 nodeId: details->nodeId,
75394 outAccessLevel: &accessLevel);
75395 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) {
75396 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75397 return;
75398 }
75399
75400 UA_Boolean historizing = false;
75401 UA_Server_readHistorizing(server,
75402 nodeId: details->nodeId,
75403 outHistorizing: &historizing);
75404 if (!historizing) {
75405 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75406 return;
75407 }
75408 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75409 server,
75410 ctx->gathering.context,
75411 &details->nodeId);
75412
75413 if (!setting) {
75414 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75415 return;
75416 }
75417
75418 UA_ServerConfig *config = UA_Server_getConfig(server);
75419 result->operationResultsSize = details->updateValuesSize;
75420 result->operationResults = (UA_StatusCode*)UA_Array_new(size: result->operationResultsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]);
75421 for (size_t i = 0; i < details->updateValuesSize; ++i) {
75422 if (config->accessControl.allowHistoryUpdateUpdateData &&
75423 !config->accessControl.allowHistoryUpdateUpdateData(server, &config->accessControl, sessionId, sessionContext,
75424 &details->nodeId, details->performInsertReplace,
75425 &details->updateValues[i])) {
75426 result->operationResults[i] = UA_STATUSCODE_BADUSERACCESSDENIED;
75427 continue;
75428 }
75429 switch (details->performInsertReplace) {
75430 case UA_PERFORMUPDATETYPE_INSERT:
75431 if (!setting->historizingBackend.insertDataValue) {
75432 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75433 continue;
75434 }
75435 result->operationResults[i]
75436 = setting->historizingBackend.insertDataValue(server,
75437 setting->historizingBackend.context,
75438 sessionId,
75439 sessionContext,
75440 &details->nodeId,
75441 &details->updateValues[i]);
75442 continue;
75443 case UA_PERFORMUPDATETYPE_REPLACE:
75444 if (!setting->historizingBackend.replaceDataValue) {
75445 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75446 continue;
75447 }
75448 result->operationResults[i]
75449 = setting->historizingBackend.replaceDataValue(server,
75450 setting->historizingBackend.context,
75451 sessionId,
75452 sessionContext,
75453 &details->nodeId,
75454 &details->updateValues[i]);
75455 continue;
75456 case UA_PERFORMUPDATETYPE_UPDATE:
75457 if (!setting->historizingBackend.updateDataValue) {
75458 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75459 continue;
75460 }
75461 result->operationResults[i]
75462 = setting->historizingBackend.updateDataValue(server,
75463 setting->historizingBackend.context,
75464 sessionId,
75465 sessionContext,
75466 &details->nodeId,
75467 &details->updateValues[i]);
75468 continue;
75469 default:
75470 result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75471 continue;
75472 }
75473 }
75474}
75475
75476
75477static void
75478deleteRawModified_service_default(UA_Server *server,
75479 void *hdbContext,
75480 const UA_NodeId *sessionId,
75481 void *sessionContext,
75482 const UA_RequestHeader *requestHeader,
75483 const UA_DeleteRawModifiedDetails *details,
75484 UA_HistoryUpdateResult *result)
75485{
75486 if (details->isDeleteModified) {
75487 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75488 return;
75489 }
75490 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext;
75491 UA_Byte accessLevel = 0;
75492 UA_Server_readAccessLevel(server,
75493 nodeId: details->nodeId,
75494 outAccessLevel: &accessLevel);
75495 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) {
75496 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75497 return;
75498 }
75499
75500 UA_Boolean historizing = false;
75501 UA_Server_readHistorizing(server,
75502 nodeId: details->nodeId,
75503 outHistorizing: &historizing);
75504 if (!historizing) {
75505 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75506 return;
75507 }
75508 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75509 server,
75510 ctx->gathering.context,
75511 &details->nodeId);
75512
75513 if (!setting) {
75514 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75515 return;
75516 }
75517 if (!setting->historizingBackend.removeDataValue) {
75518 result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED;
75519 return;
75520 }
75521
75522 UA_ServerConfig *config = UA_Server_getConfig(server);
75523 if (config->accessControl.allowHistoryUpdateDeleteRawModified &&
75524 !config->accessControl.allowHistoryUpdateDeleteRawModified(server,
75525 &config->accessControl, sessionId, sessionContext, &details->nodeId,
75526 details->startTime, details->endTime, details->isDeleteModified)) {
75527 result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75528 return;
75529 }
75530
75531 result->statusCode
75532 = setting->historizingBackend.removeDataValue(server,
75533 setting->historizingBackend.context,
75534 sessionId,
75535 sessionContext,
75536 &details->nodeId,
75537 details->startTime,
75538 details->endTime);
75539}
75540
75541static void
75542readRaw_service_default(UA_Server *server,
75543 void *context,
75544 const UA_NodeId *sessionId,
75545 void *sessionContext,
75546 const UA_RequestHeader *requestHeader,
75547 const UA_ReadRawModifiedDetails *historyReadDetails,
75548 UA_TimestampsToReturn timestampsToReturn,
75549 UA_Boolean releaseContinuationPoints,
75550 size_t nodesToReadSize,
75551 const UA_HistoryReadValueId *nodesToRead,
75552 UA_HistoryReadResponse *response,
75553 UA_HistoryData * const * const historyData)
75554{
75555 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context;
75556 for (size_t i = 0; i < nodesToReadSize; ++i) {
75557 UA_Byte accessLevel = 0;
75558 UA_Server_readAccessLevel(server,
75559 nodeId: nodesToRead[i].nodeId,
75560 outAccessLevel: &accessLevel);
75561 if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYREAD)) {
75562 response->results[i].statusCode = UA_STATUSCODE_BADUSERACCESSDENIED;
75563 continue;
75564 }
75565
75566 UA_Boolean historizing = false;
75567 UA_Server_readHistorizing(server,
75568 nodeId: nodesToRead[i].nodeId,
75569 outHistorizing: &historizing);
75570 if (!historizing) {
75571 response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75572 continue;
75573 }
75574
75575 const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting(
75576 server,
75577 ctx->gathering.context,
75578 &nodesToRead[i].nodeId);
75579
75580 if (!setting) {
75581 response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID;
75582 continue;
75583 }
75584
75585 if (historyReadDetails->returnBounds && !setting->historizingBackend.boundSupported(
75586 server,
75587 setting->historizingBackend.context,
75588 sessionId,
75589 sessionContext,
75590 &nodesToRead[i].nodeId)) {
75591 response->results[i].statusCode = UA_STATUSCODE_BADBOUNDNOTSUPPORTED;
75592 continue;
75593 }
75594
75595 if (!setting->historizingBackend.timestampsToReturnSupported(
75596 server,
75597 setting->historizingBackend.context,
75598 sessionId,
75599 sessionContext,
75600 &nodesToRead[i].nodeId,
75601 timestampsToReturn)) {
75602 response->results[i].statusCode = UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED;
75603 continue;
75604 }
75605
75606 UA_NumericRange range;
75607 range.dimensionsSize = 0;
75608 range.dimensions = NULL;
75609 if (nodesToRead[i].indexRange.length > 0) {
75610 UA_StatusCode rangeParseResult = UA_NumericRange_parse(range: &range, str: nodesToRead[i].indexRange);
75611 if (rangeParseResult != UA_STATUSCODE_GOOD) {
75612 response->results[i].statusCode = rangeParseResult;
75613 continue;
75614 }
75615 }
75616
75617 UA_StatusCode getHistoryDataStatusCode;
75618 if (setting->historizingBackend.getHistoryData) {
75619 getHistoryDataStatusCode = setting->historizingBackend.getHistoryData(
75620 server,
75621 sessionId,
75622 sessionContext,
75623 &setting->historizingBackend,
75624 historyReadDetails->startTime,
75625 historyReadDetails->endTime,
75626 &nodesToRead[i].nodeId,
75627 setting->maxHistoryDataResponseSize,
75628 historyReadDetails->numValuesPerNode,
75629 historyReadDetails->returnBounds,
75630 timestampsToReturn,
75631 range,
75632 releaseContinuationPoints,
75633 &nodesToRead[i].continuationPoint,
75634 &response->results[i].continuationPoint,
75635 historyData[i]);
75636 } else {
75637 getHistoryDataStatusCode = getHistoryData_service_default(
75638 backend: &setting->historizingBackend,
75639 start: historyReadDetails->startTime,
75640 end: historyReadDetails->endTime,
75641 server,
75642 sessionId,
75643 sessionContext,
75644 nodeId: &nodesToRead[i].nodeId,
75645 maxSize: setting->maxHistoryDataResponseSize,
75646 numValuesPerNode: historyReadDetails->numValuesPerNode,
75647 returnBounds: historyReadDetails->returnBounds,
75648 timestampsToReturn,
75649 range,
75650 releaseContinuationPoints,
75651 continuationPoint: &nodesToRead[i].continuationPoint,
75652 outContinuationPoint: &response->results[i].continuationPoint,
75653 resultSize: &historyData[i]->dataValuesSize,
75654 result: &historyData[i]->dataValues);
75655 }
75656 if (getHistoryDataStatusCode != UA_STATUSCODE_GOOD) {
75657 response->results[i].statusCode = getHistoryDataStatusCode;
75658 continue;
75659 }
75660 }
75661 response->responseHeader.serviceResult = UA_STATUSCODE_GOOD;
75662 return;
75663}
75664
75665static void
75666setValue_service_default(UA_Server *server,
75667 void *context,
75668 const UA_NodeId *sessionId,
75669 void *sessionContext,
75670 const UA_NodeId *nodeId,
75671 UA_Boolean historizing,
75672 const UA_DataValue *value)
75673{
75674 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context;
75675 if (ctx->gathering.setValue)
75676 ctx->gathering.setValue(server,
75677 ctx->gathering.context,
75678 sessionId,
75679 sessionContext,
75680 nodeId,
75681 historizing,
75682 value);
75683}
75684
75685static void
75686clear_service_default(UA_HistoryDatabase *hdb)
75687{
75688 if (hdb == NULL || hdb->context == NULL)
75689 return;
75690 UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdb->context;
75691 ctx->gathering.deleteMembers(&ctx->gathering);
75692 UA_free(ptr: ctx);
75693}
75694
75695UA_HistoryDatabase
75696UA_HistoryDatabase_default(UA_HistoryDataGathering gathering)
75697{
75698 UA_HistoryDatabase hdb;
75699 memset(s: &hdb, c: 0, n: sizeof(UA_HistoryDatabase));
75700 UA_HistoryDatabaseContext_default *context =
75701 (UA_HistoryDatabaseContext_default*)
75702 UA_calloc(nmemb: 1, size: sizeof(UA_HistoryDatabaseContext_default));
75703 context->gathering = gathering;
75704 hdb.context = context;
75705 hdb.readRaw = &readRaw_service_default;
75706 hdb.setValue = &setValue_service_default;
75707 hdb.updateData = &updateData_service_default;
75708 hdb.deleteRawModified = &deleteRawModified_service_default;
75709 hdb.clear = clear_service_default;
75710 return hdb;
75711}
75712
75713/**** amalgamated original file "/arch/posix/ua_clock.c" ****/
75714
75715/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75716 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75717 *
75718 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
75719 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
75720 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
75721 */
75722
75723#ifdef UA_ARCHITECTURE_POSIX
75724
75725
75726#include <time.h>
75727#include <sys/time.h>
75728
75729#if defined(__APPLE__) || defined(__MACH__)
75730# include <mach/clock.h>
75731# include <mach/mach.h>
75732#endif
75733
75734UA_DateTime UA_DateTime_now(void) {
75735 struct timeval tv;
75736 gettimeofday(tv: &tv, NULL);
75737 return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH;
75738}
75739
75740/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
75741UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
75742 time_t gmt, rawtime = time(NULL);
75743 struct tm *ptm;
75744 struct tm gbuf;
75745 ptm = gmtime_r(timer: &rawtime, tp: &gbuf);
75746 // Request that mktime() looksup dst in timezone database
75747 ptm->tm_isdst = -1;
75748 gmt = mktime(tp: ptm);
75749 return (UA_Int64) (difftime(time1: rawtime, time0: gmt) * UA_DATETIME_SEC);
75750}
75751
75752UA_DateTime UA_DateTime_nowMonotonic(void) {
75753#if defined(__APPLE__) || defined(__MACH__)
75754 /* OS X does not have clock_gettime, use clock_get_time */
75755 clock_serv_t cclock;
75756 mach_timespec_t mts;
75757 host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
75758 clock_get_time(cclock, &mts);
75759 mach_port_deallocate(mach_task_self(), cclock);
75760 return (mts.tv_sec * UA_DATETIME_SEC) + (mts.tv_nsec / 100);
75761#elif !defined(CLOCK_MONOTONIC_RAW)
75762 struct timespec ts;
75763 clock_gettime(CLOCK_MONOTONIC, &ts);
75764 return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
75765#else
75766 struct timespec ts;
75767 clock_gettime(CLOCK_MONOTONIC_RAW, tp: &ts);
75768 return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
75769#endif
75770}
75771
75772#endif /* UA_ARCHITECTURE_POSIX */
75773
75774/**** amalgamated original file "/arch/posix/ua_architecture_functions.c" ****/
75775
75776/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75777 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75778 *
75779 * Copyright 2018 (c) Jose Cabral, fortiss GmbH
75780 */
75781
75782#ifdef UA_ARCHITECTURE_POSIX
75783
75784
75785/* Global malloc singletons */
75786#ifdef UA_ENABLE_MALLOC_SINGLETON
75787UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
75788UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
75789UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
75790UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
75791#endif
75792
75793unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
75794 int opts = fcntl(fd: sockfd, F_GETFL);
75795 if(opts < 0 || fcntl(fd: sockfd, F_SETFL, opts & (~O_NONBLOCK)) < 0)
75796 return UA_STATUSCODE_BADINTERNALERROR;
75797 return UA_STATUSCODE_GOOD;
75798}
75799
75800unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
75801 int opts = fcntl(fd: sockfd, F_GETFL);
75802 if(opts < 0 || fcntl(fd: sockfd, F_SETFL, opts | O_NONBLOCK) < 0)
75803 return UA_STATUSCODE_BADINTERNALERROR;
75804 return UA_STATUSCODE_GOOD;
75805}
75806
75807void UA_initialize_architecture_network(void){
75808}
75809
75810void UA_deinitialize_architecture_network(void){
75811}
75812
75813#endif /* UA_ARCHITECTURE_POSIX */
75814
75815/**** amalgamated original file "/arch/win32/ua_clock.c" ****/
75816
75817/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75818 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75819 *
75820 * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
75821 * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
75822 * Copyright 2017 (c) Thomas Stalder
75823 */
75824
75825#ifdef UA_ARCHITECTURE_WIN32
75826
75827#ifndef _BSD_SOURCE
75828# define _BSD_SOURCE
75829#endif
75830
75831
75832#include <time.h>
75833/* Backup definition of SLIST_ENTRY on mingw winnt.h */
75834# ifdef SLIST_ENTRY
75835# pragma push_macro("SLIST_ENTRY")
75836# undef SLIST_ENTRY
75837# define POP_SLIST_ENTRY
75838# endif
75839# include <windows.h>
75840/* restore definition */
75841# ifdef POP_SLIST_ENTRY
75842# undef SLIST_ENTRY
75843# undef POP_SLIST_ENTRY
75844# pragma pop_macro("SLIST_ENTRY")
75845# endif
75846
75847UA_DateTime UA_DateTime_now(void) {
75848 /* Windows filetime has the same definition as UA_DateTime */
75849 FILETIME ft;
75850 SYSTEMTIME st;
75851 GetSystemTime(&st);
75852 SystemTimeToFileTime(&st, &ft);
75853 ULARGE_INTEGER ul;
75854 ul.LowPart = ft.dwLowDateTime;
75855 ul.HighPart = ft.dwHighDateTime;
75856 return (UA_DateTime)ul.QuadPart;
75857}
75858
75859/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
75860UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
75861 time_t gmt, rawtime = time(NULL);
75862
75863 struct tm ptm;
75864#ifdef __CODEGEARC__
75865 gmtime_s(&rawtime, &ptm);
75866#else
75867 gmtime_s(&ptm, &rawtime);
75868#endif
75869 // Request that mktime() looksup dst in timezone database
75870 ptm.tm_isdst = -1;
75871 gmt = mktime(&ptm);
75872
75873 return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC);
75874}
75875
75876UA_DateTime UA_DateTime_nowMonotonic(void) {
75877 LARGE_INTEGER freq, ticks;
75878 QueryPerformanceFrequency(&freq);
75879 QueryPerformanceCounter(&ticks);
75880 UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart;
75881 return (UA_DateTime)(ticks.QuadPart * ticks2dt);
75882}
75883
75884#endif /* UA_ARCHITECTURE_WIN32 */
75885
75886/**** amalgamated original file "/arch/win32/ua_architecture_functions.c" ****/
75887
75888/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75889 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75890 *
75891 * Copyright 2018 (c) Jose Cabral, fortiss GmbH
75892 */
75893
75894#ifdef UA_ARCHITECTURE_WIN32
75895
75896
75897/* Global malloc singletons */
75898#ifdef UA_ENABLE_MALLOC_SINGLETON
75899UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc;
75900UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free;
75901UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc;
75902UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc;
75903#endif
75904
75905unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
75906 u_long iMode = 0;
75907 if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
75908 return UA_STATUSCODE_BADINTERNALERROR;
75909 return UA_STATUSCODE_GOOD;
75910}
75911
75912unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
75913 u_long iMode = 1;
75914 if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR)
75915 return UA_STATUSCODE_BADINTERNALERROR;
75916 return UA_STATUSCODE_GOOD;
75917}
75918
75919void UA_initialize_architecture_network(void){
75920 WSADATA wsaData;
75921 WSAStartup(MAKEWORD(2, 2), &wsaData);
75922}
75923
75924void UA_deinitialize_architecture_network(void){
75925 WSACleanup();
75926}
75927
75928#endif /* UA_ARCHITECTURE_WIN32 */
75929
75930/**** amalgamated original file "/arch/network_tcp.c" ****/
75931
75932/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
75933 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
75934 *
75935 * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
75936 * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
75937 * Copyright 2017 (c) frax2222
75938 * Copyright 2017 (c) Jose Cabral
75939 * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
75940 * Copyright 2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
75941 */
75942
75943#define UA_INTERNAL
75944
75945
75946
75947#include <string.h> // memset
75948
75949#ifndef MSG_NOSIGNAL
75950#define MSG_NOSIGNAL 0
75951#endif
75952
75953/****************************/
75954/* Generic Socket Functions */
75955/****************************/
75956
75957static UA_StatusCode
75958connection_getsendbuffer(UA_Connection *connection,
75959 size_t length, UA_ByteString *buf) {
75960 UA_SecureChannel *channel = connection->channel;
75961 if(channel && channel->config.sendBufferSize < length)
75962 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
75963 return UA_ByteString_allocBuffer(bs: buf, length);
75964}
75965
75966static void
75967connection_releasesendbuffer(UA_Connection *connection,
75968 UA_ByteString *buf) {
75969 UA_ByteString_clear(p: buf);
75970}
75971
75972static void
75973connection_releaserecvbuffer(UA_Connection *connection,
75974 UA_ByteString *buf) {
75975 UA_ByteString_clear(p: buf);
75976}
75977
75978static UA_StatusCode
75979connection_write(UA_Connection *connection, UA_ByteString *buf) {
75980 if(connection->state == UA_CONNECTIONSTATE_CLOSED) {
75981 UA_ByteString_clear(p: buf);
75982 return UA_STATUSCODE_BADCONNECTIONCLOSED;
75983 }
75984
75985 /* Prevent OS signals when sending to a closed socket */
75986 int flags = 0;
75987 flags |= MSG_NOSIGNAL;
75988
75989 struct pollfd poll_fd[1];
75990 poll_fd[0].fd = connection->sockfd;
75991 poll_fd[0].events = UA_POLLOUT;
75992
75993 /* Send the full buffer. This may require several calls to send */
75994 size_t nWritten = 0;
75995 do {
75996 ssize_t n = 0;
75997 do {
75998 size_t bytes_to_send = buf->length - nWritten;
75999 n = UA_send(fd: connection->sockfd,
76000 buf: (const char*)buf->data + nWritten,
76001 n: bytes_to_send, flags: flags);
76002 if(n<0) {
76003 if(UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_AGAIN) {
76004 connection->close(connection);
76005 UA_ByteString_clear(p: buf);
76006 return UA_STATUSCODE_BADCONNECTIONCLOSED;
76007 }
76008 int poll_ret;
76009 do {
76010 poll_ret = UA_poll (fds: poll_fd, nfds: 1, timeout: 1000);
76011 } while (poll_ret == 0 || (poll_ret < 0 && UA_ERRNO == UA_INTERRUPTED));
76012 }
76013 } while(n < 0);
76014
76015 nWritten += (size_t)n;
76016 } while(nWritten < buf->length);
76017
76018 /* Free the buffer */
76019 UA_ByteString_clear(p: buf);
76020 return UA_STATUSCODE_GOOD;
76021}
76022
76023static UA_StatusCode
76024connection_recv(UA_Connection *connection, UA_ByteString *response,
76025 UA_UInt32 timeout) {
76026 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76027 return UA_STATUSCODE_BADCONNECTIONCLOSED;
76028
76029 /* Listen on the socket for the given timeout until a message arrives */
76030 fd_set fdset;
76031 FD_ZERO(&fdset);
76032 UA_fd_set(connection->sockfd, &fdset);
76033 UA_UInt32 timeout_usec = timeout * 1000;
76034 struct timeval tmptv = {(long int)(timeout_usec / 1000000),
76035 (int)(timeout_usec % 1000000)};
76036 int resultsize = UA_select(nfds: connection->sockfd+1, readfds: &fdset, NULL, NULL, timeout: &tmptv);
76037
76038 /* No result */
76039 if(resultsize == 0)
76040 return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
76041
76042 if(resultsize == -1) {
76043 /* The call to select was interrupted. Act as if it timed out. */
76044 if(UA_ERRNO == UA_INTERRUPTED)
76045 return UA_STATUSCODE_GOODNONCRITICALTIMEOUT;
76046
76047 /* The error cannot be recovered. Close the connection. */
76048 connection->close(connection);
76049 return UA_STATUSCODE_BADCONNECTIONCLOSED;
76050 }
76051
76052 UA_Boolean internallyAllocated = !response->length;
76053
76054 /* Allocate the buffer */
76055 if(internallyAllocated) {
76056 size_t bufferSize = 16384; /* Use as default for a new SecureChannel */
76057 UA_SecureChannel *channel = connection->channel;
76058 if(channel && channel->config.recvBufferSize > 0)
76059 bufferSize = channel->config.recvBufferSize;
76060 UA_StatusCode res = UA_ByteString_allocBuffer(bs: response, length: bufferSize);
76061 if(res != UA_STATUSCODE_GOOD)
76062 return res;
76063 }
76064
76065 /* Get the received packet(s) */
76066 ssize_t ret = UA_recv(fd: connection->sockfd, buf: (char*)response->data, n: response->length, flags: 0);
76067
76068 /* The remote side closed the connection */
76069 if(ret == 0) {
76070 if(internallyAllocated)
76071 UA_ByteString_clear(p: response);
76072 connection->close(connection);
76073 return UA_STATUSCODE_BADCONNECTIONCLOSED;
76074 }
76075
76076 /* Error case */
76077 if(ret < 0) {
76078 if(internallyAllocated)
76079 UA_ByteString_clear(p: response);
76080 if(UA_ERRNO == UA_INTERRUPTED || (timeout > 0) ?
76081 false : (UA_ERRNO == UA_EAGAIN || UA_ERRNO == UA_WOULDBLOCK))
76082 return UA_STATUSCODE_GOOD; /* statuscode_good but no data -> retry */
76083 connection->close(connection);
76084 return UA_STATUSCODE_BADCONNECTIONCLOSED;
76085 }
76086
76087 /* Set the length of the received buffer */
76088 response->length = (size_t)ret;
76089 return UA_STATUSCODE_GOOD;
76090}
76091
76092
76093/***************************/
76094/* Server NetworkLayer TCP */
76095/***************************/
76096
76097#define MAXBACKLOG 100
76098#define NOHELLOTIMEOUT 120000 /* timeout in ms before close the connection
76099 * if server does not receive Hello Message */
76100
76101typedef struct ConnectionEntry {
76102 UA_Connection connection;
76103 LIST_ENTRY(ConnectionEntry) pointers;
76104} ConnectionEntry;
76105
76106typedef struct {
76107 const UA_Logger *logger;
76108 UA_UInt16 port;
76109 UA_UInt16 maxConnections;
76110 UA_SOCKET serverSockets[FD_SETSIZE];
76111 UA_UInt16 serverSocketsSize;
76112 LIST_HEAD(, ConnectionEntry) connections;
76113 UA_UInt16 connectionsSize;
76114} ServerNetworkLayerTCP;
76115
76116static void
76117ServerNetworkLayerTCP_freeConnection(UA_Connection *connection) {
76118 UA_free(ptr: connection);
76119}
76120
76121/* This performs only 'shutdown'. 'close' is called when the shutdown
76122 * socket is returned from select. */
76123static void
76124ServerNetworkLayerTCP_close(UA_Connection *connection) {
76125 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76126 return;
76127 UA_shutdown(fd: (UA_SOCKET)connection->sockfd, how: 2);
76128 connection->state = UA_CONNECTIONSTATE_CLOSED;
76129}
76130
76131static UA_Boolean
76132purgeFirstConnectionWithoutChannel(ServerNetworkLayerTCP *layer) {
76133 ConnectionEntry *e;
76134 LIST_FOREACH(e, &layer->connections, pointers) {
76135 if(e->connection.channel == NULL) {
76136 LIST_REMOVE(e, pointers);
76137 layer->connectionsSize--;
76138 UA_close(fd: e->connection.sockfd);
76139 e->connection.free(&e->connection);
76140 return true;
76141 }
76142 }
76143 return false;
76144}
76145
76146static UA_StatusCode
76147ServerNetworkLayerTCP_add(UA_ServerNetworkLayer *nl, ServerNetworkLayerTCP *layer,
76148 UA_Int32 newsockfd, struct sockaddr_storage *remote) {
76149 if(layer->maxConnections && layer->connectionsSize >= layer->maxConnections &&
76150 !purgeFirstConnectionWithoutChannel(layer)) {
76151 return UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES;
76152 }
76153
76154 /* Set nonblocking */
76155 UA_socket_set_nonblocking(sockfd: newsockfd);//TODO: check return value
76156
76157 /* Do not merge packets on the socket (disable Nagle's algorithm) */
76158 int dummy = 1;
76159 if(UA_setsockopt(fd: newsockfd, IPPROTO_TCP, TCP_NODELAY,
76160 optval: (const char *)&dummy, optlen: sizeof(dummy)) < 0) {
76161 UA_LOG_SOCKET_ERRNO_WRAP(
76162 UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK,
76163 "Cannot set socket option TCP_NODELAY. Error: %s",
76164 errno_str));
76165 return UA_STATUSCODE_BADUNEXPECTEDERROR;
76166 }
76167
76168#if defined(UA_getnameinfo)
76169 /* Get the peer name for logging */
76170 char remote_name[100];
76171 int res = UA_getnameinfo((struct sockaddr*)remote,
76172 sizeof(struct sockaddr_storage),
76173 remote_name, sizeof(remote_name),
76174 NULL, 0, NI_NUMERICHOST);
76175 if(res == 0) {
76176 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76177 msg: "Connection %i | New connection over TCP from %s",
76178 (int)newsockfd, remote_name);
76179 } else {
76180 UA_LOG_SOCKET_ERRNO_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76181 "Connection %i | New connection over TCP, "
76182 "getnameinfo failed with error: %s",
76183 (int)newsockfd, errno_str));
76184 }
76185#else
76186 UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
76187 "Connection %i | New connection over TCP",
76188 (int)newsockfd);
76189#endif
76190 /* Allocate and initialize the connection */
76191 ConnectionEntry *e = (ConnectionEntry*)UA_malloc(size: sizeof(ConnectionEntry));
76192 if(!e) {
76193 return UA_STATUSCODE_BADOUTOFMEMORY;
76194 }
76195
76196 UA_Connection *c = &e->connection;
76197 memset(s: c, c: 0, n: sizeof(UA_Connection));
76198 c->sockfd = newsockfd;
76199 c->handle = layer;
76200 c->send = connection_write;
76201 c->close = ServerNetworkLayerTCP_close;
76202 c->free = ServerNetworkLayerTCP_freeConnection;
76203 c->getSendBuffer = connection_getsendbuffer;
76204 c->releaseSendBuffer = connection_releasesendbuffer;
76205 c->releaseRecvBuffer = connection_releaserecvbuffer;
76206 c->state = UA_CONNECTIONSTATE_OPENING;
76207 c->openingDate = UA_DateTime_nowMonotonic();
76208
76209 layer->connectionsSize++;
76210
76211 /* Add to the linked list */
76212 LIST_INSERT_HEAD(&layer->connections, e, pointers);
76213 if(nl->statistics) {
76214 nl->statistics->currentConnectionCount++;
76215 nl->statistics->cumulatedConnectionCount++;
76216 }
76217 return UA_STATUSCODE_GOOD;
76218}
76219
76220static UA_StatusCode
76221addServerSocket(ServerNetworkLayerTCP *layer, struct addrinfo *ai) {
76222 /* Create the server socket */
76223 UA_SOCKET newsock = UA_socket(domain: ai->ai_family, type: ai->ai_socktype, protocol: ai->ai_protocol);
76224 if(newsock == UA_INVALID_SOCKET)
76225 {
76226 UA_LOG_SOCKET_ERRNO_WRAP(
76227 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76228 "Error opening the server socket: %s", errno_str));
76229 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76230 }
76231
76232 /* Some Linux distributions have net.ipv6.bindv6only not activated. So
76233 * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use
76234 * AF_INET6 sockets only for IPv6. */
76235
76236 int optval = 1;
76237#if UA_IPV6
76238 if(ai->ai_family == AF_INET6 &&
76239 UA_setsockopt(fd: newsock, IPPROTO_IPV6, IPV6_V6ONLY,
76240 optval: (const char*)&optval, optlen: sizeof(optval)) == -1) {
76241 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76242 msg: "Could not set an IPv6 socket to IPv6 only");
76243 UA_close(fd: newsock);
76244 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76245
76246 }
76247#endif
76248 if(UA_setsockopt(fd: newsock, SOL_SOCKET, SO_REUSEADDR,
76249 optval: (const char *)&optval, optlen: sizeof(optval)) == -1) {
76250 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76251 msg: "Could not make the socket reusable");
76252 UA_close(fd: newsock);
76253 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76254 }
76255
76256
76257 if(UA_socket_set_nonblocking(sockfd: newsock) != UA_STATUSCODE_GOOD) {
76258 UA_LOG_WARNING(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76259 msg: "Could not set the server socket to nonblocking");
76260 UA_close(fd: newsock);
76261 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76262 }
76263
76264 /* Bind socket to address */
76265 int ret = UA_bind(fd: newsock, addr: ai->ai_addr, len: (socklen_t)ai->ai_addrlen);
76266 if(ret < 0) {
76267 /* If bind to specific address failed, try to bind *-socket */
76268 if(ai->ai_family == AF_INET) {
76269 struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
76270 if(sin->sin_addr.s_addr != htonl(INADDR_ANY)) {
76271 sin->sin_addr.s_addr = 0;
76272 ret = 0;
76273 }
76274 }
76275#if UA_IPV6
76276 else if(ai->ai_family == AF_INET6) {
76277 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
76278 if(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
76279 memset(s: &sin6->sin6_addr, c: 0, n: sizeof(sin6->sin6_addr));
76280 sin6->sin6_scope_id = 0;
76281 ret = 0;
76282 }
76283 }
76284#endif // UA_IPV6
76285 if(ret == 0) {
76286 ret = UA_bind(fd: newsock, addr: ai->ai_addr, len: (socklen_t)ai->ai_addrlen);
76287 if(ret == 0) {
76288 /* The second bind fixed the issue, inform the user. */
76289 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76290 msg: "Server socket bound to unspecified address");
76291 }
76292 }
76293 }
76294 if(ret < 0) {
76295 UA_LOG_SOCKET_ERRNO_WRAP(
76296 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76297 "Error binding a server socket: %s", errno_str));
76298 UA_close(fd: newsock);
76299 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76300 }
76301
76302 /* Start listening */
76303 if(UA_listen(fd: newsock, MAXBACKLOG) < 0) {
76304 UA_LOG_SOCKET_ERRNO_WRAP(
76305 UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76306 "Error listening on server socket: %s", errno_str));
76307 UA_close(fd: newsock);
76308 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76309 }
76310
76311 if(layer->port == 0) {
76312 /* Port was automatically chosen. Read it from the OS */
76313 struct sockaddr_in returned_addr;
76314 memset(s: &returned_addr, c: 0, n: sizeof(returned_addr));
76315 socklen_t len = sizeof(returned_addr);
76316 UA_getsockname(fd: newsock, addr: (struct sockaddr *)&returned_addr, len: &len);
76317 layer->port = ntohs(netshort: returned_addr.sin_port);
76318 }
76319
76320 layer->serverSockets[layer->serverSocketsSize] = newsock;
76321 layer->serverSocketsSize++;
76322 return UA_STATUSCODE_GOOD;
76323}
76324
76325static UA_StatusCode
76326ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_Logger *logger,
76327 const UA_String *customHostname) {
76328 UA_initialize_architecture_network();
76329
76330 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76331 layer->logger = logger;
76332
76333 /* Get addrinfo of the server and create server sockets */
76334 char hostname[512];
76335 if(customHostname->length) {
76336 if(customHostname->length >= sizeof(hostname))
76337 return UA_STATUSCODE_BADOUTOFMEMORY;
76338 memcpy(dest: hostname, src: customHostname->data, n: customHostname->length);
76339 hostname[customHostname->length] = '\0';
76340 }
76341 char portno[6];
76342 UA_snprintf(s: portno, maxlen: 6, format: "%d", layer->port);
76343 struct addrinfo hints, *res;
76344 memset(s: &hints, c: 0, n: sizeof hints);
76345#if UA_IPV6
76346 hints.ai_family = AF_UNSPEC; /* allow IPv4 and IPv6 */
76347#else
76348 hints.ai_family = AF_INET; /* enforce IPv4 only */
76349#endif
76350 hints.ai_socktype = SOCK_STREAM;
76351 hints.ai_flags = AI_PASSIVE;
76352#ifdef AI_ADDRCONFIG
76353 hints.ai_flags |= AI_ADDRCONFIG;
76354#endif
76355 hints.ai_protocol = IPPROTO_TCP;
76356 int retcode = UA_getaddrinfo(name: customHostname->length ? hostname : NULL,
76357 service: portno, req: &hints, pai: &res);
76358 if(retcode != 0) {
76359 UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK,
76360 "getaddrinfo lookup of %s failed with error %d - %s", hostname, retcode, errno_str));
76361 return UA_STATUSCODE_BADINTERNALERROR;
76362 }
76363
76364 /* There might be serveral addrinfos (for different network cards,
76365 * IPv4/IPv6). Add a server socket for all of them. */
76366 struct addrinfo *ai = res;
76367 for(layer->serverSocketsSize = 0;
76368 layer->serverSocketsSize < FD_SETSIZE && ai != NULL;
76369 ai = ai->ai_next) {
76370 addServerSocket(layer, ai);
76371 }
76372 UA_freeaddrinfo(ai: res);
76373
76374 if(layer->serverSocketsSize == 0) {
76375 return UA_STATUSCODE_BADCOMMUNICATIONERROR;
76376 }
76377
76378 /* Get the discovery url from the hostname */
76379 UA_String du = UA_STRING_NULL;
76380 char discoveryUrlBuffer[256];
76381 if(customHostname->length) {
76382 du.length = (size_t)UA_snprintf(s: discoveryUrlBuffer, maxlen: 255, format: "opc.tcp://%.*s:%d/",
76383 (int)customHostname->length, customHostname->data,
76384 layer->port);
76385 du.data = (UA_Byte*)discoveryUrlBuffer;
76386 } else {
76387 char hostnameBuffer[256];
76388 if(UA_gethostname(name: hostnameBuffer, len: 255) == 0) {
76389 du.length = (size_t)UA_snprintf(s: discoveryUrlBuffer, maxlen: 255, format: "opc.tcp://%s:%d/",
76390 hostnameBuffer, layer->port);
76391 du.data = (UA_Byte*)discoveryUrlBuffer;
76392 } else {
76393 UA_LOG_ERROR(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK, msg: "Could not get the hostname");
76394 return UA_STATUSCODE_BADINTERNALERROR;
76395 }
76396 }
76397 UA_String_copy(src: &du, dst: &nl->discoveryUrl);
76398
76399 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76400 msg: "TCP network layer listening on %.*s",
76401 (int)nl->discoveryUrl.length, nl->discoveryUrl.data);
76402 return UA_STATUSCODE_GOOD;
76403}
76404
76405/* After every select, reset the sockets to listen on */
76406static UA_Int32
76407setFDSet(ServerNetworkLayerTCP *layer, fd_set *fdset) {
76408 FD_ZERO(fdset);
76409 UA_Int32 highestfd = 0;
76410 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76411 UA_fd_set(layer->serverSockets[i], fdset);
76412 if((UA_Int32)layer->serverSockets[i] > highestfd)
76413 highestfd = (UA_Int32)layer->serverSockets[i];
76414 }
76415
76416 ConnectionEntry *e;
76417 LIST_FOREACH(e, &layer->connections, pointers) {
76418 UA_fd_set(e->connection.sockfd, fdset);
76419 if((UA_Int32)e->connection.sockfd > highestfd)
76420 highestfd = (UA_Int32)e->connection.sockfd;
76421 }
76422
76423 return highestfd;
76424}
76425
76426static UA_StatusCode
76427ServerNetworkLayerTCP_listen(UA_ServerNetworkLayer *nl, UA_Server *server,
76428 UA_UInt16 timeout) {
76429 /* Every open socket can generate two jobs */
76430 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76431
76432 if(layer->serverSocketsSize == 0)
76433 return UA_STATUSCODE_GOOD;
76434
76435 /* Listen on open sockets (including the server) */
76436 fd_set fdset, errset;
76437 UA_Int32 highestfd = setFDSet(layer, fdset: &fdset);
76438 setFDSet(layer, fdset: &errset);
76439 struct timeval tmptv = {0, timeout * 1000};
76440 if(UA_select(nfds: highestfd+1, readfds: &fdset, NULL, exceptfds: &errset, timeout: &tmptv) < 0) {
76441 UA_LOG_SOCKET_ERRNO_WRAP(
76442 UA_LOG_DEBUG(layer->logger, UA_LOGCATEGORY_NETWORK,
76443 "Socket select failed with %s", errno_str));
76444 // we will retry, so do not return bad
76445 return UA_STATUSCODE_GOOD;
76446 }
76447
76448 /* Accept new connections via the server sockets */
76449 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76450 if(!UA_fd_isset(layer->serverSockets[i], &fdset))
76451 continue;
76452
76453 struct sockaddr_storage remote;
76454 socklen_t remote_size = sizeof(remote);
76455 UA_SOCKET newsockfd = UA_accept(fd: layer->serverSockets[i],
76456 addr: (struct sockaddr*)&remote, addr_len: &remote_size);
76457 if(newsockfd == UA_INVALID_SOCKET)
76458 continue;
76459
76460 UA_LOG_TRACE(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76461 msg: "Connection %i | New TCP connection on server socket %i",
76462 (int)newsockfd, (int)(layer->serverSockets[i]));
76463
76464 if(ServerNetworkLayerTCP_add(nl, layer, newsockfd: (UA_Int32)newsockfd, remote: &remote) != UA_STATUSCODE_GOOD) {
76465 UA_close(fd: newsockfd);
76466 }
76467 }
76468
76469 /* Read from established sockets */
76470 ConnectionEntry *e, *e_tmp;
76471 UA_DateTime now = UA_DateTime_nowMonotonic();
76472 LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
76473 if((e->connection.state == UA_CONNECTIONSTATE_OPENING) &&
76474 (now > (e->connection.openingDate + (NOHELLOTIMEOUT * UA_DATETIME_MSEC)))) {
76475 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76476 msg: "Connection %i | Closed by the server (no Hello Message)",
76477 (int)(e->connection.sockfd));
76478 LIST_REMOVE(e, pointers);
76479 layer->connectionsSize--;
76480 UA_close(fd: e->connection.sockfd);
76481 UA_Server_removeConnection(server, connection: &e->connection);
76482 if(nl->statistics) {
76483 nl->statistics->connectionTimeoutCount++;
76484 nl->statistics->currentConnectionCount--;
76485 }
76486 continue;
76487 }
76488
76489 if(!UA_fd_isset(e->connection.sockfd, &errset) &&
76490 !UA_fd_isset(e->connection.sockfd, &fdset))
76491 continue;
76492
76493 UA_LOG_TRACE(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76494 msg: "Connection %i | Activity on the socket",
76495 (int)(e->connection.sockfd));
76496
76497 UA_ByteString buf = UA_BYTESTRING_NULL;
76498 UA_StatusCode retval = connection_recv(connection: &e->connection, response: &buf, timeout: 0);
76499
76500 if(retval == UA_STATUSCODE_GOOD) {
76501 /* Process packets */
76502 UA_Server_processBinaryMessage(server, connection: &e->connection, message: &buf);
76503 connection_releaserecvbuffer(connection: &e->connection, buf: &buf);
76504 } else if(retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
76505 /* The socket is shutdown but not closed */
76506 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76507 msg: "Connection %i | Closed",
76508 (int)(e->connection.sockfd));
76509 LIST_REMOVE(e, pointers);
76510 layer->connectionsSize--;
76511 UA_close(fd: e->connection.sockfd);
76512 UA_Server_removeConnection(server, connection: &e->connection);
76513 if(nl->statistics) {
76514 nl->statistics->currentConnectionCount--;
76515 }
76516 }
76517 }
76518 return UA_STATUSCODE_GOOD;
76519}
76520
76521static void
76522ServerNetworkLayerTCP_stop(UA_ServerNetworkLayer *nl, UA_Server *server) {
76523 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76524 UA_LOG_INFO(logger: layer->logger, category: UA_LOGCATEGORY_NETWORK,
76525 msg: "Shutting down the TCP network layer");
76526
76527 /* Close the server sockets */
76528 for(UA_UInt16 i = 0; i < layer->serverSocketsSize; i++) {
76529 UA_shutdown(fd: layer->serverSockets[i], how: 2);
76530 UA_close(fd: layer->serverSockets[i]);
76531 }
76532 layer->serverSocketsSize = 0;
76533
76534 /* Close open connections */
76535 ConnectionEntry *e;
76536 LIST_FOREACH(e, &layer->connections, pointers)
76537 ServerNetworkLayerTCP_close(connection: &e->connection);
76538
76539 /* Run recv on client sockets. This picks up the closed sockets and frees
76540 * the connection. */
76541 ServerNetworkLayerTCP_listen(nl, server, timeout: 0);
76542
76543 UA_deinitialize_architecture_network();
76544}
76545
76546/* run only when the server is stopped */
76547static void
76548ServerNetworkLayerTCP_clear(UA_ServerNetworkLayer *nl) {
76549 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP *)nl->handle;
76550 UA_String_clear(p: &nl->discoveryUrl);
76551
76552 /* Hard-close and remove remaining connections. The server is no longer
76553 * running. So this is safe. */
76554 ConnectionEntry *e, *e_tmp;
76555 LIST_FOREACH_SAFE(e, &layer->connections, pointers, e_tmp) {
76556 LIST_REMOVE(e, pointers);
76557 layer->connectionsSize--;
76558 UA_close(fd: e->connection.sockfd);
76559 UA_free(ptr: e);
76560 if(nl->statistics) {
76561 nl->statistics->currentConnectionCount--;
76562 }
76563 }
76564
76565 /* Free the layer */
76566 UA_free(ptr: layer);
76567}
76568
76569UA_ServerNetworkLayer
76570UA_ServerNetworkLayerTCP(UA_ConnectionConfig config, UA_UInt16 port,
76571 UA_UInt16 maxConnections) {
76572 UA_ServerNetworkLayer nl;
76573 memset(s: &nl, c: 0, n: sizeof(UA_ServerNetworkLayer));
76574 nl.clear = ServerNetworkLayerTCP_clear;
76575 nl.localConnectionConfig = config;
76576 nl.start = ServerNetworkLayerTCP_start;
76577 nl.listen = ServerNetworkLayerTCP_listen;
76578 nl.stop = ServerNetworkLayerTCP_stop;
76579 nl.handle = NULL;
76580
76581 ServerNetworkLayerTCP *layer = (ServerNetworkLayerTCP*)
76582 UA_calloc(nmemb: 1,size: sizeof(ServerNetworkLayerTCP));
76583 if(!layer)
76584 return nl;
76585 nl.handle = layer;
76586
76587 layer->port = port;
76588 layer->maxConnections = maxConnections;
76589
76590 return nl;
76591}
76592
76593typedef struct TCPClientConnection {
76594 struct addrinfo hints, *server;
76595 UA_DateTime connStart;
76596 UA_String endpointUrl;
76597 UA_UInt32 timeout;
76598} TCPClientConnection;
76599
76600/***************************/
76601/* Client NetworkLayer TCP */
76602/***************************/
76603
76604static void
76605ClientNetworkLayerTCP_close(UA_Connection *connection) {
76606 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76607 return;
76608
76609 if(connection->sockfd != UA_INVALID_SOCKET) {
76610 UA_shutdown(fd: connection->sockfd, how: 2);
76611 UA_close(fd: connection->sockfd);
76612 }
76613 connection->state = UA_CONNECTIONSTATE_CLOSED;
76614}
76615
76616static void
76617ClientNetworkLayerTCP_free(UA_Connection *connection) {
76618 if(!connection->handle)
76619 return;
76620
76621 TCPClientConnection *tcpConnection = (TCPClientConnection *)connection->handle;
76622 if(tcpConnection->server)
76623 UA_freeaddrinfo(ai: tcpConnection->server);
76624 UA_String_clear(p: &tcpConnection->endpointUrl);
76625 UA_free(ptr: tcpConnection);
76626 connection->handle = NULL;
76627}
76628
76629UA_StatusCode
76630UA_ClientConnectionTCP_poll(UA_Connection *connection, UA_UInt32 timeout,
76631 const UA_Logger *logger) {
76632 if(connection->state == UA_CONNECTIONSTATE_CLOSED)
76633 return UA_STATUSCODE_BADDISCONNECT;
76634 if(connection->state == UA_CONNECTIONSTATE_ESTABLISHED)
76635 return UA_STATUSCODE_GOOD;
76636
76637 /* Connection timeout? */
76638 TCPClientConnection *tcpConnection = (TCPClientConnection*) connection->handle;
76639 if(tcpConnection == NULL) {
76640 connection->state = UA_CONNECTIONSTATE_CLOSED;
76641 return UA_STATUSCODE_BADDISCONNECT; // some thing is wrong
76642 }
76643 if((UA_Double) (UA_DateTime_nowMonotonic() - tcpConnection->connStart)
76644 > (UA_Double) tcpConnection->timeout * UA_DATETIME_MSEC ) {
76645 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK, msg: "Timed out");
76646 ClientNetworkLayerTCP_close(connection);
76647 return UA_STATUSCODE_BADDISCONNECT;
76648 }
76649
76650 /* Get a socket and connect (only once) if not already done in a previous
76651 * call. On win32, calling connect multiple times is not recommended on
76652 * non-blocking sockets
76653 * (https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-connect).
76654 * On posix it is also not necessary to call connect multiple times.
76655 *
76656 * Identification of successfull connection is done using select (writeable/errorfd)
76657 * and getsockopt using SO_ERROR on win32 and posix.
76658 */
76659 if(connection->sockfd == UA_INVALID_SOCKET) {
76660 connection->sockfd = UA_socket(domain: tcpConnection->server->ai_family,
76661 type: tcpConnection->server->ai_socktype,
76662 protocol: tcpConnection->server->ai_protocol);
76663 if(connection->sockfd == UA_INVALID_SOCKET) {
76664 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76665 msg: "Could not create client socket: %s", strerror(UA_ERRNO));
76666 ClientNetworkLayerTCP_close(connection);
76667 return UA_STATUSCODE_BADDISCONNECT;
76668 }
76669
76670 /* Non blocking connect to be able to timeout */
76671 if(UA_socket_set_nonblocking(sockfd: connection->sockfd) != UA_STATUSCODE_GOOD) {
76672 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76673 msg: "Could not set the client socket to nonblocking");
76674 ClientNetworkLayerTCP_close(connection);
76675 return UA_STATUSCODE_BADDISCONNECT;
76676 }
76677
76678 /* Don't have the socket create interrupt signals */
76679#ifdef SO_NOSIGPIPE
76680 int val = 1;
76681 int sso_result = setsockopt(connection->sockfd, SOL_SOCKET, SO_NOSIGPIPE,
76682 (void *)&val, sizeof(val));
76683 if(sso_result < 0)
76684 UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, "Couldn't set SO_NOSIGPIPE");
76685#endif
76686 int error = UA_connect(fd: connection->sockfd, addr: tcpConnection->server->ai_addr,
76687 len: tcpConnection->server->ai_addrlen);
76688
76689 /* Connection successful */
76690 if(error == 0) {
76691 connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
76692 return UA_STATUSCODE_GOOD;
76693 }
76694
76695 /* The connection failed */
76696 if((UA_ERRNO != UA_ERR_CONNECTION_PROGRESS)) {
76697 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76698 msg: "Connection to %.*s failed with error: %s",
76699 (int)tcpConnection->endpointUrl.length,
76700 tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
76701 ClientNetworkLayerTCP_close(connection);
76702 return UA_STATUSCODE_BADDISCONNECT;
76703 }
76704 }
76705
76706 /* Use select to wait until connected. Return with a half-opened connection
76707 * after a timeout. */
76708 UA_UInt32 timeout_usec = timeout * 1000;
76709
76710#ifdef _OS9000
76711 /* OS-9 cannot use select for checking write sockets. Therefore, we need to
76712 * use connect until success or failed */
76713 int resultsize = 0;
76714 do {
76715 u_int32 time = 0x80000001;
76716 signal_code sig;
76717
76718 timeout_usec -= 1000000/256; // Sleep 1/256 second
76719 if(timeout_usec < 0)
76720 break;
76721
76722 _os_sleep(&time, &sig);
76723 error = connect(connection->sockfd, tcpConnection->server->ai_addr,
76724 tcpConnection->server->ai_addrlen);
76725 if((error == -1 && UA_ERRNO == EISCONN) || (error == 0))
76726 resultsize = 1;
76727 if(error == -1 && UA_ERRNO != EALREADY && UA_ERRNO != EINPROGRESS)
76728 break;
76729 } while(resultsize == 0);
76730#else
76731 /* Wait in a select-call until the connection fully opens or the timeout
76732 * happens */
76733
76734 /* On windows select both writing and error fdset */
76735 fd_set writing_fdset;
76736 FD_ZERO(&writing_fdset);
76737 UA_fd_set(connection->sockfd, &writing_fdset);
76738 fd_set error_fdset;
76739 FD_ZERO(&error_fdset);
76740#ifdef _WIN32
76741 UA_fd_set(connection->sockfd, &error_fdset);
76742#endif
76743 struct timeval tmptv = {(long int)(timeout_usec / 1000000),
76744 (int)(timeout_usec % 1000000)};
76745
76746 int ret = UA_select(nfds: (UA_Int32)(connection->sockfd + 1), NULL, writefds: &writing_fdset,
76747 exceptfds: &error_fdset, timeout: &tmptv);
76748
76749 // When select fails abort connection
76750 if(ret == -1) {
76751 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76752 msg: "Connection to %.*s failed with error: %s",
76753 (int)tcpConnection->endpointUrl.length,
76754 tcpConnection->endpointUrl.data, strerror(UA_ERRNO));
76755 ClientNetworkLayerTCP_close(connection);
76756 return UA_STATUSCODE_BADDISCONNECT;
76757 } else if (timeout && ret == 0) {
76758 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76759 msg: "Connection to %.*s timed out",
76760 (int)tcpConnection->endpointUrl.length,
76761 tcpConnection->endpointUrl.data);
76762 ClientNetworkLayerTCP_close(connection);
76763 return UA_STATUSCODE_BADTIMEOUT;
76764 }
76765
76766 int resultsize = UA_fd_isset(connection->sockfd, &writing_fdset);
76767#endif
76768
76769 /* Any errors on the socket reported? */
76770 OPTVAL_TYPE so_error = 0;
76771 socklen_t len = sizeof(so_error);
76772 ret = UA_getsockopt(fd: connection->sockfd, SOL_SOCKET, SO_ERROR, optval: &so_error, optlen: &len);
76773 if(ret != 0 || so_error != 0) {
76774 // no UA_LOG_SOCKET_ERRNO_GAI_WRAP because of so_error
76775#ifndef _WIN32
76776 char *errno_str = strerror(errnum: ret == 0 ? so_error : UA_ERRNO);
76777#elif defined(UNDER_CE)
76778 LPVOID errno_str = NULL;
76779 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
76780 FORMAT_MESSAGE_IGNORE_INSERTS,
76781 NULL, ret == 0 ? so_error : WSAGetLastError(),
76782 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&errno_str, 0,
76783 NULL);
76784#else
76785 char *errno_str = NULL;
76786 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
76787 FORMAT_MESSAGE_IGNORE_INSERTS,
76788 NULL, ret == 0 ? so_error : WSAGetLastError(),
76789 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&errno_str, 0,
76790 NULL);
76791#endif
76792 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76793 msg: "Connection to %.*s failed with error: %s",
76794 (int)tcpConnection->endpointUrl.length,
76795 tcpConnection->endpointUrl.data, errno_str);
76796#ifdef _WIN32
76797 LocalFree(errno_str);
76798#endif
76799 ClientNetworkLayerTCP_close(connection);
76800 return UA_STATUSCODE_BADDISCONNECT;
76801 }
76802
76803 /* The connection is fully opened. Otherwise, select has timed out. But we
76804 * can retry. */
76805 if(resultsize > 0)
76806 connection->state = UA_CONNECTIONSTATE_ESTABLISHED;
76807
76808 return UA_STATUSCODE_GOOD;
76809}
76810
76811UA_Connection
76812UA_ClientConnectionTCP_init(UA_ConnectionConfig config, const UA_String endpointUrl,
76813 UA_UInt32 timeout, const UA_Logger *logger) {
76814 UA_initialize_architecture_network();
76815
76816 UA_Connection connection;
76817 memset(s: &connection, c: 0, n: sizeof(UA_Connection));
76818
76819 connection.state = UA_CONNECTIONSTATE_OPENING;
76820 connection.sockfd = UA_INVALID_SOCKET;
76821 connection.send = connection_write;
76822 connection.recv = connection_recv;
76823 connection.close = ClientNetworkLayerTCP_close;
76824 connection.free = ClientNetworkLayerTCP_free;
76825 connection.getSendBuffer = connection_getsendbuffer;
76826 connection.releaseSendBuffer = connection_releasesendbuffer;
76827 connection.releaseRecvBuffer = connection_releaserecvbuffer;
76828
76829 TCPClientConnection *tcpClientConnection = (TCPClientConnection*)
76830 UA_malloc(size: sizeof(TCPClientConnection));
76831 if(!tcpClientConnection) {
76832 connection.state = UA_CONNECTIONSTATE_CLOSED;
76833 return connection;
76834 }
76835 memset(s: tcpClientConnection, c: 0, n: sizeof(TCPClientConnection));
76836 connection.handle = (void*) tcpClientConnection;
76837 tcpClientConnection->timeout = timeout;
76838 UA_String hostnameString = UA_STRING_NULL;
76839 UA_String pathString = UA_STRING_NULL;
76840 UA_UInt16 port = 0;
76841 char hostname[512];
76842 tcpClientConnection->connStart = UA_DateTime_nowMonotonic();
76843 UA_String_copy(src: &endpointUrl, dst: &tcpClientConnection->endpointUrl);
76844
76845 UA_StatusCode parse_retval =
76846 UA_parseEndpointUrl(endpointUrl: &endpointUrl, outHostname: &hostnameString, outPort: &port, outPath: &pathString);
76847 if(parse_retval != UA_STATUSCODE_GOOD || hostnameString.length > 511) {
76848 UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK,
76849 msg: "Server url is invalid: %.*s",
76850 (int)endpointUrl.length, endpointUrl.data);
76851 connection.state = UA_CONNECTIONSTATE_CLOSED;
76852 return connection;
76853 }
76854 memcpy(dest: hostname, src: hostnameString.data, n: hostnameString.length);
76855 hostname[hostnameString.length] = 0;
76856
76857 if(port == 0) {
76858 port = 4840;
76859 UA_LOG_INFO(logger, category: UA_LOGCATEGORY_NETWORK,
76860 msg: "No port defined, using default port %" PRIu16, port);
76861 }
76862
76863 memset(s: &tcpClientConnection->hints, c: 0, n: sizeof(tcpClientConnection->hints));
76864 tcpClientConnection->hints.ai_family = AF_UNSPEC;
76865 tcpClientConnection->hints.ai_socktype = SOCK_STREAM;
76866 char portStr[6];
76867 UA_snprintf(s: portStr, maxlen: 6, format: "%d", port);
76868 int error = UA_getaddrinfo(name: hostname, service: portStr, req: &tcpClientConnection->hints,
76869 pai: &tcpClientConnection->server);
76870 if(error != 0 || !tcpClientConnection->server) {
76871 UA_LOG_SOCKET_ERRNO_GAI_WRAP(UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK,
76872 "DNS lookup of %s failed with error %d - %s",
76873 hostname, error, errno_str));
76874 connection.state = UA_CONNECTIONSTATE_CLOSED;
76875 return connection;
76876 }
76877
76878 /* Return connection with state UA_CONNECTIONSTATE_OPENING */
76879 return connection;
76880}
76881

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