Browse Source

Merge branch 'master' into unsigned_array_size

Julius Pfrommer 9 years ago
parent
commit
c63411078e

+ 75 - 43
src/server/ua_securechannel_manager.c

@@ -2,21 +2,22 @@
 #include "ua_session.h"
 #include "ua_statuscodes.h"
 
-UA_StatusCode
-UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_UInt32 maxChannelCount,
-                             UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
-                             UA_UInt32 startTokenId) {
+UA_StatusCode UA_SecureChannelManager_init(UA_SecureChannelManager *cm,
+        size_t maxChannelCount, UA_UInt32 tokenLifetime,
+        UA_UInt32 startChannelId, UA_UInt32 startTokenId) {
     LIST_INIT(&cm->channels);
-    cm->lastChannelId      = startChannelId;
-    cm->lastTokenId        = startTokenId;
+    cm->lastChannelId = startChannelId;
+    cm->lastTokenId = startTokenId;
     cm->maxChannelLifetime = tokenLifetime;
-    cm->maxChannelCount    = maxChannelCount;
+    cm->maxChannelCount = maxChannelCount;
+    cm->currentChannelCount = 0;
     return UA_STATUSCODE_GOOD;
 }
 
 void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
     channel_list_entry *entry, *temp;
-    LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
+    LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp)
+    {
         LIST_REMOVE(entry, pointers);
         UA_SecureChannel_deleteMembersCleanup(&entry->channel);
         UA_free(entry);
@@ -24,31 +25,51 @@ void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
 }
 
 /* remove channels that were not renewed or who have no connection attached */
-void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_DateTime now) {
+void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm,
+        UA_DateTime now) {
     channel_list_entry *entry, *temp;
-    LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp) {
-        UA_DateTime timeout = entry->channel.securityToken.createdAt +
-            ((UA_DateTime)entry->channel.securityToken.revisedLifetime * 10000);
-        if(timeout < now || !entry->channel.connection) {
+    LIST_FOREACH_SAFE(entry, &cm->channels, pointers, temp)
+    {
+        UA_DateTime timeout = entry->channel.securityToken.createdAt
+                + ((UA_DateTime) entry->channel.securityToken.revisedLifetime
+                        * 10000);
+        if (timeout < now || !entry->channel.connection) {
             LIST_REMOVE(entry, pointers);
             UA_SecureChannel_deleteMembersCleanup(&entry->channel);
+#ifndef UA_MULTITHREADING
+            cm->currentChannelCount--;
+#else
+            cm->currentChannelCount = uatomic_add_return(
+                    &cm->currentChannelCount, -1);
+#endif
             UA_free(entry);
-        } else if(entry->channel.nextSecurityToken.tokenId > 0) {
+        } else if (entry->channel.nextSecurityToken.tokenId > 0) {
             UA_SecureChannel_revolveTokens(&entry->channel);
         }
     }
 }
 
-UA_StatusCode
-UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
-                             const UA_OpenSecureChannelRequest *request,
-                             UA_OpenSecureChannelResponse *response) {
-    if(request->securityMode != UA_MESSAGESECURITYMODE_NONE)
+UA_StatusCode UA_SecureChannelManager_open(UA_SecureChannelManager *cm,
+        UA_Connection *conn, const UA_OpenSecureChannelRequest *request,
+        UA_OpenSecureChannelResponse *response) {
+
+    if (request->securityMode != UA_MESSAGESECURITYMODE_NONE) {
         return UA_STATUSCODE_BADSECURITYMODEREJECTED;
 
+    }
+
     channel_list_entry *entry = UA_malloc(sizeof(channel_list_entry));
-    if(!entry)
+    if (!entry) {
         return UA_STATUSCODE_BADOUTOFMEMORY;
+    }
+    if (cm->currentChannelCount >= cm->maxChannelCount) {
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+    }
+#ifndef UA_MULTITHREADING
+    cm->currentChannelCount++;
+#else
+    cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, 1);
+#endif
 
     UA_SecureChannel_init(&entry->channel);
     response->responseHeader.stringTableSize = 0;
@@ -58,75 +79,86 @@ UA_SecureChannelManager_open(UA_SecureChannelManager *cm, UA_Connection *conn,
     entry->channel.securityToken.channelId = cm->lastChannelId++;
     entry->channel.securityToken.tokenId = cm->lastTokenId++;
     entry->channel.securityToken.createdAt = UA_DateTime_now();
-    entry->channel.securityToken.revisedLifetime = (request->requestedLifetime > cm->maxChannelLifetime) ?
-                                                   cm->maxChannelLifetime : request->requestedLifetime;
+    entry->channel.securityToken.revisedLifetime =
+            (request->requestedLifetime > cm->maxChannelLifetime) ?
+                    cm->maxChannelLifetime : request->requestedLifetime;
     /* pragmatic workaround to get clients requesting lifetime of 0 working */
-    if(entry->channel.securityToken.revisedLifetime == 0)
+    if (entry->channel.securityToken.revisedLifetime == 0)
         entry->channel.securityToken.revisedLifetime = cm->maxChannelLifetime;
 
     UA_ByteString_copy(&request->clientNonce, &entry->channel.clientNonce);
-    entry->channel.serverAsymAlgSettings.securityPolicyUri =
-        UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None");
+    entry->channel.serverAsymAlgSettings.securityPolicyUri = UA_STRING_ALLOC(
+            "http://opcfoundation.org/UA/SecurityPolicy#None");
 
     UA_SecureChannel_generateNonce(&entry->channel.serverNonce);
     UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
-    UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
+    UA_ChannelSecurityToken_copy(&entry->channel.securityToken,
+            &response->securityToken);
 
     UA_Connection_attachSecureChannel(conn, &entry->channel);
     LIST_INSERT_HEAD(&cm->channels, entry, pointers);
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode
-UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Connection *conn,
-                              const UA_OpenSecureChannelRequest *request,
-                              UA_OpenSecureChannelResponse *response) {
+UA_StatusCode UA_SecureChannelManager_renew(UA_SecureChannelManager *cm,
+        UA_Connection *conn, const UA_OpenSecureChannelRequest *request,
+        UA_OpenSecureChannelResponse *response) {
     UA_SecureChannel *channel = conn->channel;
-    if(!channel)
+    if (!channel)
         return UA_STATUSCODE_BADINTERNALERROR;
 
     /* if no security token is already issued */
-    if(channel->nextSecurityToken.tokenId == 0) {
+    if (channel->nextSecurityToken.tokenId == 0) {
         channel->nextSecurityToken.channelId = channel->securityToken.channelId;
         //FIXME: UaExpert seems not to use the new tokenid
         channel->nextSecurityToken.tokenId = cm->lastTokenId++;
         //channel->nextSecurityToken.tokenId = channel->securityToken.tokenId;
         channel->nextSecurityToken.createdAt = UA_DateTime_now();
-        channel->nextSecurityToken.revisedLifetime = (request->requestedLifetime > cm->maxChannelLifetime) ?
-                                                 cm->maxChannelLifetime : request->requestedLifetime;
+        channel->nextSecurityToken.revisedLifetime =
+                (request->requestedLifetime > cm->maxChannelLifetime) ?
+                        cm->maxChannelLifetime : request->requestedLifetime;
 
         /* pragmatic workaround to get clients requesting lifetime of 0 working */
-        if(channel->nextSecurityToken.revisedLifetime == 0)
+        if (channel->nextSecurityToken.revisedLifetime == 0)
             channel->nextSecurityToken.revisedLifetime = cm->maxChannelLifetime;
     }
 
-    if(channel->clientNonce.data)
+    if (channel->clientNonce.data)
         UA_ByteString_deleteMembers(&channel->clientNonce);
 
     UA_ByteString_copy(&request->clientNonce, &channel->clientNonce);
     UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
-    UA_ChannelSecurityToken_copy(&channel->nextSecurityToken, &response->securityToken);
+    UA_ChannelSecurityToken_copy(&channel->nextSecurityToken,
+            &response->securityToken);
     return UA_STATUSCODE_GOOD;
 }
 
 UA_SecureChannel *
 UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
     channel_list_entry *entry;
-    LIST_FOREACH(entry, &cm->channels, pointers) {
-        if(entry->channel.securityToken.channelId == channelId)
+    LIST_FOREACH(entry, &cm->channels, pointers)
+    {
+        if (entry->channel.securityToken.channelId == channelId)
             return &entry->channel;
     }
     return NULL;
 }
 
-UA_StatusCode
-UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
+UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm,
+        UA_UInt32 channelId) {
     channel_list_entry *entry;
-    LIST_FOREACH(entry, &cm->channels, pointers) {
-        if(entry->channel.securityToken.channelId == channelId) {
+    LIST_FOREACH(entry, &cm->channels, pointers)
+    {
+        if (entry->channel.securityToken.channelId == channelId) {
             LIST_REMOVE(entry, pointers);
             UA_SecureChannel_deleteMembersCleanup(&entry->channel);
             UA_free(entry);
+#ifndef UA_MULTITHREADING
+            cm->currentChannelCount--;
+#else
+            cm->currentChannelCount = uatomic_add_return(
+                    &cm->currentChannelCount, -1);
+#endif
             return UA_STATUSCODE_GOOD;
         }
     }

+ 3 - 2
src/server/ua_securechannel_manager.h

@@ -13,7 +13,8 @@ typedef struct channel_list_entry {
 
 typedef struct UA_SecureChannelManager {
     LIST_HEAD(channel_list, channel_list_entry) channels; // doubly-linked list of channels
-    UA_Int32    maxChannelCount;
+    size_t    maxChannelCount;
+    size_t currentChannelCount;
     UA_DateTime maxChannelLifetime;
     UA_MessageSecurityMode securityMode;
     UA_DateTime channelLifeTime;
@@ -22,7 +23,7 @@ typedef struct UA_SecureChannelManager {
 } UA_SecureChannelManager;
 
 UA_StatusCode
-UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_UInt32 maxChannelCount,
+UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
                              UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
                              UA_UInt32 startTokenId);
 

+ 1 - 1
src/server/ua_server.c

@@ -37,7 +37,7 @@ static const UA_NodeId nodeIdOrganizes = {
 
 static const UA_ExpandedNodeId expandedNodeIdBaseDataVariabletype = {
     .nodeId = {.namespaceIndex = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
-               .identifier.numeric = UA_NS0ID_HASTYPEDEFINITION},
+               .identifier.numeric = UA_NS0ID_BASEDATAVARIABLETYPE},
     .namespaceUri = {.length = -1, .data = NULL}, .serverIndex = 0};
 
 #ifndef ENABLE_GENERATE_NAMESPACE0

+ 8 - 1
src/server/ua_subscription.c

@@ -230,7 +230,6 @@ static void Subscription_timedUpdateNotificationsJob(UA_Server *server, void *da
     Subscription_updateNotifications(sub);
 }
 
-
 UA_StatusCode Subscription_createdUpdateJob(UA_Server *server, UA_Guid jobId, UA_Subscription *sub) {
     if(server == NULL || sub == NULL)
         return UA_STATUSCODE_BADSERVERINDEXINVALID;
@@ -344,30 +343,37 @@ UA_Boolean MonitoredItem_CopyMonitoredValueToVariant(UA_UInt32 attributeID, cons
     switch(attributeID) {
     case UA_ATTRIBUTEID_NODEID:
         UA_Variant_setScalarCopy(&dst->value, (const UA_NodeId*)&src->nodeId, &UA_TYPES[UA_TYPES_NODEID]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_NODECLASS:
         UA_Variant_setScalarCopy(&dst->value, (const UA_Int32*)&src->nodeClass, &UA_TYPES[UA_TYPES_INT32]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_BROWSENAME:
         UA_Variant_setScalarCopy(&dst->value, (const UA_String*)&src->browseName, &UA_TYPES[UA_TYPES_QUALIFIEDNAME]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_DISPLAYNAME:
         UA_Variant_setScalarCopy(&dst->value, (const UA_String*)&src->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_DESCRIPTION:
         UA_Variant_setScalarCopy(&dst->value, (const UA_String*)&src->displayName, &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_WRITEMASK:
         UA_Variant_setScalarCopy(&dst->value, (const UA_String*)&src->writeMask, &UA_TYPES[UA_TYPES_UINT32]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_USERWRITEMASK:
         UA_Variant_setScalarCopy(&dst->value, (const UA_String*)&src->writeMask, &UA_TYPES[UA_TYPES_UINT32]);
+        dst->hasValue = UA_TRUE;
         samplingError = UA_FALSE;
         break;
     case UA_ATTRIBUTEID_ISABSTRACT:
@@ -385,6 +391,7 @@ UA_Boolean MonitoredItem_CopyMonitoredValueToVariant(UA_UInt32 attributeID, cons
             const UA_VariableNode *vsrc = (const UA_VariableNode*)src;
             if(srcAsVariableNode->valueSource == UA_VALUESOURCE_VARIANT) {
                 UA_Variant_copy(&vsrc->value.variant.value, &dst->value);
+                dst->hasValue = UA_TRUE;
                 //no onRead callback here since triggered by a subscription
                 samplingError = UA_FALSE;
             } else {