Pārlūkot izejas kodu

securechannel and session cleanup (deactivated)

Julius Pfrommer 9 gadi atpakaļ
vecāks
revīzija
f16fdd7466

+ 1 - 1
include/ua_server.h

@@ -122,7 +122,7 @@ typedef struct UA_WorkItem {
             UA_ByteString message;
         } binaryNetworkMessage;
         struct {
-            void * data;
+            void *data;
             void (*method)(UA_Server *server, void *data);
         } methodCall;
     } work;

+ 5 - 11
src/server/ua_securechannel_manager.c

@@ -2,11 +2,6 @@
 #include "ua_session.h"
 #include "ua_statuscodes.h"
 
-typedef struct channel_list_entry {
-    UA_SecureChannel channel;
-    LIST_ENTRY(channel_list_entry) pointers;
-} channel_list_entry;
-
 UA_StatusCode UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_UInt32 maxChannelCount,
                                            UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
                                            UA_UInt32 startTokenId) {
@@ -119,20 +114,19 @@ UA_SecureChannel * UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_U
 
 UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
     // TODO lock access
-    // TODO: close the binaryconnection if it is still open. So we do not have stray pointers..
     channel_list_entry *entry;
     LIST_FOREACH(entry, &cm->channels, pointers) {
         if(entry->channel.securityToken.channelId == channelId) {
-            if(entry->channel.connection)
-                entry->channel.connection->channel = UA_NULL; // remove pointer back to the channel
-            if(entry->channel.session)
-                entry->channel.session->channel = UA_NULL; // remove ponter back to the channel
+            UA_Connection *c = entry->channel.connection;
+            if(c) {
+                UA_Connection_detachSecureChannel(c);
+                c->close(c);
+            }
             UA_SecureChannel_deleteMembers(&entry->channel);
             LIST_REMOVE(entry, pointers);
             UA_free(entry);
             return UA_STATUSCODE_GOOD;
         }
     }
-    //TODO notify server application that secureChannel has been closed part 6 - §7.1.4
     return UA_STATUSCODE_BADINTERNALERROR;
 }

+ 6 - 0
src/server/ua_securechannel_manager.h

@@ -4,6 +4,12 @@
 #include "ua_util.h"
 #include "ua_server.h"
 #include "ua_securechannel.h"
+#include "queue.h"
+
+typedef struct channel_list_entry {
+    UA_SecureChannel channel;
+    LIST_ENTRY(channel_list_entry) pointers;
+} channel_list_entry;
 
 typedef struct UA_SecureChannelManager {
     LIST_HEAD(channel_list, channel_list_entry) channels; // doubly-linked list of channels

+ 41 - 0
src/server/ua_server.c

@@ -115,6 +115,43 @@ void UA_Server_delete(UA_Server *server) {
 	UA_free(server);
 }
 
+/**
+ * Recurring cleanup. Removing unused and timed-out channels and sessions
+ * Todo: make this thread-safe
+ */
+static void UA_Server_cleanup(UA_Server *server, void *nothing) {
+    printf( "cleaning up...\n");
+    fflush(stdout);
+    UA_DateTime now = UA_DateTime_now();
+    channel_list_entry *entry;
+    /* remove channels that were not renewed or who have no connection attached */
+    LIST_FOREACH(entry, &server->secureChannelManager.channels, pointers) {
+        if(entry->channel.securityToken.createdAt +
+           (10000 * entry->channel.securityToken.revisedLifetime) > now ||
+           entry->channel.connection)
+            continue;
+        UA_Connection *c = entry->channel.connection;
+        UA_Connection_detachSecureChannel(c);
+        if(c) {
+            c->close(c);
+        }
+        UA_SecureChannel_detachSession(&entry->channel);
+        UA_SecureChannel_deleteMembers(&entry->channel);
+        LIST_REMOVE(entry, pointers);
+        UA_free(entry);
+    }
+
+    session_list_entry *sentry;
+    LIST_FOREACH(sentry, &server->sessionManager.sessions, pointers) {
+        if(sentry->session.validTill < now) {
+            LIST_REMOVE(sentry, pointers);
+            UA_SecureChannel_detachSession(sentry->session.channel);
+            UA_Session_deleteMembers(&sentry->session);
+            UA_free(sentry);
+        }
+    }
+}
+
 static UA_StatusCode readStatus(void *handle, UA_Boolean sourceTimeStamp, UA_DataValue *value) {
     UA_ServerStatusDataType *status = UA_ServerStatusDataType_new();
     status->startTime   = ((const UA_Server*)handle)->startTime;
@@ -335,6 +372,10 @@ UA_Server * UA_Server_new(UA_ServerConfig config) {
 
     server->nodestore = UA_NodeStore_new();
 
+	/* UA_WorkItem cleanup = {.type = UA_WORKITEMTYPE_METHODCALL, */
+    /*                        .work.methodCall = {.method = UA_Server_cleanup, .data = NULL} }; */
+	/* UA_Server_addRepeatedWorkItem(server, &cleanup, 100000, NULL); */
+
     /**********************/
     /* Server Information */
     /**********************/

+ 5 - 3
src/server/ua_server_worker.c

@@ -154,9 +154,9 @@ static UA_StatusCode addTimedWork(UA_Server *server, const UA_WorkItem *item, UA
         if(tw->repetitionInterval == repetitionInterval &&
            (repetitionInterval > 0 || tw->time == firstTime))
             break; // found a matching entry
+        lastTw = tw;
         if(tw->time > firstTime) {
             tw = UA_NULL; // not matchin entry exists
-            lastTw = tw;
             break;
         }
     }
@@ -285,11 +285,13 @@ static UA_UInt16 processTimedWork(UA_Server *server) {
 
     // check if the next timed work is sooner than the usual timeout
     UA_TimedWork *first = LIST_FIRST(&server->timedWork);
-    UA_UInt16 timeout = MAXTIMEOUT;
+    UA_Int32 timeout = MAXTIMEOUT;
     if(first) {
         timeout = (first->time - current)/10;
         if(timeout > MAXTIMEOUT)
-            timeout = MAXTIMEOUT;
+            return MAXTIMEOUT;
+        if(timeout < 0)
+            return 0;
     }
     return timeout;
 }

+ 1 - 7
src/server/ua_session_manager.c

@@ -8,11 +8,6 @@
  implementation is choosen based on whether multithreading is enabled or not.
  */
 
-typedef struct session_list_entry {
-    UA_Session session;
-    LIST_ENTRY(session_list_entry) pointers;
-} session_list_entry;
-
 UA_StatusCode UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
                                     UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId) {
     LIST_INIT(&sessionManager->sessions);
@@ -129,8 +124,7 @@ UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_Node
         return UA_STATUSCODE_BADINTERNALERROR;
 
     LIST_REMOVE(current, pointers);
-    if(current->session.channel)
-        current->session.channel->session = UA_NULL; // the channel is no longer attached to a session
+    UA_SecureChannel_detachSession(current->session.channel);
     UA_Session_deleteMembers(&current->session);
     UA_free(current);
     return UA_STATUSCODE_GOOD;

+ 5 - 0
src/server/ua_session_manager.h

@@ -6,6 +6,11 @@
 #include "ua_util.h"
 #include "ua_session.h"
 
+typedef struct session_list_entry {
+    UA_Session session;
+    LIST_ENTRY(session_list_entry) pointers;
+} session_list_entry;
+
 typedef struct UA_SessionManager {
     LIST_HEAD(session_list, session_list_entry) sessions; // doubly-linked list of sessions
     UA_UInt32    maxSessionCount;