mirror of
https://github.com/open62541/open62541.git
synced 2026-10-17 04:42:09 +08:00
refactor(driver): More cleanup for GDS Receiver
This commit is contained in:
committed by
Julius Pfrommer
parent
2b2c0667c8
commit
629e3e9c1f
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user