Coverage Report

Created: 2026-09-27 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/server/ua_server.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2014-2017 (c) Florian Palm
7
 *    Copyright 2015-2016 (c) Sten Grüner
8
 *    Copyright 2015-2016 (c) Chris Iatrou
9
 *    Copyright 2015 (c) LEvertz
10
 *    Copyright 2015-2016 (c) Oleksiy Vasylyev
11
 *    Copyright 2016 (c) Julian Grothoff
12
 *    Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
13
 *    Copyright 2016 (c) Lorenz Haas
14
 *    Copyright 2017 (c) frax2222
15
 *    Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB
16
 *    Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang)
17
 *    Copyright 2019 (c) Kalycito Infotech Private Limited
18
 *    Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes)
19
 *    Copyright 2022-2025 (c) Fraunhofer IOSB (Author: Andreas Ebner)
20
 *    Copyright 2024 (c) Fraunhofer IOSB (Author: Noel Graf)
21
 */
22
23
#include "ua_server_internal.h"
24
25
#ifdef UA_ENABLE_SUBSCRIPTIONS
26
#include "ua_subscription.h"
27
#endif
28
29
#ifdef UA_ENABLE_NODESET_INJECTOR
30
#include "open62541/nodesetinjector.h"
31
#endif
32
33
#ifdef UA_ENABLE_ENCRYPTION
34
#include "open62541/plugin/certificategroup_default.h"
35
#endif
36
37
6.46k
#define STARTCHANNELID 1
38
6.46k
#define STARTTOKENID 1
39
40
/**********************/
41
/* Namespace Handling */
42
/**********************/
43
44
/* The NS1 Uri can be changed by the user to some custom string. This method is
45
 * called to initialize the NS1 Uri if it is not set before to the default
46
 * Application URI.
47
 *
48
 * This is done as soon as the Namespace Array is read or written via node value
49
 * read / write services, or UA_Server_addNamespace, or UA_Server_getNamespaceByIndex
50
 * UA_Server_getNamespaceByName or UA_Server_run_startup is called.
51
 *
52
 * Therefore one has to set the custom NS1 URI before one of the previously
53
 * mentioned steps. */
54
55
void
56
19.9k
setupNs1Uri(UA_Server *server) {
57
19.9k
    if(!server->namespaces[1].data) {
58
19.9k
        UA_String_copy(&server->config.applicationDescription.applicationUri,
59
19.9k
                       &server->namespaces[1]);
60
19.9k
    }
61
19.9k
}
62
63
19.4k
UA_UInt16 addNamespace(UA_Server *server, const UA_String name) {
64
    /* ensure that the uri for ns1 is set up from the app description */
65
19.4k
    setupNs1Uri(server);
66
67
    /* Check if the namespace already exists in the server's namespace array */
68
19.4k
    for(size_t i = 0; i < server->namespacesSize; ++i) {
69
19.4k
        if(UA_String_equal(&name, &server->namespaces[i]))
70
19.4k
            return (UA_UInt16) i;
71
19.4k
    }
72
73
    /* Make the array bigger */
74
0
    UA_String *newNS = (UA_String*)UA_realloc(server->namespaces,
75
0
                                              sizeof(UA_String) * (server->namespacesSize + 1));
76
0
    UA_CHECK_MEM(newNS, return 0);
77
78
0
    server->namespaces = newNS;
79
80
    /* Copy the namespace string */
81
0
    UA_StatusCode retval = UA_String_copy(&name, &server->namespaces[server->namespacesSize]);
82
0
    UA_CHECK_STATUS(retval, return 0);
83
84
    /* Announce the change (otherwise, the array appears unchanged) */
85
0
    ++server->namespacesSize;
86
0
    return (UA_UInt16)(server->namespacesSize - 1);
87
0
}
88
89
19.4k
UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
90
    /* Override const attribute to get string (dirty hack) */
91
19.4k
    UA_String nameString;
92
19.4k
    nameString.length = strlen(name);
93
19.4k
    nameString.data = (UA_Byte*)(uintptr_t)name;
94
19.4k
    lockServer(server);
95
19.4k
    UA_UInt16 retVal = addNamespace(server, nameString);
96
19.4k
    unlockServer(server);
97
19.4k
    return retVal;
98
19.4k
}
99
100
UA_ServerConfig*
101
1.36M
UA_Server_getConfig(UA_Server *server) {
102
1.36M
    UA_CHECK_MEM(server, return NULL);
103
1.36M
    return &server->config;
104
1.36M
}
105
106
UA_StatusCode
107
getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
108
0
                   size_t *foundIndex) {
109
    /* ensure that the uri for ns1 is set up from the app description */
110
0
    setupNs1Uri(server);
111
0
    UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
112
0
    for(size_t idx = 0; idx < server->namespacesSize; idx++) {
113
0
        if(UA_String_equal(&server->namespaces[idx], &namespaceUri)) {
114
0
            (*foundIndex) = idx;
115
0
            res = UA_STATUSCODE_GOOD;
116
0
            break;
117
0
        }
118
0
    }
119
0
    return res;
120
0
}
121
122
UA_StatusCode
123
getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
124
0
                   UA_String *foundUri) {
125
    /* ensure that the uri for ns1 is set up from the app description */
126
0
    setupNs1Uri(server);
127
0
    UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND;
128
0
    if(namespaceIndex >= server->namespacesSize)
129
0
        return res;
130
0
    res = UA_String_copy(&server->namespaces[namespaceIndex], foundUri);
131
0
    return res;
132
0
}
133
134
UA_StatusCode
135
UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri,
136
0
                             size_t *foundIndex) {
137
0
    lockServer(server);
138
0
    UA_StatusCode res = getNamespaceByName(server, namespaceUri, foundIndex);
139
0
    unlockServer(server);
140
0
    return res;
141
0
}
142
143
UA_StatusCode
144
UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex,
145
0
                              UA_String *foundUri) {
146
0
    lockServer(server);
147
0
    UA_StatusCode res = getNamespaceByIndex(server, namespaceIndex, foundUri);
148
0
    unlockServer(server);
149
0
    return res;
150
0
}
151
152
UA_StatusCode
153
UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId,
154
0
                               UA_NodeIteratorCallback callback, void *handle) {
155
0
    UA_BrowseDescription bd;
156
0
    UA_BrowseDescription_init(&bd);
157
0
    bd.nodeId = parentNodeId;
158
0
    bd.browseDirection = UA_BROWSEDIRECTION_BOTH;
159
0
    bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_ISFORWARD;
160
161
0
    UA_BrowseResult br = UA_Server_browse(server, 0, &bd);
162
0
    UA_StatusCode res = br.statusCode;
163
0
    UA_CHECK_STATUS(res, goto cleanup);
164
165
0
    for(size_t i = 0; i < br.referencesSize; i++) {
166
0
        if(!UA_ExpandedNodeId_isLocal(&br.references[i].nodeId))
167
0
            continue;
168
0
        res = callback(br.references[i].nodeId.nodeId, !br.references[i].isForward,
169
0
                       br.references[i].referenceTypeId, handle);
170
0
        UA_CHECK_STATUS(res, goto cleanup);
171
0
    }
172
0
cleanup:
173
0
    UA_BrowseResult_clear(&br);
174
0
    return res;
175
0
}
176
177
/********************/
178
/* GDS Transaction  */
179
/********************/
180
181
UA_StatusCode
182
0
UA_GDSTransaction_init(UA_GDSTransaction *transaction, UA_Server *server, const UA_NodeId sessionId) {
183
0
    if(!transaction || !server)
184
0
        return UA_STATUSCODE_BADINTERNALERROR;
185
186
0
    UA_ByteString csr = UA_BYTESTRING_NULL;
187
0
    if(transaction->localCsrCertificate.length > 0)
188
0
        csr = transaction->localCsrCertificate;
189
190
0
    memset(transaction, 0, sizeof(UA_GDSTransaction));
191
192
0
    transaction->state = UA_GDSTRANSACTIONSTATE_PENDING;
193
0
    UA_NodeId_copy(&sessionId, &transaction->sessionId);
194
0
    transaction->server = server;
195
0
    transaction->localCsrCertificate = csr;
196
0
    transaction->applyChangesQueued = false;
197
198
0
    return UA_STATUSCODE_GOOD;
199
0
}
200
201
UA_CertificateGroup*
202
UA_GDSTransaction_getCertificateGroup(UA_GDSTransaction *transaction,
203
0
                                      const UA_CertificateGroup *certGroup) {
204
0
#ifdef UA_ENABLE_ENCRYPTION
205
0
    if(!transaction || !certGroup)
206
0
        return NULL;
207
208
    /* Check if transaction was initialized */
209
0
    if(transaction->state != UA_GDSTRANSACTIONSTATE_PENDING)
210
0
        return NULL;
211
212
0
    for(size_t i = 0; i < transaction->certGroupSize; i++) {
213
0
        UA_CertificateGroup *group = &transaction->certGroups[i];
214
0
        if(UA_NodeId_equal(&group->certificateGroupId, &certGroup->certificateGroupId))
215
0
            return group;
216
0
    }
217
218
    /* If the certGroup does not exist, create a new one */
219
0
    transaction->certGroups = (UA_CertificateGroup*)UA_realloc(transaction->certGroups, (transaction->certGroupSize + 1) * sizeof(UA_CertificateGroup));
220
0
    if(!transaction->certGroups)
221
0
        return NULL;
222
223
0
    transaction->certGroupSize++;
224
225
0
    memset(&transaction->certGroups[transaction->certGroupSize-1], 0, sizeof(UA_CertificateGroup));
226
227
0
    UA_TrustListDataType trustList;
228
0
    UA_TrustListDataType_init(&trustList);
229
0
    trustList.specifiedLists = UA_TRUSTLISTMASKS_ALL;
230
0
    certGroup->getTrustList((UA_CertificateGroup*)(uintptr_t)certGroup, &trustList);
231
232
    /* Set up the parameters */
233
0
    static UA_THREAD_LOCAL UA_KeyValuePair params[1] = {
234
0
        {{0, UA_STRING_STATIC("max-trust-listsize")}, {0}}
235
0
    };
236
0
    UA_KeyValueMap paramsMap = {1, params};
237
238
0
    UA_ServerConfig *config = UA_Server_getConfig(transaction->server);
239
0
    UA_Variant_setScalar(&params[0].value, &config->maxTrustListSize,
240
0
                         &UA_TYPES[UA_TYPES_UINT32]);
241
242
0
    UA_CertificateGroup_Memorystore(&transaction->certGroups[transaction->certGroupSize-1],
243
0
        (UA_NodeId*)(uintptr_t)&certGroup->certificateGroupId, &trustList, certGroup->logging, &paramsMap);
244
245
0
    UA_TrustListDataType_clear(&trustList);
246
247
0
    return &transaction->certGroups[transaction->certGroupSize-1];
248
#else
249
    return NULL;
250
#endif
251
0
}
252
253
UA_StatusCode
254
UA_GDSTransaction_addCertificateInfo(UA_GDSTransaction *transaction,
255
                                     const UA_NodeId certificateGroupId,
256
                                     const UA_NodeId certificateTypeId,
257
                                     const UA_ByteString *certificate,
258
0
                                     const UA_ByteString *privateKey) {
259
0
    if(!transaction || !certificate)
260
0
        return UA_STATUSCODE_BADINTERNALERROR;
261
262
    /* Check if transaction was initialized */
263
0
    if(transaction->state != UA_GDSTRANSACTIONSTATE_PENDING)
264
0
        return UA_STATUSCODE_BADINVALIDSTATE;
265
266
    /* Check if an entry with certificateGroupId and certificateTypeId already exists */
267
0
    for(size_t i = 0; i < transaction->certificateInfosSize; i++) {
268
0
        UA_GDSCertificateInfo *certInfo = &transaction->certificateInfos[i];
269
270
0
        if(!UA_NodeId_equal(&certInfo->certificateGroup, &certificateGroupId) ||
271
0
           !UA_NodeId_equal(&certInfo->certificateType, &certificateTypeId))
272
0
            continue;
273
274
0
        UA_ByteString_clear(&certInfo->certificate);
275
0
        UA_ByteString_clear(&certInfo->privateKey);
276
277
0
        UA_ByteString_copy(certificate, &certInfo->certificate);
278
0
        certInfo->privateKey = UA_BYTESTRING_NULL;
279
0
        if(privateKey)
280
0
            UA_ByteString_copy(privateKey, &certInfo->privateKey);
281
282
0
        return UA_STATUSCODE_GOOD;
283
0
    }
284
285
0
    UA_GDSCertificateInfo *newCertInfos = (UA_GDSCertificateInfo *)UA_realloc(transaction->certificateInfos,
286
0
        (transaction->certificateInfosSize + 1) * sizeof(UA_GDSCertificateInfo));
287
0
    if(!newCertInfos)
288
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
289
290
0
    transaction->certificateInfos = newCertInfos;
291
292
0
    UA_GDSCertificateInfo *newCertInfo = &transaction->certificateInfos[transaction->certificateInfosSize];
293
0
    UA_ByteString_copy(certificate, &newCertInfo->certificate);
294
0
    UA_NodeId_copy(&certificateGroupId, &newCertInfo->certificateGroup);
295
0
    UA_NodeId_copy(&certificateTypeId, &newCertInfo->certificateType);
296
0
    newCertInfo->privateKey = UA_BYTESTRING_NULL;
297
0
    if(privateKey)
298
0
        UA_ByteString_copy(privateKey, &newCertInfo->privateKey);
299
300
0
    transaction->certificateInfosSize++;
301
302
0
    return UA_STATUSCODE_GOOD;
303
0
}
304
305
6.46k
void UA_GDSTransaction_clear(UA_GDSTransaction *transaction) {
306
6.46k
    if(!transaction)
307
0
        return;
308
309
6.46k
    transaction->state = UA_GDSTRANSACTIONSTATE_FRESH;
310
6.46k
    transaction->server = NULL;
311
6.46k
    UA_NodeId_clear(&transaction->sessionId);
312
6.46k
    UA_ByteString_clear(&transaction->localCsrCertificate);
313
314
6.46k
    if(transaction->certGroups) {
315
0
        for(size_t i = 0; i < transaction->certGroupSize; i++) {
316
0
            transaction->certGroups[i].clear(&transaction->certGroups[i]);
317
0
        }
318
0
        UA_free(transaction->certGroups);
319
0
        transaction->certGroupSize = 0;
320
0
        transaction->certGroups = NULL;
321
0
    }
322
323
6.46k
    if(transaction->certificateInfos) {
324
0
        for(size_t i = 0; i < transaction->certificateInfosSize; i++) {
325
0
            UA_ByteString_clear(&transaction->certificateInfos[i].certificate);
326
0
            UA_ByteString_clear(&transaction->certificateInfos[i].privateKey);
327
0
            UA_NodeId_clear(&transaction->certificateInfos[i].certificateGroup);
328
0
            UA_NodeId_clear(&transaction->certificateInfos[i].certificateType);
329
0
        }
330
0
        UA_free(transaction->certificateInfos);
331
0
        transaction->certificateInfosSize = 0;
332
0
        transaction->certificateInfos = NULL;
333
0
    }
334
6.46k
}
335
336
0
void UA_GDSTransaction_delete(UA_GDSTransaction *transaction) {
337
0
    UA_GDSTransaction_clear(transaction);
338
0
    UA_free(transaction);
339
0
}
340
341
#ifndef UA_ENABLE_GDS_PUSHMANAGEMENT
342
/* Minimal stub: when GDS push management is not compiled in,
343
 * only the embedded transaction needs to be cleared. */
344
void
345
6.46k
UA_GDSManager_clear(UA_GDSManager *gdsManager) {
346
6.46k
    if(!gdsManager)
347
0
        return;
348
6.46k
    gdsManager->checkSessionCallbackId = 0;
349
6.46k
    UA_GDSTransaction_clear(&gdsManager->transaction);
350
6.46k
}
351
#endif
352
353
/*********************/
354
/* Server Components */
355
/*********************/
356
357
enum ZIP_CMP
358
15.9k
cmpServerComponent(const UA_UInt64 *a, const UA_UInt64 *b) {
359
15.9k
    if(*a == *b)
360
0
        return ZIP_CMP_EQ;
361
15.9k
    return (*a < *b) ? ZIP_CMP_LESS : ZIP_CMP_MORE;
362
15.9k
}
363
364
void
365
addServerComponent(UA_Server *server, UA_ServerComponent *sc,
366
20.2k
                   UA_UInt64 *identifier) {
367
20.2k
    if(!sc)
368
0
        return;
369
370
20.2k
    sc->identifier = ++server->serverComponentIds;
371
20.2k
    ZIP_INSERT(UA_ServerComponentTree, &server->serverComponents, sc);
372
373
    /* Start the component if the server is started */
374
20.2k
    if(server->state == UA_LIFECYCLESTATE_STARTED && sc->start)
375
0
        sc->start(sc, server);
376
377
20.2k
    if(identifier)
378
0
        *identifier = sc->identifier;
379
20.2k
}
380
381
static void *
382
760
findServerComponent(void *context, UA_ServerComponent *sc) {
383
760
    UA_String *name = (UA_String*)context;
384
760
    return (UA_String_equal(&sc->name, name)) ? sc : NULL;
385
760
}
386
387
UA_ServerComponent *
388
516
getServerComponentByName(UA_Server *server, UA_String name) {
389
516
    return (UA_ServerComponent*)
390
516
        ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
391
516
                 findServerComponent, &name);
392
516
}
393
394
static void *
395
816
startServerComponent(void *server, UA_ServerComponent *sc) {
396
816
    sc->start(sc, (UA_Server*)server);
397
816
    return NULL;
398
816
}
399
400
static void *
401
816
stopServerComponent(void *_, UA_ServerComponent *sc) {
402
816
    sc->stop(sc);
403
816
    return NULL;
404
816
}
405
406
/* ZIP_ITER returns NULL only if all components are stopped */
407
static void *
408
1.08k
checkServerComponent(void *_, UA_ServerComponent *sc) {
409
1.08k
    return (sc->state == UA_LIFECYCLESTATE_STOPPED) ? NULL : (void*)0x01;
410
1.08k
}
411
412
/********************/
413
/* Server Lifecycle */
414
/********************/
415
416
/* The server needs to be stopped before it can be deleted */
417
UA_StatusCode
418
6.46k
UA_Server_delete(UA_Server *server) {
419
6.46k
    if(!server)
420
0
        return UA_STATUSCODE_BADINTERNALERROR;
421
422
6.46k
    if(server->state != UA_LIFECYCLESTATE_STOPPED) {
423
0
        UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
424
0
                     "The server must be fully stopped before it can be deleted");
425
0
        return UA_STATUSCODE_BADINTERNALERROR;
426
0
    }
427
428
6.46k
    lockServer(server);
429
430
6.46k
    session_list_entry *current, *temp;
431
6.46k
    LIST_FOREACH_SAFE(current, &server->sessions, pointers, temp) {
432
4.04k
        UA_Session_remove(server, &current->session, UA_SHUTDOWNREASON_CLOSE);
433
4.04k
    }
434
6.46k
    UA_Array_delete(server->namespaces, server->namespacesSize, &UA_TYPES[UA_TYPES_STRING]);
435
436
6.46k
#ifdef UA_ENABLE_SUBSCRIPTIONS
437
    /* Remove subscriptions without a session */
438
6.46k
    UA_Subscription *sub, *sub_tmp;
439
6.46k
    LIST_FOREACH_SAFE(sub, &server->subscriptions, serverListEntry, sub_tmp) {
440
0
        UA_Subscription_delete(server, sub);
441
0
    }
442
443
#ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS
444
    UA_ConditionList_delete(server);
445
#endif
446
447
6.46k
#endif
448
449
6.46k
#if UA_MULTITHREADING >= 100
450
6.46k
    UA_AsyncManager_clear(&server->asyncManager, server);
451
6.46k
#endif
452
453
    /* Clean up the Admin Session */
454
6.46k
    UA_Session_clear(&server->adminSession, server);
455
6.46k
#ifdef UA_ENABLE_SUBSCRIPTIONS
456
6.46k
    server->adminSubscription = NULL;
457
6.46k
    UA_assert(server->monitoredItemsSize == 0);
458
6.46k
    UA_assert(server->subscriptionsSize == 0);
459
6.46k
#endif
460
461
    /* Remove all server components (all stopped by now) */
462
6.46k
    UA_ServerComponent *top;
463
24.1k
    while((top = ZIP_ROOT(&server->serverComponents))) {
464
17.7k
        UA_assert(top->state == UA_LIFECYCLESTATE_STOPPED);
465
17.7k
        top->clear(top);
466
17.7k
        ZIP_REMOVE(UA_ServerComponentTree, &server->serverComponents, top);
467
17.7k
        UA_free(top);
468
17.7k
    }
469
470
6.46k
    unlockServer(server); /* The timer has its own mutex */
471
472
    /* Clean up the config */
473
6.46k
    UA_ServerConfig_clear(&server->config);
474
475
6.46k
#if UA_MULTITHREADING >= 100
476
6.46k
    UA_LOCK_DESTROY(&server->serviceMutex);
477
6.46k
#endif
478
479
6.46k
    UA_GDSManager_clear(&server->gdsManager);
480
481
    /* Clean up the custom datatypes */
482
6.46k
    if(server->customTypes_internal != NULL) {
483
0
        for(size_t i = 0; i < server->customTypes_internalSize; i++) {
484
0
            UA_DataTypeArray *curr = &server->customTypes_internal[i];
485
0
            for(size_t j = 0; j < curr->typesSize; j++)
486
0
                UA_DataType_clear(&curr->types[j]);
487
0
            UA_free(curr->types);
488
0
        }
489
0
        UA_free(server->customTypes_internal);
490
0
    }
491
492
    /* Delete the server itself and return */
493
6.46k
    UA_free(server);
494
6.46k
    return UA_STATUSCODE_GOOD;
495
6.46k
}
496
497
/* Regular house-keeping tasks. Removing unused and timed-out channels and
498
 * sessions. */
499
static void
500
0
serverHouseKeeping(UA_Server *server, void *_) {
501
0
    lockServer(server);
502
0
    UA_EventLoop *el = server->config.eventLoop;
503
0
    cleanupSessions(server, el->dateTime_nowMonotonic(el));
504
0
    unlockServer(server);
505
0
}
506
507
/********************/
508
/* Server Lifecycle */
509
/********************/
510
511
static
512
UA_INLINE
513
19.4k
UA_Boolean UA_Server_NodestoreIsConfigured(UA_Server *server) {
514
19.4k
    return (server->config.nodestore && server->config.nodestore->getNode);
515
19.4k
}
516
517
static UA_Server *
518
6.46k
UA_Server_init(UA_Server *server) {
519
6.46k
    UA_StatusCode res = UA_STATUSCODE_GOOD;
520
6.46k
    UA_CHECK_FATAL(UA_Server_NodestoreIsConfigured(server), goto cleanup,
521
6.46k
                   server->config.logging, UA_LOGCATEGORY_SERVER,
522
6.46k
                   "No Nodestore configured in the server");
523
524
    /* Init start time to zero, the actual start time will be sampled in
525
     * UA_Server_run_startup() */
526
6.46k
    server->startTime = 0;
527
528
    /* Set a seed for non-cyptographic randomness */
529
6.46k
#ifndef UA_ENABLE_DETERMINISTIC_RNG
530
6.46k
    UA_random_seed((UA_UInt64)UA_DateTime_now());
531
6.46k
#endif
532
533
6.46k
    UA_LOCK_INIT(&server->serviceMutex);
534
6.46k
    lockServer(server);
535
536
    /* Initialize the adminSession */
537
6.46k
    UA_Session_init(&server->adminSession);
538
6.46k
    server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID;
539
6.46k
    server->adminSession.sessionId.identifier.guid.data1 = 1;
540
6.46k
    server->adminSession.validTill = UA_INT64_MAX;
541
6.46k
    server->adminSession.sessionName = UA_STRING_ALLOC("Administrator");
542
543
6.46k
#ifdef UA_ENABLE_SUBSCRIPTIONS
544
    /* Initialize the adminSubscription */
545
6.46k
    server->adminSubscription = UA_Subscription_new();
546
6.46k
    UA_CHECK_MEM(server->adminSubscription, goto cleanup);
547
6.46k
    UA_Session_attachSubscription(&server->adminSession, server->adminSubscription);
548
6.46k
#endif
549
550
    /* Create Namespaces 0 and 1
551
     * Ns1 will be filled later with the uri from the app description */
552
6.46k
    server->namespaces = (UA_String *)UA_Array_new(2, &UA_TYPES[UA_TYPES_STRING]);
553
6.46k
    UA_CHECK_MEM(server->namespaces, goto cleanup);
554
555
6.46k
    server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/");
556
6.46k
    server->namespaces[1] = UA_STRING_NULL;
557
6.46k
    server->namespacesSize = 2;
558
559
    /* Initialize Session Management */
560
6.46k
    LIST_INIT(&server->sessions);
561
6.46k
    server->sessionCount = 0;
562
563
    /* Initialize SecureChannel */
564
6.46k
    TAILQ_INIT(&server->channels);
565
    /* TODO: use an ID that is likely to be unique after a restart */
566
6.46k
    server->lastChannelId = STARTCHANNELID;
567
6.46k
    server->lastTokenId = STARTTOKENID;
568
569
6.46k
#if UA_MULTITHREADING >= 100
570
6.46k
    UA_AsyncManager_init(&server->asyncManager, server);
571
6.46k
#endif
572
573
    /* Initialize namespace 0 */
574
6.46k
#if defined(UA_GENERATED_NAMESPACE_ZERO) || defined(UA_NAMESPACE_ZERO_MINIMAL)
575
    /* Generate NS0 nodes at runtime or create the minimal NS0 */
576
6.46k
    res = initNS0(server);
577
#else
578
    /* NONE configuration: NS0 pre-loaded by external nodestore (e.g., ROM).
579
     * Only connect data sources for dynamic values like ServerTime, ServerStatus, etc. */
580
    res = initNS0_dataSources(server);
581
#endif
582
6.46k
    UA_CHECK_STATUS(res, goto cleanup);
583
584
#ifdef UA_ENABLE_GDS_PUSHMANAGEMENT
585
    res = initNS0PushManagement(server);
586
    UA_CHECK_STATUS(res, goto cleanup);
587
#endif
588
589
#ifdef UA_ENABLE_NODESET_INJECTOR
590
    res = UA_Server_injectNodesets(server);
591
    UA_CHECK_STATUS(res, goto cleanup);
592
#endif
593
594
    /* Initialize the binay protocol support */
595
6.46k
    addServerComponent(server, UA_BinaryProtocolManager_new(server), NULL);
596
597
    /* Initialized Discovery */
598
6.46k
#ifdef UA_ENABLE_DISCOVERY
599
6.46k
    addServerComponent(server, UA_DiscoveryManager_new(), NULL);
600
6.46k
#endif
601
602
    /* Initialize PubSub */
603
6.46k
#ifdef UA_ENABLE_PUBSUB
604
6.46k
    if(server->config.pubsubEnabled)
605
6.46k
        addServerComponent(server, UA_PubSubManager_new(server), NULL);
606
6.46k
#endif
607
608
    /* For all custom datatypes, check if they are represented in the
609
     * information model. If not, add them. */
610
6.46k
#ifdef UA_ENABLE_TYPEDESCRIPTION
611
6.46k
    for(const UA_DataTypeArray *custom = server->config.customDataTypes;
612
6.46k
        custom != NULL; custom = custom->next) {
613
0
        for(size_t i = 0; i < custom->typesSize; i++) {
614
0
            const UA_DataType *type = &custom->types[i];
615
0
            if(type->typeKind != UA_DATATYPEKIND_STRUCTURE &&
616
0
               type->typeKind != UA_DATATYPEKIND_OPTSTRUCT &&
617
0
               type->typeKind != UA_DATATYPEKIND_UNION)
618
0
                continue;
619
0
            const UA_Node *node =
620
0
                UA_NODESTORE_GET_SELECTIVE(server, &type->typeId, 0,
621
0
                                           UA_REFERENCETYPESET_NONE,
622
0
                                           UA_BROWSEDIRECTION_INVALID);
623
0
            if(node) {
624
0
                UA_NODESTORE_RELEASE(server, node);
625
0
                continue;
626
0
            }
627
628
0
            UA_QualifiedName dataTypeBrowseName =
629
0
                {type->typeId.namespaceIndex, UA_STRING_STATIC((char*)(uintptr_t)type->typeName)};
630
0
            UA_DataTypeAttributes dta = UA_DataTypeAttributes_default;
631
0
            dta.displayName.text = UA_STRING((char*)(uintptr_t)type->typeName);
632
0
            res = UA_Server_addDataTypeNode(server, type->typeId, UA_NS0ID(STRUCTURE),
633
0
                                            UA_NS0ID(HASSUBTYPE), dataTypeBrowseName,
634
0
                                            dta, NULL, NULL);
635
0
            if(res != UA_STATUSCODE_GOOD) {
636
0
                UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER,
637
0
                               "Could not add DataTypeNode for %s (%N)",
638
0
                               type->typeName, type->typeId);
639
0
            }
640
0
        }
641
0
    }
642
6.46k
#endif
643
644
6.46k
    unlockServer(server);
645
6.46k
    return server;
646
647
0
 cleanup:
648
0
    unlockServer(server);
649
0
    UA_Server_delete(server);
650
0
    return NULL;
651
6.46k
}
652
653
UA_Server *
654
19.4k
UA_Server_newWithConfig(UA_ServerConfig *config) {
655
19.4k
    UA_CHECK_MEM(config, return NULL);
656
657
19.4k
    UA_CHECK_LOG(config->eventLoop != NULL, return NULL, ERROR,
658
19.4k
                 config->logging, UA_LOGCATEGORY_SERVER, "No EventLoop configured");
659
660
19.4k
    UA_Server *server = (UA_Server *)UA_calloc(1, sizeof(UA_Server));
661
19.4k
    UA_CHECK_MEM(server, UA_ServerConfig_clear(config); return NULL);
662
663
19.4k
    server->config = *config;
664
665
    /* If not defined, set logging to what the server has */
666
19.4k
    if(!server->config.secureChannelPKI.logging)
667
0
        server->config.secureChannelPKI.logging = server->config.logging;
668
19.4k
    if(!server->config.sessionPKI.logging)
669
0
        server->config.sessionPKI.logging = server->config.logging;
670
671
    /* Reset the old config */
672
19.4k
    memset(config, 0, sizeof(UA_ServerConfig));
673
19.4k
    return UA_Server_init(server);
674
19.4k
}
675
676
/* Returns if the server should be shut down immediately */
677
static UA_Boolean
678
0
setServerShutdown(UA_Server *server) {
679
0
    if(server->endTime != 0)
680
0
        return false;
681
0
    if(server->config.shutdownDelay == 0)
682
0
        return true;
683
684
0
    UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER,
685
0
                   "Shutting down the server with a delay of %i ms",
686
0
                   (int)server->config.shutdownDelay);
687
688
0
    UA_EventLoop *el = server->config.eventLoop;
689
0
    server->endTime = el->dateTime_now(el) + (UA_DateTime)(server->config.shutdownDelay * UA_DATETIME_MSEC);
690
691
    /* Call the application notification callback */
692
0
    UA_ServerConfig *config = &server->config;
693
0
    if(config->lifecycleNotificationCallback)
694
0
        config->lifecycleNotificationCallback(server, UA_APPLICATIONNOTIFICATIONTYPE_LIFECYCLE_SHUTDOWN,
695
0
                                              UA_KEYVALUEMAP_NULL);
696
0
    if(config->globalNotificationCallback)
697
0
        config->globalNotificationCallback(server, UA_APPLICATIONNOTIFICATIONTYPE_LIFECYCLE_SHUTDOWN,
698
0
                                           UA_KEYVALUEMAP_NULL);
699
700
0
    return false;
701
0
}
702
703
/*******************/
704
/* Timed Callbacks */
705
/*******************/
706
707
UA_StatusCode
708
UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback,
709
0
                           void *data, UA_DateTime date, UA_UInt64 *callbackId) {
710
0
    lockServer(server);
711
0
    UA_EventLoop *el = server->config.eventLoop;
712
0
    UA_StatusCode retval = el->addTimer(el, (UA_Callback)callback, server, data,
713
0
                                        0.0, &date, UA_TIMERPOLICY_ONCE, callbackId);
714
0
    unlockServer(server);
715
0
    return retval;
716
0
}
717
718
UA_StatusCode
719
addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
720
2.64k
                    void *data, UA_Double interval_ms, UA_UInt64 *callbackId) {
721
2.64k
    UA_LOCK_ASSERT(&server->serviceMutex);
722
2.64k
    UA_EventLoop *el = server->config.eventLoop;
723
2.64k
    return el->addTimer(el, (UA_Callback)callback, server, data, interval_ms, NULL,
724
2.64k
                        UA_TIMERPOLICY_CURRENTTIME, callbackId);
725
2.64k
}
726
727
UA_StatusCode
728
UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback,
729
                              void *data, UA_Double interval_ms,
730
0
                              UA_UInt64 *callbackId) {
731
0
    lockServer(server);
732
0
    UA_StatusCode res = addRepeatedCallback(server, callback, data, interval_ms, callbackId);
733
0
    unlockServer(server);
734
0
    return res;
735
0
}
736
737
UA_StatusCode
738
changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
739
0
                               UA_Double interval_ms) {
740
0
    UA_LOCK_ASSERT(&server->serviceMutex);
741
0
    UA_EventLoop *el = server->config.eventLoop;
742
0
    return el->modifyTimer(el, callbackId, interval_ms, NULL, UA_TIMERPOLICY_CURRENTTIME);
743
0
}
744
745
UA_StatusCode
746
UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId,
747
0
                                         UA_Double interval_ms) {
748
0
    lockServer(server);
749
0
    UA_StatusCode retval = changeRepeatedCallbackInterval(server, callbackId, interval_ms);
750
0
    unlockServer(server);
751
0
    return retval;
752
0
}
753
754
void
755
2.64k
removeCallback(UA_Server *server, UA_UInt64 callbackId) {
756
2.64k
    UA_LOCK_ASSERT(&server->serviceMutex);
757
2.64k
    UA_EventLoop *el = server->config.eventLoop;
758
2.64k
    el->removeTimer(el, callbackId);
759
2.64k
}
760
761
void
762
0
UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId) {
763
0
    lockServer(server);
764
0
    removeCallback(server, callbackId);
765
0
    unlockServer(server);
766
0
}
767
768
/* When the trustlist changes, re-check the certificates of all
769
 * SecureChannels */
770
static void
771
0
secureChannel_delayedCloseTrustList(void *application, void *context) {
772
0
    UA_DelayedCallback *dc = (UA_DelayedCallback*)context;
773
0
    UA_Server *server = (UA_Server*)application;
774
775
0
    UA_CertificateGroup *certGroup = &server->config.secureChannelPKI;
776
0
    UA_SecureChannel *channel;
777
0
    TAILQ_FOREACH(channel, &server->channels, serverEntry) {
778
0
        if(channel->state != UA_SECURECHANNELSTATE_CLOSED &&
779
0
           channel->state != UA_SECURECHANNELSTATE_CLOSING)
780
0
            continue;
781
0
        if(channel->remoteCertificate.length == 0)
782
0
            continue; /* SecureChannels w/o security */
783
0
        UA_StatusCode res =
784
0
            validateCertificate(server, certGroup, channel, channel->sessions,
785
0
                                "RenewTrustList", NULL, channel->remoteCertificate);
786
0
        if(res != UA_STATUSCODE_GOOD)
787
0
            UA_SecureChannel_shutdown(channel, UA_SHUTDOWNREASON_CLOSE);
788
0
    }
789
0
    UA_free(dc);
790
0
}
791
792
static UA_CertificateGroup*
793
0
getCertificateGroup(UA_Server *server, const UA_NodeId certificateGroupId) {
794
0
    UA_NodeId defaultApplicationGroup =
795
0
        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP);
796
0
    UA_NodeId defaultUserTokenGroup =
797
0
        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP);
798
0
    if(UA_NodeId_equal(&certificateGroupId, &defaultApplicationGroup)) {
799
0
        return &server->config.secureChannelPKI;
800
0
    }
801
0
    if(UA_NodeId_equal(&certificateGroupId, &defaultUserTokenGroup)) {
802
0
        return &server->config.sessionPKI;
803
0
    }
804
0
    return NULL;
805
0
}
806
807
UA_StatusCode
808
UA_Server_addCertificates(UA_Server *server,
809
                          const UA_NodeId certificateGroupId,
810
                          UA_ByteString *certificates,
811
                          size_t certificatesSize,
812
                          UA_ByteString *crls,
813
                          size_t crlsSize,
814
                          const UA_Boolean isTrusted,
815
0
                          const UA_Boolean appendCertificates) {
816
0
    UA_CertificateGroup *certGroup = getCertificateGroup(server, certificateGroupId);
817
0
    if(!certGroup)
818
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
819
820
0
    UA_TrustListDataType trustList;
821
0
    UA_TrustListDataType_init(&trustList);
822
823
0
    if(isTrusted) {
824
0
        trustList.specifiedLists = UA_TRUSTLISTMASKS_TRUSTEDCERTIFICATES | UA_TRUSTLISTMASKS_TRUSTEDCRLS;
825
0
        trustList.trustedCertificates = certificates;
826
0
        trustList.trustedCertificatesSize = certificatesSize;
827
0
        trustList.trustedCrls = crls;
828
0
        trustList.trustedCrlsSize = crlsSize;
829
0
    } else {
830
0
        trustList.specifiedLists = UA_TRUSTLISTMASKS_ISSUERCERTIFICATES | UA_TRUSTLISTMASKS_ISSUERCRLS;
831
0
        trustList.issuerCertificates = certificates;
832
0
        trustList.issuerCertificatesSize = certificatesSize;
833
0
        trustList.issuerCrls = crls;
834
0
        trustList.issuerCrlsSize = crlsSize;
835
0
    }
836
837
    /* When adding certificate files to the TrustList,
838
     * it is not necessary to check the trust status of the existing SecureChannels. */
839
0
    if(appendCertificates)
840
0
        return certGroup->addToTrustList(certGroup, &trustList);
841
842
0
    UA_StatusCode retval = certGroup->setTrustList(certGroup, &trustList);
843
0
    if(retval != UA_STATUSCODE_GOOD)
844
0
        return retval;
845
846
0
    UA_DelayedCallback *dc = (UA_DelayedCallback*)UA_calloc(1, sizeof(UA_DelayedCallback));
847
0
    if(!dc)
848
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
849
850
0
    dc->callback = secureChannel_delayedCloseTrustList;
851
0
    dc->application = server;
852
0
    dc->context = dc;
853
854
0
    UA_EventLoop *el = server->config.eventLoop;
855
0
    el->addDelayedCallback(el, dc);
856
857
0
    return UA_STATUSCODE_GOOD;
858
0
}
859
860
UA_StatusCode
861
UA_Server_removeCertificates(UA_Server *server,
862
                             const UA_NodeId certificateGroupId,
863
                             UA_ByteString *certificates,
864
                             size_t certificatesSize,
865
0
                             const UA_Boolean isTrusted) {
866
0
    UA_CertificateGroup *certGroup = getCertificateGroup(server, certificateGroupId);
867
0
    if(!certGroup)
868
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
869
870
0
    UA_ByteString *crls = NULL;
871
0
    size_t crlsSize = 0;
872
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
873
0
    for(size_t i = 0; i < certificatesSize; i++) {
874
0
        retval = certGroup->getCertificateCrls(certGroup, &certificates[i], isTrusted, &crls, &crlsSize);
875
        /* Tolerate "Bad_NoMatch" to support removing CA certificates that do
876
         * not have an associated CRL. */
877
0
        if((retval != UA_STATUSCODE_GOOD) && (retval != UA_STATUSCODE_BADNOMATCH)) {
878
0
            UA_Array_delete(crls, crlsSize, &UA_TYPES[UA_TYPES_BYTESTRING]);
879
0
            return retval;
880
0
        }
881
0
    }
882
883
0
    UA_TrustListDataType trustList;
884
0
    UA_TrustListDataType_init(&trustList);
885
0
    if(isTrusted) {
886
0
        trustList.specifiedLists = UA_TRUSTLISTMASKS_TRUSTEDCERTIFICATES | UA_TRUSTLISTMASKS_TRUSTEDCRLS;
887
0
        trustList.trustedCertificates = certificates;
888
0
        trustList.trustedCertificatesSize = certificatesSize;
889
0
        trustList.trustedCrls = crls;
890
0
        trustList.trustedCrlsSize = crlsSize;
891
0
    } else {
892
0
        trustList.specifiedLists = UA_TRUSTLISTMASKS_ISSUERCERTIFICATES | UA_TRUSTLISTMASKS_ISSUERCRLS;
893
0
        trustList.issuerCertificates = certificates;
894
0
        trustList.issuerCertificatesSize = certificatesSize;
895
0
        trustList.issuerCrls = crls;
896
0
        trustList.issuerCrlsSize = crlsSize;
897
0
    }
898
899
0
    retval = certGroup->removeFromTrustList(certGroup, &trustList);
900
0
    UA_Array_delete(crls, crlsSize, &UA_TYPES[UA_TYPES_BYTESTRING]);
901
0
    if(retval != UA_STATUSCODE_GOOD)
902
0
        return retval;
903
904
0
    UA_DelayedCallback *dc = (UA_DelayedCallback*)UA_calloc(1, sizeof(UA_DelayedCallback));
905
0
    if(!dc)
906
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
907
908
0
    dc->callback = secureChannel_delayedCloseTrustList;
909
0
    dc->application = server;
910
0
    dc->context = dc;
911
912
0
    UA_EventLoop *el = server->config.eventLoop;
913
0
    el->addDelayedCallback(el, dc);
914
915
0
    return UA_STATUSCODE_GOOD;
916
0
}
917
918
typedef struct UpdateCertInfo {
919
    UA_Server *server;
920
    UA_NodeId certificateTypeId;
921
} UpdateCertInfo;
922
923
static void
924
0
secureChannel_delayedClose(void *application, void *context) {
925
0
    UA_DelayedCallback *dc = (UA_DelayedCallback*)context;
926
0
    UpdateCertInfo *info = (UpdateCertInfo*)application;
927
928
0
    UA_SecureChannel *channel;
929
0
    TAILQ_FOREACH(channel, &info->server->channels, serverEntry) {
930
0
        const UA_SecurityPolicy *policy = channel->securityPolicy;
931
0
        if(UA_NodeId_equal(&policy->certificateTypeId, &(info->certificateTypeId)))
932
0
            UA_SecureChannel_shutdown(channel, UA_SHUTDOWNREASON_CLOSE);
933
0
    }
934
0
    UA_NodeId_clear(&(info->certificateTypeId));
935
0
    UA_free(info);
936
0
    UA_free(dc);
937
0
}
938
939
UA_StatusCode
940
UA_Server_updateCertificate(UA_Server *server,
941
                            const UA_NodeId certificateGroupId,
942
                            const UA_NodeId certificateTypeId,
943
                            const UA_ByteString certificate,
944
0
                            const UA_ByteString *privateKey) {
945
0
    if(!server)
946
0
        return UA_STATUSCODE_BADINTERNALERROR;
947
948
0
    lockServer(server);
949
950
0
    if(server->gdsManager.transaction.state == UA_GDSTRANSACTIONSTATE_PENDING) {
951
0
        unlockServer(server);
952
0
        return UA_STATUSCODE_BADTRANSACTIONPENDING;
953
0
    }
954
955
0
    UA_NodeId defaultApplicationGroup = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP);
956
0
    UA_NodeId certGroupId = certificateGroupId;
957
0
    if(UA_NodeId_isNull(&certGroupId)) {
958
        /* Use default value if argument is empty */
959
0
        certGroupId = defaultApplicationGroup;
960
0
    }
961
    /* The server currently only supports the DefaultApplicationGroup */
962
0
    if(!UA_NodeId_equal(&certGroupId, &defaultApplicationGroup)) {
963
0
        unlockServer(server);
964
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
965
0
    }
966
967
    /* The server currently only supports the following certificate type */
968
    /* UA_NodeId certTypRsaMin = UA_NODEID_NUMERIC(0, UA_NS0ID_RSAMINAPPLICATIONCERTIFICATETYPE); */
969
0
    UA_NodeId certTypRsaSha256 = UA_NODEID_NUMERIC(0, UA_NS0ID_RSASHA256APPLICATIONCERTIFICATETYPE);
970
0
    if(!UA_NodeId_equal(&certificateTypeId, &certTypRsaSha256)) {
971
0
        unlockServer(server);
972
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
973
0
    }
974
975
0
    UA_ByteString newPrivateKey = UA_BYTESTRING_NULL;
976
0
    if(privateKey) {
977
0
        if(UA_CertificateUtils_checkKeyPair(&certificate, privateKey) != UA_STATUSCODE_GOOD) {
978
0
            unlockServer(server);
979
0
            return UA_STATUSCODE_BADNOTSUPPORTED;
980
0
        }
981
0
        newPrivateKey = *privateKey;
982
0
    } else {
983
0
#ifdef UA_ENABLE_ENCRYPTION
984
        /* No key to pair the certificate with, so check that it parses */
985
0
        size_t keySize = 0;
986
0
        if(UA_CertificateUtils_getKeySize((UA_ByteString*)(uintptr_t)&certificate,
987
0
                                          &keySize) != UA_STATUSCODE_GOOD) {
988
0
            unlockServer(server);
989
0
            return UA_STATUSCODE_BADCERTIFICATEINVALID;
990
0
        }
991
0
#endif
992
0
    }
993
994
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
995
0
    for(size_t i = 0; i < server->config.endpointsSize; i++) {
996
0
        UA_EndpointDescription *ed = &server->config.endpoints[i];
997
0
        UA_SecurityPolicy *sp = getSecurityPolicyByUri(server,
998
0
                            &server->config.endpoints[i].securityPolicyUri);
999
0
        UA_CHECK_MEM(sp, unlockServer(server); return UA_STATUSCODE_BADINTERNALERROR);
1000
1001
0
        if(!UA_NodeId_equal(&sp->certificateTypeId, &certificateTypeId))
1002
0
            continue;
1003
1004
0
        retval = sp->updateCertificate(sp, certificate, newPrivateKey);
1005
0
        if(retval != UA_STATUSCODE_GOOD) {
1006
0
            unlockServer(server);
1007
0
            return retval;
1008
0
        }
1009
1010
0
        UA_ByteString_clear(&ed->serverCertificate);
1011
0
        UA_ByteString_copy(&certificate, &ed->serverCertificate);
1012
0
    }
1013
1014
0
    UA_DelayedCallback *dc = (UA_DelayedCallback*)UA_calloc(1, sizeof(UA_DelayedCallback));
1015
0
    if(!dc) {
1016
0
        unlockServer(server);
1017
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
1018
0
    }
1019
1020
0
    UpdateCertInfo *certInfo = (UpdateCertInfo*)UA_calloc(1, sizeof(UpdateCertInfo));
1021
0
    certInfo->server = server;
1022
0
    UA_NodeId_copy(&certificateTypeId, &(certInfo->certificateTypeId));
1023
1024
0
    dc->callback = secureChannel_delayedClose;
1025
0
    dc->application = certInfo;
1026
0
    dc->context = dc;
1027
1028
0
    UA_EventLoop *el = server->config.eventLoop;
1029
0
    el->addDelayedCallback(el, dc);
1030
1031
0
    unlockServer(server);
1032
0
    return UA_STATUSCODE_GOOD;
1033
0
}
1034
1035
UA_StatusCode
1036
UA_Server_createSigningRequest(UA_Server *server,
1037
                               const UA_NodeId certificateGroupId,
1038
                               const UA_NodeId certificateTypeId,
1039
                               const UA_String *subjectName,
1040
                               const UA_Boolean *regenerateKey,
1041
                               const UA_ByteString *nonce,
1042
0
                               UA_ByteString *csr) {
1043
0
    if(!server || !csr)
1044
0
        return UA_STATUSCODE_BADINTERNALERROR;
1045
1046
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
1047
0
    UA_NodeId defaultApplicationGroup = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP);
1048
0
    UA_NodeId certGroupId = certificateGroupId;
1049
0
    if(UA_NodeId_isNull(&certGroupId)) {
1050
        /* Use default value if argument is empty */
1051
0
        certGroupId = defaultApplicationGroup;
1052
0
    }
1053
    /* The server currently only supports the DefaultApplicationGroup */
1054
0
    if(!UA_NodeId_equal(&certGroupId, &defaultApplicationGroup))
1055
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
1056
1057
    /* The server currently only supports RSA CertificateType */
1058
0
    UA_NodeId rsaShaCertificateType = UA_NODEID_NUMERIC(0, UA_NS0ID_RSASHA256APPLICATIONCERTIFICATETYPE);
1059
0
    UA_NodeId rsaMinCertificateType = UA_NODEID_NUMERIC(0,UA_NS0ID_RSAMINAPPLICATIONCERTIFICATETYPE);
1060
0
    if(!UA_NodeId_equal(&certificateTypeId, &rsaShaCertificateType) &&
1061
0
       !UA_NodeId_equal(&certificateTypeId, &rsaMinCertificateType))
1062
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
1063
1064
0
    UA_CertificateGroup certGroup = server->config.secureChannelPKI;
1065
1066
0
    if(!UA_NodeId_equal(&certGroup.certificateGroupId, &defaultApplicationGroup))
1067
0
        return UA_STATUSCODE_BADINTERNALERROR;
1068
1069
0
    UA_ByteString *newPrivateKey = NULL;
1070
0
    if(regenerateKey && *regenerateKey == true)
1071
0
        newPrivateKey = UA_ByteString_new();
1072
1073
0
    for(size_t i = 0; i < server->config.endpointsSize; i++) {
1074
0
        UA_SecurityPolicy *sp =
1075
0
            getSecurityPolicyByUri(server, &server->config.endpoints[i].securityPolicyUri);
1076
0
        if(!sp) {
1077
0
            retval = UA_STATUSCODE_BADINTERNALERROR;
1078
0
            goto cleanup;
1079
0
        }
1080
1081
0
        if(sp->policyType == UA_SECURITYPOLICYTYPE_NONE)
1082
0
            continue;
1083
1084
0
        if(UA_NodeId_equal(&certificateTypeId, &sp->certificateTypeId) &&
1085
0
           UA_NodeId_equal(&certGroupId, &sp->certificateGroupId)) {
1086
0
            retval = sp->createSigningRequest(sp, subjectName, nonce,
1087
0
                                              &UA_KEYVALUEMAP_NULL, csr, newPrivateKey);
1088
0
            if(retval != UA_STATUSCODE_GOOD)
1089
0
                goto cleanup;
1090
0
        }
1091
0
    }
1092
1093
0
    UA_ByteString_clear(&server->gdsManager.transaction.localCsrCertificate);
1094
0
    UA_ByteString_copy(csr, &server->gdsManager.transaction.localCsrCertificate);
1095
1096
0
cleanup:
1097
0
    if(newPrivateKey)
1098
0
    {
1099
        /* wipe private key before freeing its memory */
1100
0
        UA_ByteString_memZero(newPrivateKey);
1101
0
        UA_ByteString_delete(newPrivateKey);
1102
0
    }
1103
1104
0
    return retval;
1105
0
}
1106
1107
/***************************/
1108
/* Server lookup functions */
1109
/***************************/
1110
1111
UA_SecurityPolicy *
1112
10.9k
getSecurityPolicyByUri(const UA_Server *server, const UA_String *securityPolicyUri) {
1113
10.9k
    for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
1114
10.9k
        UA_SecurityPolicy *sp = &server->config.securityPolicies[i];
1115
10.9k
        if(UA_String_equal(securityPolicyUri, &sp->policyUri))
1116
10.9k
            return sp;
1117
10.9k
    }
1118
0
    return NULL;
1119
10.9k
}
1120
1121
UA_SecurityPolicy *
1122
0
getSecurityPolicyByPostfix(const UA_Server *server, const UA_String uriPostfix) {
1123
0
    for(size_t i = 0; i < server->config.securityPoliciesSize; i++) {
1124
0
        UA_SecurityPolicy *sp = &server->config.securityPolicies[i];
1125
0
        UA_String spPostfix = securityPolicyUriPostfix(sp->policyUri);
1126
0
        if(UA_String_equal(&uriPostfix, &spPostfix))
1127
0
            return sp;
1128
0
    }
1129
0
    return NULL;
1130
0
}
1131
1132
/* The local ApplicationUri has to match the certificates of the
1133
 * SecurityPolicies */
1134
static void
1135
536
verifyServerApplicationUri(const UA_Server *server) {
1136
#if UA_LOGLEVEL <= 400
1137
    const UA_ServerConfig *sc = &server->config;
1138
    for(size_t i = 0; i < sc->securityPoliciesSize; i++) {
1139
        UA_SecurityPolicy *sp = &sc->securityPolicies[i];
1140
        if(sp->policyType == UA_SECURITYPOLICYTYPE_NONE &&
1141
           sp->localCertificate.length == 0)
1142
            continue;
1143
        UA_StatusCode retval =
1144
            UA_CertificateUtils_verifyApplicationUri(&sp->localCertificate,
1145
                                &sc->applicationDescription.applicationUri);
1146
        if(retval != UA_STATUSCODE_GOOD) {
1147
            UA_LOG_WARNING(sc->logging, UA_LOGCATEGORY_SERVER,
1148
                           "The ApplicationUri %S in the server's ApplicationDescription "
1149
                           "does not match the URI specified in the certificate "
1150
                           "for the SecurityPolicy %S",
1151
                           server->config.applicationDescription.applicationUri,
1152
                           sp->policyUri);
1153
        }
1154
    }
1155
#endif
1156
536
}
1157
1158
UA_ServerStatistics
1159
0
UA_Server_getStatistics(UA_Server *server) {
1160
0
    UA_ServerStatistics stat;
1161
0
    lockServer(server);
1162
0
    stat.scs = server->secureChannelStatistics;
1163
0
    UA_ServerDiagnosticsSummaryDataType *sds = &server->serverDiagnosticsSummary;
1164
0
    stat.ss.currentSessionCount = server->activeSessionCount;
1165
0
    stat.ss.cumulatedSessionCount = sds->cumulatedSessionCount;
1166
0
    stat.ss.securityRejectedSessionCount = sds->securityRejectedSessionCount;
1167
0
    stat.ss.rejectedSessionCount = sds->rejectedSessionCount;
1168
0
    stat.ss.sessionTimeoutCount = sds->sessionTimeoutCount;
1169
0
    stat.ss.sessionAbortCount = sds->sessionAbortCount;
1170
0
    unlockServer(server);
1171
0
    return stat;
1172
0
}
1173
1174
/********************/
1175
/* Main Server Loop */
1176
/********************/
1177
1178
476
#define UA_MAXTIMEOUT 500 /* Max timeout in ms between main-loop iterations */
1179
1180
void
1181
816
setServerLifecycleState(UA_Server *server, UA_LifecycleState state) {
1182
816
    UA_LOCK_ASSERT(&server->serviceMutex);
1183
1184
    /* Not state change, nothing to do */
1185
816
    if(server->state == state)
1186
0
        return;
1187
1188
816
    server->state = state; /* Apply the state change */
1189
1190
    /* Call the application notification callback */
1191
816
    UA_ServerConfig *config = &server->config;
1192
816
    if(config->globalNotificationCallback || config->lifecycleNotificationCallback) {
1193
0
        UA_ApplicationNotificationType nt = UA_APPLICATIONNOTIFICATIONTYPE_LIFECYCLE_STARTED;
1194
0
        switch(state) {
1195
0
        case UA_LIFECYCLESTATE_STOPPED: nt = UA_APPLICATIONNOTIFICATIONTYPE_LIFECYCLE_STOPPED; break;
1196
0
        case UA_LIFECYCLESTATE_STOPPING: nt = UA_APPLICATIONNOTIFICATIONTYPE_LIFECYCLE_STOPPING; break;
1197
0
        default: break;
1198
0
        }
1199
0
        if(config->lifecycleNotificationCallback)
1200
0
            config->lifecycleNotificationCallback(server, nt, UA_KEYVALUEMAP_NULL);
1201
0
        if(config->globalNotificationCallback)
1202
0
            config->globalNotificationCallback(server, nt, UA_KEYVALUEMAP_NULL);
1203
0
    }
1204
1205
    /* Call the (legacy) notification callback */
1206
816
    if(server->config.notifyLifecycleState)
1207
0
        server->config.notifyLifecycleState(server, state);
1208
816
}
1209
1210
UA_LifecycleState
1211
0
UA_Server_getLifecycleState(UA_Server *server) {
1212
0
    return server->state;
1213
0
}
1214
1215
/* Start: Spin up the workers and the network layer and sample the server's
1216
 *        start time.
1217
 * Iterate: Process repeated callbacks and events in the network layer. This
1218
 *          part can be driven from an external main-loop in an event-driven
1219
 *          single-threaded architecture.
1220
 * Stop: Stop workers, finish all callbacks, stop the network layer, clean up */
1221
1222
UA_StatusCode
1223
272
UA_Server_run_startup(UA_Server *server) {
1224
272
    if(server == NULL) {
1225
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
1226
0
    }
1227
272
    UA_ServerConfig *config = &server->config;
1228
1229
272
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1230
    /* Prominently warn user that fuzzing build is enabled. This will tamper
1231
     * with authentication tokens and other important variables E.g. if fuzzing
1232
     * is enabled, and two clients are connected, subscriptions do not work
1233
     * properly, since the tokens will be overridden to allow easier fuzzing. */
1234
272
    UA_LOG_FATAL(server->config.logging, UA_LOGCATEGORY_SERVER,
1235
272
                 "Server was built with unsafe fuzzing mode. "
1236
272
                 "This should only be used for specific fuzzing builds.");
1237
272
#endif
1238
1239
272
    if(server->state != UA_LIFECYCLESTATE_STOPPED) {
1240
0
        UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
1241
0
                       "The server has already been started");
1242
0
        return UA_STATUSCODE_BADINTERNALERROR;
1243
0
    }
1244
1245
    /* Check if UserIdentityTokens are defined */
1246
272
    bool hasUserIdentityTokens = false;
1247
544
    for(size_t i = 0; i < config->endpointsSize; i++) {
1248
272
        if(config->endpoints[i].userIdentityTokensSize > 0) {
1249
0
            hasUserIdentityTokens = true;
1250
0
            break;
1251
0
        }
1252
272
    }
1253
272
    if(config->accessControl.userTokenPoliciesSize == 0 && hasUserIdentityTokens == false) {
1254
0
        UA_LOG_ERROR(config->logging, UA_LOGCATEGORY_SERVER,
1255
0
                     "The server has no userIdentificationPolicies defined.");
1256
0
        return UA_STATUSCODE_BADINTERNALERROR;
1257
0
    }
1258
1259
    /* Start the EventLoop if not already started */
1260
272
    UA_StatusCode retVal = UA_STATUSCODE_GOOD;
1261
272
    UA_EventLoop *el = config->eventLoop;
1262
272
    UA_CHECK_MEM_ERROR(el, return UA_STATUSCODE_BADINTERNALERROR,
1263
272
                       config->logging, UA_LOGCATEGORY_SERVER,
1264
272
                       "An EventLoop must be configured");
1265
1266
272
    if(el->state != UA_EVENTLOOPSTATE_STARTED) {
1267
0
        retVal = el->start(el);
1268
0
        UA_CHECK_STATUS(retVal, return retVal); /* Errors are logged internally */
1269
0
    }
1270
1271
    /* Take the server lock */
1272
272
    lockServer(server);
1273
1274
    /* Does the ApplicationUri match the local certificates? */
1275
272
    verifyServerApplicationUri(server);
1276
1277
272
#if UA_MULTITHREADING >= 100
1278
    /* Add regulare callback for async operation processing */
1279
272
    UA_AsyncManager_start(&server->asyncManager, server);
1280
272
#endif
1281
1282
    /* Are there enough SecureChannels possible for the max number of sessions? */
1283
272
    if(config->maxSecureChannels != 0 &&
1284
272
       (config->maxSessions == 0 || config->maxSessions > config->maxSecureChannels)) {
1285
0
        UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
1286
0
                       "Maximum SecureChannels count not enough for the "
1287
0
                       "maximum Sessions count");
1288
0
    }
1289
1290
    /* Add a regular callback for housekeeping tasks. With a 1s interval. */
1291
272
    retVal = addRepeatedCallback(server, serverHouseKeeping,
1292
272
                                 NULL, 1000.0, &server->houseKeepingCallbackId);
1293
272
    UA_CHECK_STATUS_ERROR(retVal, unlockServer(server); return retVal,
1294
272
                          config->logging, UA_LOGCATEGORY_SERVER,
1295
272
                          "Could not create the server housekeeping task");
1296
1297
    /* Ensure that the uri for ns1 is set up from the app description */
1298
272
    UA_String_clear(&server->namespaces[1]);
1299
272
    setupNs1Uri(server);
1300
1301
    /* At least one endpoint has to be configured */
1302
272
    if(config->endpointsSize == 0) {
1303
0
        UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
1304
0
                       "There has to be at least one endpoint.");
1305
0
    }
1306
1307
    /* Update Endpoint description */
1308
544
    for(size_t i = 0; i < config->endpointsSize; ++i) {
1309
272
        UA_ApplicationDescription_clear(&config->endpoints[i].server);
1310
272
        UA_ApplicationDescription_copy(&config->applicationDescription,
1311
272
                                       &config->endpoints[i].server);
1312
272
    }
1313
1314
    /* Write ServerArray with same ApplicationUri value as NamespaceArray */
1315
272
    UA_Variant var;
1316
272
    UA_Variant_init(&var);
1317
272
    UA_Variant_setArray(&var, &config->applicationDescription.applicationUri,
1318
272
                        1, &UA_TYPES[UA_TYPES_STRING]);
1319
272
    UA_NodeId serverArray = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERARRAY);
1320
272
    writeValueAttribute(server, serverArray, &var);
1321
1322
    /* Sample the start time and set it to the Server object */
1323
272
    server->startTime = el->dateTime_now(el);
1324
272
    UA_Variant_init(&var);
1325
272
    UA_Variant_setScalar(&var, &server->startTime, &UA_TYPES[UA_TYPES_DATETIME]);
1326
272
    UA_NodeId startTime =
1327
272
        UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME);
1328
272
    writeValueAttribute(server, startTime, &var);
1329
1330
    /* Start all ServerComponents */
1331
272
    ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
1332
272
             startServerComponent, server);
1333
1334
    /* Check that the binary protocol support component have been started */
1335
272
    UA_ServerComponent *binaryProtocolManager =
1336
272
        getServerComponentByName(server, UA_STRING("binary"));
1337
272
    if(!binaryProtocolManager) {
1338
0
        UA_LOG_ERROR(config->logging, UA_LOGCATEGORY_SERVER,
1339
0
                     "Binary protocol support component not found.");
1340
        /* Stop all server components that have already been started */
1341
0
        ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
1342
0
                 stopServerComponent, server);
1343
0
        unlockServer(server);
1344
0
        return UA_STATUSCODE_BADINTERNALERROR;
1345
0
    }
1346
272
    if(binaryProtocolManager->state != UA_LIFECYCLESTATE_STARTED) {
1347
0
        UA_LOG_ERROR(config->logging, UA_LOGCATEGORY_SERVER,
1348
0
                       "The binary protocol support component could not been started.");
1349
        /* Stop all server components that have already been started */
1350
0
        ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
1351
0
                 stopServerComponent, NULL);
1352
0
        unlockServer(server);
1353
0
        return UA_STATUSCODE_BADINTERNALERROR;
1354
0
    }
1355
1356
    /* Set the server to STARTED. From here on, only use
1357
     * UA_Server_run_shutdown(server) to stop the server. */
1358
272
    setServerLifecycleState(server, UA_LIFECYCLESTATE_STARTED);
1359
1360
272
    unlockServer(server);
1361
272
    return UA_STATUSCODE_GOOD;
1362
272
}
1363
1364
UA_UInt16
1365
1.59k
UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
1366
    /* Make sure an EventLoop is configured */
1367
1.59k
    UA_EventLoop *el = server->config.eventLoop;
1368
1.59k
    if(!el)
1369
0
        return 0;
1370
1371
    /* Process timed and network events in the EventLoop */
1372
1.59k
    UA_UInt32 timeout = (waitInternal) ? UA_MAXTIMEOUT : 0;
1373
1.59k
    el->run(el, timeout);
1374
1375
    /* Return the time until the next scheduled callback */
1376
1.59k
    UA_DateTime now = el->dateTime_nowMonotonic(el);
1377
1.59k
    UA_DateTime nextTimeout = (el->nextTimer(el) - now) / UA_DATETIME_MSEC;
1378
1.59k
    if(nextTimeout < 0)
1379
0
        nextTimeout = 0;
1380
1.59k
    if(nextTimeout > UA_UINT16_MAX)
1381
272
        nextTimeout = UA_UINT16_MAX;
1382
1.59k
    return (UA_UInt16)nextTimeout;
1383
1.59k
}
1384
1385
static UA_Boolean
1386
0
testShutdownCondition(UA_Server *server) {
1387
    /* Was there a wait time until the shutdown configured? */
1388
0
    if(server->endTime == 0)
1389
0
        return false;
1390
0
    UA_EventLoop *el = server->config.eventLoop;
1391
0
    return (el->dateTime_now(el) > server->endTime);
1392
0
}
1393
1394
static UA_Boolean
1395
544
testStoppedCondition(UA_Server *server) {
1396
    /* Check if there are remaining server components that did not fully stop */
1397
544
    if(ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
1398
544
                checkServerComponent, NULL) != NULL)
1399
272
        return false;
1400
272
    return true;
1401
544
}
1402
1403
UA_StatusCode
1404
272
UA_Server_run_shutdown(UA_Server *server) {
1405
272
    if(server == NULL)
1406
0
        return UA_STATUSCODE_BADINVALIDARGUMENT;
1407
1408
272
    lockServer(server);
1409
1410
272
    if(server->state != UA_LIFECYCLESTATE_STARTED) {
1411
0
        UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
1412
0
                     "The server is not started, cannot be shut down");
1413
0
        unlockServer(server);
1414
0
        return UA_STATUSCODE_BADINTERNALERROR;
1415
0
    }
1416
1417
    /* Set to stopping and notify the application */
1418
272
    setServerLifecycleState(server, UA_LIFECYCLESTATE_STOPPING);
1419
1420
272
#if UA_MULTITHREADING >= 100
1421
    /* Stop regular callback for async operation processing */
1422
272
    UA_AsyncManager_stop(&server->asyncManager, server);
1423
272
#endif
1424
1425
    /* Stop the regular housekeeping tasks */
1426
272
    if(server->houseKeepingCallbackId != 0) {
1427
272
        removeCallback(server, server->houseKeepingCallbackId);
1428
272
        server->houseKeepingCallbackId = 0;
1429
272
    }
1430
1431
    /* Stop all ServerComponents */
1432
272
    ZIP_ITER(UA_ServerComponentTree, &server->serverComponents,
1433
272
             stopServerComponent, NULL);
1434
1435
    /* Are we already stopped? */
1436
272
    if(testStoppedCondition(server)) {
1437
0
        setServerLifecycleState(server, UA_LIFECYCLESTATE_STOPPED);
1438
0
    }
1439
1440
    /* Only stop the EventLoop if it is coupled to the server lifecycle  */
1441
272
    if(server->config.externalEventLoop) {
1442
0
        unlockServer(server);
1443
0
        return UA_STATUSCODE_GOOD;
1444
0
    }
1445
1446
    /* Unlock and do one "normal" iteration. This allows threads waiting for the
1447
     * server lock to proceed before the server lock is destroyed. */
1448
272
    unlockServer(server);
1449
272
    UA_Server_run_iterate(server, true);
1450
272
    lockServer(server);
1451
1452
    /* Iterate the EventLoop until the server is stopped */
1453
272
    UA_StatusCode res = UA_STATUSCODE_GOOD;
1454
272
    UA_EventLoop *el = server->config.eventLoop;
1455
272
    while(!testStoppedCondition(server) &&
1456
0
          res == UA_STATUSCODE_GOOD) {
1457
        /* Event-loop callbacks on other threads may need the server lock. */
1458
0
        unlockServer(server);
1459
0
        res = el->run(el, 100);
1460
0
        lockServer(server);
1461
0
    }
1462
1463
    /* Stop the EventLoop. Iterate until stopped. */
1464
272
    el->stop(el);
1465
272
    while(el->state != UA_EVENTLOOPSTATE_STOPPED &&
1466
0
          el->state != UA_EVENTLOOPSTATE_FRESH &&
1467
0
          res == UA_STATUSCODE_GOOD) {
1468
        /* Event-loop callbacks on other threads may need the server lock. */
1469
0
        unlockServer(server);
1470
0
        res = el->run(el, 100);
1471
0
        lockServer(server);
1472
0
    }
1473
1474
    /* Set server lifecycle state to stopped if not already the case */
1475
272
    setServerLifecycleState(server, UA_LIFECYCLESTATE_STOPPED);
1476
1477
272
    unlockServer(server);
1478
272
    return res;
1479
272
}
1480
1481
UA_StatusCode
1482
0
UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) {
1483
0
    UA_StatusCode retval = UA_Server_run_startup(server);
1484
0
    UA_CHECK_STATUS(retval, return retval);
1485
1486
0
    while(!testShutdownCondition(server)) {
1487
0
        UA_Server_run_iterate(server, true);
1488
0
        if(!*running) {
1489
0
            if(setServerShutdown(server))
1490
0
                break;
1491
0
        }
1492
0
    }
1493
0
    return UA_Server_run_shutdown(server);
1494
0
}
1495
1496
43.6M
void lockServer(UA_Server *server) {
1497
43.6M
    if(UA_LIKELY(server->config.eventLoop && server->config.eventLoop->lock))
1498
43.6M
        server->config.eventLoop->lock(server->config.eventLoop);
1499
43.6M
    UA_LOCK(&server->serviceMutex);
1500
43.6M
}
1501
1502
43.6M
void unlockServer(UA_Server *server) {
1503
43.6M
    if(UA_LIKELY(server->config.eventLoop && server->config.eventLoop->unlock))
1504
43.6M
        server->config.eventLoop->unlock(server->config.eventLoop);
1505
43.6M
    UA_UNLOCK(&server->serviceMutex);
1506
43.6M
}