refactor(driver): More cleanup for GDS Receiver

This commit is contained in:
Julius Pfrommer
2026-07-18 14:50:20 +02:00
committed by Julius Pfrommer
parent 2b2c0667c8
commit 629e3e9c1f
5 changed files with 241 additions and 91 deletions
+107 -56
View File
@@ -343,7 +343,7 @@ UA_GDSReceiver_getFileInfoMetadata(UA_GDSReceiverContext *ctx,
UA_UtcTime *lastUpdateTime) {
UA_FileInfo *fi = UA_GDSReceiver_getFileInfo(ctx, certificateGroupId);
if(!fi)
return UA_STATUSCODE_BADINTERNALERROR;
return UA_STATUSCODE_BADNOTFOUND;
*openCount = fi->openCount;
*lastUpdateTime = fi->lastUpdateTime;
return UA_STATUSCODE_GOOD;
@@ -375,7 +375,7 @@ checkSessionActive(UA_Server *server, void *data) {
UA_EventLoop *el = sc->eventLoop;
el->lock(el);
UA_GDSReceiverContext *ctx = gdsReceiver(server);
UA_GDSReceiverContext *ctx = (UA_GDSReceiverContext*)data;
UA_GDSTransaction *transaction = &ctx->transaction;
UA_Boolean removingCallback = false;
if(transaction->state != UA_GDSTRANSACTIONSTATE_FRESH) {
@@ -428,7 +428,7 @@ checkSessionActive(UA_Server *server, void *data) {
UA_free(fileContext);
/* Updating OpenCount Variable in the information model */
writeOpenCountVariable(server, certGroup);
writeOpenCountVariable(ctx, certGroup);
}
}
@@ -521,7 +521,6 @@ UA_GDSReceiver_closeAndUpdateTrustList(UA_GDSReceiverContext *ctx,
UA_UInt32 fileHandle,
UA_Variant *output) {
UA_assert(certGroup != NULL);
UA_Server *server = ctx->drv.server;
UA_GDSTransaction *transaction = &ctx->transaction;
UA_FileInfo *fileInfo =
@@ -564,7 +563,7 @@ UA_GDSReceiver_closeAndUpdateTrustList(UA_GDSReceiverContext *ctx,
UA_free(fileContext);
/* Updating OpenCount Variable in the information model */
writeOpenCountVariable(server, certGroup);
writeOpenCountVariable(ctx, certGroup);
/* Output arg, indicates that the ApplyChanges Method shall be called before
* the new trust list will be used. */
@@ -579,7 +578,6 @@ UA_GDSReceiver_closeTrustList(UA_GDSReceiverContext *ctx,
const UA_NodeId *sessionId,
UA_UInt32 fileHandle) {
UA_assert(certGroup != NULL);
UA_Server *server = ctx->drv.server;
UA_GDSTransaction *transaction = &ctx->transaction;
UA_FileInfo *fileInfo =
@@ -605,7 +603,7 @@ UA_GDSReceiver_closeTrustList(UA_GDSReceiverContext *ctx,
UA_free(fileContext);
/* Updating OpenCount Variable in the information model */
writeOpenCountVariable(server, certGroup);
writeOpenCountVariable(ctx, certGroup);
return UA_STATUSCODE_GOOD;
}
@@ -615,7 +613,6 @@ UA_GDSReceiver_readTrustList(UA_GDSReceiverContext *ctx, UA_CertificateGroup *ce
UA_Int32 length, UA_Variant *output) {
UA_assert(certGroup != NULL);
/* UA_GDSReceiverContext *ctx = gdsReceiver(server); */
UA_FileInfo *fileInfo =
UA_GDSReceiver_getFileInfo(ctx, certGroup->certificateGroupId);
if(!fileInfo)
@@ -688,7 +685,7 @@ UA_GDSReceiver_addCertificate(UA_GDSReceiverContext *ctx,
/* Updating LastUpdateTime Variable in the information model */
fileInfo->lastUpdateTime = UA_DateTime_now();
writeLastUpdateVariable(server, certGroup);
writeLastUpdateVariable(ctx, certGroup);
return UA_STATUSCODE_GOOD;
}
@@ -736,7 +733,7 @@ UA_GDSReceiver_stageCertificateUpdate(UA_GDSReceiverContext *ctx,
if(ctx->checkSessionCallbackId == 0) {
retval = UA_Server_addRepeatedCallback(ctx->drv.server, checkSessionActive,
NULL, CHECKACTIVESESSIONINTERVAL,
ctx, CHECKACTIVESESSIONINTERVAL,
&ctx->checkSessionCallbackId);
if(retval != UA_STATUSCODE_GOOD)
return retval;
@@ -1015,7 +1012,7 @@ UA_GDSReceiver_openTrustListWithMask(UA_GDSReceiverContext *ctx, UA_CertificateG
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(ctx->checkSessionCallbackId == 0) {
retval = UA_Server_addRepeatedCallback(server, checkSessionActive, NULL,
retval = UA_Server_addRepeatedCallback(server, checkSessionActive, ctx,
CHECKACTIVESESSIONINTERVAL,
&ctx->checkSessionCallbackId);
if(retval != UA_STATUSCODE_GOOD)
@@ -1069,7 +1066,7 @@ UA_GDSReceiver_openTrustListWithMask(UA_GDSReceiverContext *ctx, UA_CertificateG
fileInfo->openCount += 1;
/* Updating OpenCount Variable in the information model */
writeOpenCountVariable(server, certGroup);
writeOpenCountVariable(ctx, certGroup);
LIST_INSERT_HEAD(&fileInfo->fileContext, fileContext, listEntry);
@@ -1114,7 +1111,7 @@ UA_GDSReceiver_openTrustList(UA_GDSReceiverContext *ctx, UA_CertificateGroup *ce
}
if(ctx->checkSessionCallbackId == 0) {
retval = UA_Server_addRepeatedCallback(server, checkSessionActive, NULL,
retval = UA_Server_addRepeatedCallback(server, checkSessionActive, ctx,
CHECKACTIVESESSIONINTERVAL,
&ctx->checkSessionCallbackId);
if(retval != UA_STATUSCODE_GOOD)
@@ -1166,7 +1163,7 @@ UA_GDSReceiver_openTrustList(UA_GDSReceiverContext *ctx, UA_CertificateGroup *ce
fileInfo->openCount += 1;
/* Updating OpenCount Variable in the information model */
writeOpenCountVariable(server, certGroup);
writeOpenCountVariable(ctx, certGroup);
LIST_INSERT_HEAD(&fileInfo->fileContext, fileContext, listEntry);
@@ -1175,9 +1172,9 @@ UA_GDSReceiver_openTrustList(UA_GDSReceiverContext *ctx, UA_CertificateGroup *ce
static void
secureChannel_delayedClose(void *application, void *context) {
UA_Server *server = (UA_Server*)context;
UA_GDSReceiverContext *ctx = (UA_GDSReceiverContext*)context;
UA_Server *server = ctx->drv.server;
UA_ServerConfig *sc = UA_Server_getConfig(server);
UA_GDSReceiverContext *ctx = gdsReceiver(server);
UA_GDSTransactionChanges *changes = (UA_GDSTransactionChanges*)application;
ChannelMetadata *cm;
@@ -1412,8 +1409,10 @@ UA_GDSReceiver_updateCertificate(UA_GDSReceiver *receiver,
const UA_NodeId certificateTypeId,
const UA_ByteString certificate,
const UA_ByteString *privateKey) {
if(!receiver || !receiver->drv.server)
return UA_STATUSCODE_BADINTERNALERROR;
if(!receiver || certificate.length == 0)
return UA_STATUSCODE_BADINVALIDARGUMENT;
if(!receiver->drv.server)
return UA_STATUSCODE_BADINVALIDSTATE;
UA_ServerConfig *sc = UA_Server_getConfig(receiver->drv.server);
sc->eventLoop->lock(sc->eventLoop);
@@ -1508,8 +1507,10 @@ UA_GDSReceiver_createSigningRequest(UA_GDSReceiver *receiver,
const UA_Boolean *regenerateKey,
const UA_ByteString *nonce,
UA_ByteString *csr) {
if(!receiver || !receiver->drv.server || !csr)
return UA_STATUSCODE_BADINTERNALERROR;
if(!receiver || !csr)
return UA_STATUSCODE_BADINVALIDARGUMENT;
if(!receiver->drv.server)
return UA_STATUSCODE_BADINVALIDSTATE;
UA_ServerConfig *sc = UA_Server_getConfig(receiver->drv.server);
sc->eventLoop->lock(sc->eventLoop);
@@ -1543,50 +1544,53 @@ UA_GDSReceiver_applyChanges(UA_GDSReceiverContext *ctx) {
if(!changes)
return UA_STATUSCODE_BADOUTOFMEMORY;
/* Apply Trust list changes */
for(size_t i = 0; i < transaction->certGroupSize; i++) {
*changes = UA_GDSTRANSACTIONCHANGES_TRUSTLIST;
UA_CertificateGroup transactionCertGroup = transaction->certGroups[i];
UA_TrustListDataType trustList;
UA_TrustListDataType_init(&trustList);
trustList.specifiedLists = UA_TRUSTLISTMASKS_ALL;
retval = transactionCertGroup.getTrustList(&transactionCertGroup,
&trustList);
if(retval != UA_STATUSCODE_GOOD) {
UA_TrustListDataType_clear(&trustList);
size_t groupsSize = transaction->certGroupSize;
UA_CertificateGroup **groups = NULL;
UA_TrustListDataType *newTrustLists = NULL;
UA_TrustListDataType *oldTrustLists = NULL;
if(groupsSize > 0) {
groups = (UA_CertificateGroup**)UA_calloc(groupsSize, sizeof(void*));
newTrustLists = (UA_TrustListDataType*)
UA_calloc(groupsSize, sizeof(UA_TrustListDataType));
oldTrustLists = (UA_TrustListDataType*)
UA_calloc(groupsSize, sizeof(UA_TrustListDataType));
if(!groups || !newTrustLists || !oldTrustLists) {
retval = UA_STATUSCODE_BADOUTOFMEMORY;
goto cleanup;
}
}
UA_CertificateGroup *certGroup =
getCertGroup(server, &transactionCertGroup.certificateGroupId);
if(!certGroup) {
UA_TrustListDataType_clear(&trustList);
goto cleanup;
}
retval = certGroup->setTrustList(certGroup, &trustList);
UA_TrustListDataType_clear(&trustList);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
UA_FileInfo *fileInfo =
UA_GDSReceiver_getFileInfo(ctx, certGroup->certificateGroupId);
if(!fileInfo) {
/* Resolve every live group and snapshot both the staged and current trust
* lists before mutating configuration. The snapshots permit rolling back
* all trust-list changes if any subsequent operation fails. */
for(size_t i = 0; i < groupsSize; i++) {
UA_CertificateGroup *stagedGroup = &transaction->certGroups[i];
groups[i] = getCertGroup(server, &stagedGroup->certificateGroupId);
if(!groups[i]) {
retval = UA_STATUSCODE_BADINTERNALERROR;
goto cleanup;
}
newTrustLists[i].specifiedLists = UA_TRUSTLISTMASKS_ALL;
oldTrustLists[i].specifiedLists = UA_TRUSTLISTMASKS_ALL;
retval = stagedGroup->getTrustList(stagedGroup, &newTrustLists[i]);
if(retval == UA_STATUSCODE_GOOD)
retval = groups[i]->getTrustList(groups[i], &oldTrustLists[i]);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
}
/* Updating LastUpdateTime Variable in the information model */
fileInfo->lastUpdateTime = UA_DateTime_now();
writeLastUpdateVariable(server, certGroup);
size_t appliedGroups = 0;
for(size_t i = 0; i < groupsSize; i++) {
/* Include the current group in rollback even if its plugin reports an
* error after partially changing its internal state. */
appliedGroups = i + 1;
retval = groups[i]->setTrustList(groups[i], &newTrustLists[i]);
if(retval != UA_STATUSCODE_GOOD)
goto rollback;
}
/* Apply Server certificate changes */
for(size_t i = 0; i < transaction->certificateInfosSize; i++) {
if(*changes != UA_GDSTRANSACTIONCHANGES_NOTHING) {
*changes = UA_GDSTRANSACTIONCHANGES_BOTH;
} else {
*changes = UA_GDSTRANSACTIONCHANGES_CERTIFICATE;
}
UA_GDSCertificateInfo certInfo = transaction->certificateInfos[i];
UA_NodeId certTypeId = certInfo.certificateType;
UA_ByteString certificate = certInfo.certificate;
@@ -1595,7 +1599,23 @@ UA_GDSReceiver_applyChanges(UA_GDSReceiverContext *ctx) {
retval = applyCertificateToPolicies(sc, &certTypeId, certificate,
privateKey);
if(retval != UA_STATUSCODE_GOOD)
goto cleanup;
goto rollback;
}
if(groupsSize > 0 && transaction->certificateInfosSize > 0)
*changes = UA_GDSTRANSACTIONCHANGES_BOTH;
else if(groupsSize > 0)
*changes = UA_GDSTRANSACTIONCHANGES_TRUSTLIST;
else if(transaction->certificateInfosSize > 0)
*changes = UA_GDSTRANSACTIONCHANGES_CERTIFICATE;
/* Publish metadata only after the complete transaction has succeeded. */
for(size_t i = 0; i < groupsSize; i++) {
UA_FileInfo *fileInfo =
UA_GDSReceiver_getFileInfo(ctx, groups[i]->certificateGroupId);
UA_assert(fileInfo != NULL);
fileInfo->lastUpdateTime = UA_DateTime_now();
writeLastUpdateVariable(ctx, groups[i]);
}
/* Add to the delayed callback list. Will be cleaned up in the next
@@ -1604,14 +1624,42 @@ UA_GDSReceiver_applyChanges(UA_GDSReceiverContext *ctx) {
UA_DelayedCallback *dc = &transaction->dc;
dc->callback = secureChannel_delayedClose;
dc->application = changes;
dc->context = server;
dc->context = ctx;
UA_EventLoop *el = sc->eventLoop;
ctx->pendingDelayedCallbacks++;
el->addDelayedCallback(el, dc);
for(size_t i = 0; i < groupsSize; i++) {
UA_TrustListDataType_clear(&newTrustLists[i]);
UA_TrustListDataType_clear(&oldTrustLists[i]);
}
UA_free(groups);
UA_free(newTrustLists);
UA_free(oldTrustLists);
return UA_STATUSCODE_GOOD;
rollback:
while(appliedGroups > 0) {
appliedGroups--;
UA_StatusCode rollbackRes = groups[appliedGroups]->setTrustList(
groups[appliedGroups], &oldTrustLists[appliedGroups]);
if(rollbackRes != UA_STATUSCODE_GOOD)
UA_LOG_ERROR(sc->logging, UA_LOGCATEGORY_SERVER,
"Could not roll back a GDS Receiver trust-list update");
}
cleanup:
if(newTrustLists) {
for(size_t i = 0; i < groupsSize; i++)
UA_TrustListDataType_clear(&newTrustLists[i]);
}
if(oldTrustLists) {
for(size_t i = 0; i < groupsSize; i++)
UA_TrustListDataType_clear(&oldTrustLists[i]);
}
UA_free(groups);
UA_free(newTrustLists);
UA_free(oldTrustLists);
UA_GDSTransaction_clear(transaction);
UA_free(changes);
return retval;
@@ -1694,6 +1742,10 @@ UA_GDSReceiver_start(UA_Driver *drv) {
static void
UA_GDSReceiver_stop(UA_Driver *drv) {
UA_GDSReceiverContext *ctx = (UA_GDSReceiverContext*)drv;
if(ctx->initialized) {
clearNS0PushManagement(ctx);
ctx->initialized = false;
}
if(ctx->checkSessionCallbackId != 0) {
UA_Server_removeCallback(drv->server, ctx->checkSessionCallbackId);
ctx->checkSessionCallbackId = 0;
@@ -1704,7 +1756,6 @@ UA_GDSReceiver_stop(UA_Driver *drv) {
drv->state = UA_LIFECYCLESTATE_STOPPED;
}
/* TODO: Remove NS0 entries here for true "driver" semantics */
static UA_StatusCode
UA_GDSReceiver_free(UA_Driver *drv) {
if(drv->state != UA_LIFECYCLESTATE_STOPPED) {
+5 -5
View File
@@ -17,20 +17,20 @@ _UA_BEGIN_DECLS
typedef struct UA_GDSReceiverContext UA_GDSReceiverContext;
UA_GDSReceiverContext *
gdsReceiver(UA_Server *server);
UA_StatusCode
initNS0PushManagement(UA_GDSReceiverContext *ctx);
void
clearNS0PushManagement(UA_GDSReceiverContext *ctx);
UA_CertificateGroup *
getCertGroup(UA_Server *server, const UA_NodeId *objectId);
UA_StatusCode
writeOpenCountVariable(UA_Server *server, UA_CertificateGroup *group);
writeOpenCountVariable(UA_GDSReceiverContext *ctx, UA_CertificateGroup *group);
UA_StatusCode
writeLastUpdateVariable(UA_Server *server, UA_CertificateGroup *group);
writeLastUpdateVariable(UA_GDSReceiverContext *ctx, UA_CertificateGroup *group);
UA_StatusCode
UA_GDSReceiver_initFileInfos(UA_GDSReceiverContext *ctx, UA_UtcTime lastUpdateTime);
+63 -21
View File
@@ -13,14 +13,6 @@
#define STATIC_NS0ID(ID) {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_##ID}}
UA_GDSReceiverContext *
gdsReceiver(UA_Server *server) {
UA_Driver *drv = UA_Server_getDrivers(server);
while(drv && drv->driverType != UA_DRIVERTYPE_GDS_RECEIVER)
drv = drv->next;
return (UA_GDSReceiverContext *)drv;
}
UA_CertificateGroup*
getCertGroup(UA_Server *server, const UA_NodeId *objectId) {
UA_ServerConfig *sc = UA_Server_getConfig(server);
@@ -66,7 +58,8 @@ writeGDSNs0Variable(UA_Server *server, const UA_NodeId id,
}
UA_StatusCode
writeOpenCountVariable(UA_Server *server, UA_CertificateGroup *group) {
writeOpenCountVariable(UA_GDSReceiverContext *ctx, UA_CertificateGroup *group) {
UA_Server *server = ((UA_GDSReceiver*)ctx)->drv.server;
static UA_NodeId defaultApplicationGroup =
STATIC_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP);
static UA_NodeId defaultUserTokenGroup =
@@ -75,7 +68,7 @@ writeOpenCountVariable(UA_Server *server, UA_CertificateGroup *group) {
UA_UInt16 openCount;
UA_UtcTime lastUpdateTime;
UA_StatusCode res = UA_GDSReceiver_getFileInfoMetadata(
gdsReceiver(server), group->certificateGroupId, &openCount, &lastUpdateTime);
ctx, group->certificateGroupId, &openCount, &lastUpdateTime);
if(res != UA_STATUSCODE_GOOD)
return res;
@@ -97,7 +90,8 @@ writeOpenCountVariable(UA_Server *server, UA_CertificateGroup *group) {
}
UA_StatusCode
writeLastUpdateVariable(UA_Server *server, UA_CertificateGroup *group) {
writeLastUpdateVariable(UA_GDSReceiverContext *ctx, UA_CertificateGroup *group) {
UA_Server *server = ((UA_GDSReceiver*)ctx)->drv.server;
static UA_NodeId defaultApplicationGroup =
STATIC_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP);
static UA_NodeId defaultUserTokenGroup =
@@ -106,7 +100,7 @@ writeLastUpdateVariable(UA_Server *server, UA_CertificateGroup *group) {
UA_UInt16 openCount;
UA_UtcTime lastUpdateTime;
UA_StatusCode res = UA_GDSReceiver_getFileInfoMetadata(
gdsReceiver(server), group->certificateGroupId, &openCount, &lastUpdateTime);
ctx, group->certificateGroupId, &openCount, &lastUpdateTime);
if(res != UA_STATUSCODE_GOOD)
return res;
@@ -128,16 +122,17 @@ writeLastUpdateVariable(UA_Server *server, UA_CertificateGroup *group) {
}
static UA_StatusCode
createFileInfos(UA_Server *server) {
createFileInfos(UA_GDSReceiverContext *ctx) {
/* The server currently only supports the DefaultApplicationGroup and
* UserTokenGroup */
UA_UtcTime lastUpdateTime = UA_DateTime_now();
return UA_GDSReceiver_initFileInfos(gdsReceiver(server), lastUpdateTime);
return UA_GDSReceiver_initFileInfos(ctx, lastUpdateTime);
}
static UA_StatusCode
writeGroupVariables(UA_Server *server) {
writeGroupVariables(UA_GDSReceiverContext *ctx) {
UA_Server *server = ((UA_GDSReceiver*)ctx)->drv.server;
UA_NodeId certificateTypes[2] = {
UA_NODEID_NUMERIC(0, UA_NS0ID_RSAMINAPPLICATIONCERTIFICATETYPE),
UA_NODEID_NUMERIC(0, UA_NS0ID_RSASHA256APPLICATIONCERTIFICATETYPE)
@@ -165,7 +160,7 @@ writeGroupVariables(UA_Server *server) {
UA_UInt16 openCount;
UA_UtcTime lastUpdateTime;
UA_StatusCode res = UA_GDSReceiver_getFileInfoMetadata(
gdsReceiver(server),
ctx,
UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP),
&openCount, &lastUpdateTime);
if(res != UA_STATUSCODE_GOOD)
@@ -180,7 +175,7 @@ writeGroupVariables(UA_Server *server) {
/* DefaultUserTokenGroup */
res = UA_GDSReceiver_getFileInfoMetadata(
gdsReceiver(server),
ctx,
UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP),
&openCount, &lastUpdateTime);
if(res != UA_STATUSCODE_GOOD)
@@ -657,14 +652,22 @@ setMethodCallback(UA_GDSReceiverContext *ctx, UA_NodeId methodId,
UA_StatusCode
initNS0PushManagement(UA_GDSReceiverContext *ctx) {
UA_Server *server = ((UA_GDSReceiver*)ctx)->drv.server;
UA_StatusCode retval = UA_STATUSCODE_GOOD;
/* Create FileInfo */
retval |= createFileInfos(server);
/* Create the persistent FileInfo state only once. The Namespace Zero
* callbacks themselves are installed again when the driver is restarted. */
UA_UInt16 openCount;
UA_UtcTime lastUpdateTime;
UA_StatusCode res = UA_GDSReceiver_getFileInfoMetadata(
ctx, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP),
&openCount, &lastUpdateTime);
if(res == UA_STATUSCODE_BADNOTFOUND)
retval |= createFileInfos(ctx);
else
retval |= res;
/* Set variables */
retval |= writeGroupVariables(server);
retval |= writeGroupVariables(ctx);
/* Set method callbacks */
retval |= setMethodCallback(ctx, UA_NS0ID(SERVERCONFIGURATION_UPDATECERTIFICATE), updateCertificateAction);
@@ -691,7 +694,46 @@ initNS0PushManagement(UA_GDSReceiverContext *ctx) {
retval |= setMethodCallback(ctx, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_GETPOSITION), getPositionFileAction);
retval |= setMethodCallback(ctx, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_SETPOSITION), setPositionFileAction);
retval |= setMethodCallback(ctx, UA_NS0ID(SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_SETPOSITION), setPositionFileAction);
if(retval != UA_STATUSCODE_GOOD)
clearNS0PushManagement(ctx);
return retval;
}
void
clearNS0PushManagement(UA_GDSReceiverContext *ctx) {
UA_Server *server = ((UA_GDSReceiver*)ctx)->drv.server;
static const UA_UInt32 methodIds[] = {
UA_NS0ID_SERVERCONFIGURATION_UPDATECERTIFICATE,
UA_NS0ID_SERVERCONFIGURATION_CREATESIGNINGREQUEST,
UA_NS0ID_SERVERCONFIGURATION_GETREJECTEDLIST,
UA_NS0ID_SERVERCONFIGURATION_APPLYCHANGES,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_ADDCERTIFICATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_ADDCERTIFICATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_REMOVECERTIFICATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_REMOVECERTIFICATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_OPENWITHMASKS,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_OPENWITHMASKS,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_CLOSEANDUPDATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_CLOSEANDUPDATE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_OPEN,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_OPEN,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_READ,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_READ,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_WRITE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_WRITE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_CLOSE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_CLOSE,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_GETPOSITION,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_GETPOSITION,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTAPPLICATIONGROUP_TRUSTLIST_SETPOSITION,
UA_NS0ID_SERVERCONFIGURATION_CERTIFICATEGROUPS_DEFAULTUSERTOKENGROUP_TRUSTLIST_SETPOSITION
};
for(size_t i = 0; i < sizeof(methodIds) / sizeof(methodIds[0]); i++) {
UA_NodeId methodId = UA_NODEID_NUMERIC(0, methodIds[i]);
UA_Server_setMethodNodeCallback(server, methodId, NULL);
UA_Server_setNodeContext(server, methodId, NULL);
}
}
#endif
+6 -2
View File
@@ -48,7 +48,9 @@ UA_GDSReceiver_new(void);
/* Update the application certificate used by the server endpoints. The GDS
* Receiver driver must be attached and started. If certificateGroupId is
* null, the DefaultApplicationGroup is used. This function is thread-safe. */
* null, the DefaultApplicationGroup is used. Returns BadInvalidArgument for a
* null receiver or empty certificate and BadInvalidState if the receiver is
* not attached and started. This function is thread-safe. */
UA_EXPORT UA_StatusCode
UA_GDSReceiver_updateCertificate(UA_GDSReceiver *receiver,
const UA_NodeId certificateGroupId,
@@ -58,7 +60,9 @@ UA_GDSReceiver_updateCertificate(UA_GDSReceiver *receiver,
/* Create a PKCS #10 DER-encoded certificate signing request. The GDS Receiver
* driver must be attached and started. If certificateGroupId is null,
* the DefaultApplicationGroup is used. This function is thread-safe. */
* the DefaultApplicationGroup is used. Returns BadInvalidArgument for a null
* receiver or output pointer and BadInvalidState if the receiver is not
* attached and started. This function is thread-safe. */
UA_EXPORT UA_StatusCode
UA_GDSReceiver_createSigningRequest(UA_GDSReceiver *receiver,
const UA_NodeId certificateGroupId,
@@ -69,6 +69,17 @@ createSigningRequest(void) {
return res;
}
static void
checkHelpersDuringShutdown(void *application, void *context) {
UA_Server *server_ = (UA_Server*)application;
ck_assert_ptr_eq(server_, server);
ck_assert_uint_eq(UA_Server_getLifecycleState(server),
UA_LIFECYCLESTATE_STOPPING);
ck_assert_uint_eq(updateCertificate(), UA_STATUSCODE_BADINVALIDSTATE);
ck_assert_uint_eq(createSigningRequest(), UA_STATUSCODE_BADINVALIDSTATE);
*(UA_Boolean*)context = true;
}
static UA_StatusCode
stageAndApplyCertificateUpdate(void) {
UA_ByteString certificate = {CERT_DER_LENGTH, CERT_DER_DATA};
@@ -143,28 +154,70 @@ START_TEST(rejectDuplicateReceiver) {
} END_TEST
START_TEST(helpersBeforeStartupAndDuringShutdown) {
UA_ByteString certificate = {CERT_DER_LENGTH, CERT_DER_DATA};
UA_ByteString privateKey = {KEY_DER_LENGTH, KEY_DER_DATA};
ck_assert_uint_eq(UA_GDSReceiver_updateCertificate(
NULL, defaultApplicationGroup,
rsaSha256CertificateType, certificate, &privateKey),
UA_STATUSCODE_BADINVALIDARGUMENT);
ck_assert_uint_eq(UA_GDSReceiver_updateCertificate(
receiver, defaultApplicationGroup,
rsaSha256CertificateType, UA_BYTESTRING_NULL,
&privateKey),
UA_STATUSCODE_BADINVALIDARGUMENT);
ck_assert_uint_eq(UA_GDSReceiver_createSigningRequest(
receiver, defaultApplicationGroup,
rsaSha256CertificateType, NULL, NULL, NULL, NULL),
UA_STATUSCODE_BADINVALIDARGUMENT);
ck_assert_uint_eq(updateCertificate(), UA_STATUSCODE_BADINVALIDSTATE);
ck_assert_uint_eq(createSigningRequest(), UA_STATUSCODE_BADINVALIDSTATE);
startup();
ck_assert_uint_eq(updateCertificate(), UA_STATUSCODE_GOOD);
receiver->drv.stop(&receiver->drv);
ck_assert_uint_eq(receiver->drv.state, UA_LIFECYCLESTATE_STOPPING);
ck_assert_uint_eq(updateCertificate(), UA_STATUSCODE_BADINVALIDSTATE);
ck_assert_uint_eq(createSigningRequest(), UA_STATUSCODE_BADINVALIDSTATE);
UA_Server_run_iterate(server, false);
UA_Boolean callbackCalled = false;
UA_DelayedCallback callback = {0};
callback.callback = checkHelpersDuringShutdown;
callback.application = server;
callback.context = &callbackCalled;
UA_EventLoop *eventLoop = UA_Server_getConfig(server)->eventLoop;
eventLoop->addDelayedCallback(eventLoop, &callback);
ck_assert_uint_eq(UA_Server_run_shutdown(server), UA_STATUSCODE_GOOD);
serverStarted = false;
ck_assert(callbackCalled);
ck_assert_uint_eq(receiver->drv.state, UA_LIFECYCLESTATE_STOPPED);
} END_TEST
START_TEST(removeStoppedReceiver) {
startup();
receiver->drv.stop(&receiver->drv);
ck_assert_uint_eq(UA_Server_run_shutdown(server), UA_STATUSCODE_GOOD);
serverStarted = false;
ck_assert_uint_eq(receiver->drv.state, UA_LIFECYCLESTATE_STOPPED);
void *methodContext = receiver;
ck_assert_uint_eq(UA_Server_getNodeContext(
server,
UA_NODEID_NUMERIC(
0, UA_NS0ID_SERVERCONFIGURATION_APPLYCHANGES),
&methodContext),
UA_STATUSCODE_GOOD);
ck_assert_ptr_null(methodContext);
ck_assert_uint_eq(UA_Server_removeDriver(server, &receiver->drv),
UA_STATUSCODE_GOOD);
ck_assert_uint_eq(receiver->drv.free(&receiver->drv), UA_STATUSCODE_GOOD);
receiver = NULL;
receiver = UA_GDSReceiver_new();
ck_assert_ptr_nonnull(receiver);
ck_assert_uint_eq(UA_Server_addDriver(server, &receiver->drv),
UA_STATUSCODE_GOOD);
startup();
methodContext = NULL;
ck_assert_uint_eq(UA_Server_getNodeContext(
server,
UA_NODEID_NUMERIC(
0, UA_NS0ID_SERVERCONFIGURATION_APPLYCHANGES),
&methodContext),
UA_STATUSCODE_GOOD);
ck_assert_ptr_eq(methodContext, receiver);
} END_TEST
int