Browse Source

use delayedFree to remove sessions and securechannels

Julius Pfrommer 9 years ago
parent
commit
dec02aeebb

+ 3 - 1
include/ua_job.h

@@ -26,6 +26,8 @@ typedef struct UA_Connection UA_Connection;
 struct UA_Server;
 typedef struct UA_Server UA_Server;
 
+typedef void (*UA_ServerCallback)(UA_Server *server, void *data);
+
 /** Jobs describe work that is executed once or repeatedly in the server */
 typedef struct {
     enum {
@@ -44,7 +46,7 @@ typedef struct {
         } binaryMessage;
         struct {
             void *data;
-            void (*method)(UA_Server *server, void *data);
+            UA_ServerCallback method;
         } methodCall;
     } job;
 } UA_Job;

+ 9 - 8
src/server/ua_securechannel_manager.c

@@ -1,18 +1,18 @@
 #include "ua_securechannel_manager.h"
 #include "ua_session.h"
-#include "ua_statuscodes.h"
+#include "ua_server_internal.h"
 
 UA_StatusCode
 UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
                              UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
-                             UA_UInt32 startTokenId, UA_Logger logger) {
+                             UA_UInt32 startTokenId, UA_Server *server) {
     LIST_INIT(&cm->channels);
     cm->lastChannelId = startChannelId;
     cm->lastTokenId = startTokenId;
     cm->maxChannelLifetime = tokenLifetime;
     cm->maxChannelCount = maxChannelCount;
     cm->currentChannelCount = 0;
-    cm->logger = logger;
+    cm->server = server;
     return UA_STATUSCODE_GOOD;
 }
 
@@ -33,17 +33,17 @@ void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_Dat
             entry->channel.securityToken.createdAt +
             (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_MSEC_TO_DATETIME);
         if(timeout < now || !entry->channel.connection) {
-            UA_LOG_DEBUG(cm->logger, UA_LOGCATEGORY_SECURECHANNEL,
+            UA_LOG_DEBUG(cm->server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
                          "SecureChannel %i has timed out", entry->channel.securityToken.channelId);
             LIST_REMOVE(entry, pointers);
             UA_SecureChannel_deleteMembersCleanup(&entry->channel);
 #ifndef UA_ENABLE_MULTITHREADING
             cm->currentChannelCount--;
+            UA_free(entry);
 #else
-            cm->currentChannelCount = uatomic_add_return(
-                    &cm->currentChannelCount, -1);
+            cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
+            UA_Server_delayedFree(cm->server, entry);
 #endif
-            UA_free(entry);
         } else if(entry->channel.nextSecurityToken.tokenId > 0) {
             UA_SecureChannel_revolveTokens(&entry->channel);
         }
@@ -144,11 +144,12 @@ UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt
         if(entry->channel.securityToken.channelId == channelId) {
             LIST_REMOVE(entry, pointers);
             UA_SecureChannel_deleteMembersCleanup(&entry->channel);
-            UA_free(entry);
 #ifndef UA_ENABLE_MULTITHREADING
             cm->currentChannelCount--;
+            UA_free(entry);
 #else
             cm->currentChannelCount = uatomic_add_return(&cm->currentChannelCount, -1);
+            UA_Server_delayedFree(cm->server, entry);
 #endif
             return UA_STATUSCODE_GOOD;
         }

+ 2 - 2
src/server/ua_securechannel_manager.h

@@ -20,13 +20,13 @@ typedef struct UA_SecureChannelManager {
     UA_DateTime channelLifeTime;
     UA_UInt32 lastChannelId;
     UA_UInt32 lastTokenId;
-    UA_Logger logger;
+    UA_Server *server;
 } UA_SecureChannelManager;
 
 UA_StatusCode
 UA_SecureChannelManager_init(UA_SecureChannelManager *cm, size_t maxChannelCount,
                              UA_UInt32 tokenLifetime, UA_UInt32 startChannelId,
-                             UA_UInt32 startTokenId, UA_Logger logger);
+                             UA_UInt32 startTokenId, UA_Server *server);
 
 void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm);
 

+ 5 - 5
src/server/ua_server.c

@@ -263,7 +263,7 @@ void UA_Server_delete(UA_Server *server) {
 
     // Delete all internal data
     UA_SecureChannelManager_deleteMembers(&server->secureChannelManager);
-    UA_SessionManager_deleteMembers(&server->sessionManager, server);
+    UA_SessionManager_deleteMembers(&server->sessionManager);
     UA_RCU_LOCK();
     UA_NodeStore_delete(server->nodestore);
     UA_RCU_UNLOCK();
@@ -281,9 +281,9 @@ void UA_Server_delete(UA_Server *server) {
 }
 
 /* Recurring cleanup. Removing unused and timed-out channels and sessions */
-static void UA_Server_cleanup(UA_Server *server, void *nothing) {
+static void UA_Server_cleanup(UA_Server *server, void *_) {
     UA_DateTime now = UA_DateTime_now();
-    UA_SessionManager_cleanupTimedOut(&server->sessionManager, server, now);
+    UA_SessionManager_cleanupTimedOut(&server->sessionManager, now);
     UA_SecureChannelManager_cleanupTimedOut(&server->secureChannelManager, now);
 }
 
@@ -479,13 +479,13 @@ UA_Server * UA_Server_new(const UA_ServerConfig config) {
 #define TOKENLIFETIME 600000 //this is in milliseconds //600000 seems to be the minimal allowet time for UaExpert
 #define STARTTOKENID 1
     UA_SecureChannelManager_init(&server->secureChannelManager, MAXCHANNELCOUNT,
-                                 TOKENLIFETIME, STARTCHANNELID, STARTTOKENID, server->config.logger);
+                                 TOKENLIFETIME, STARTCHANNELID, STARTTOKENID, server);
 
 #define MAXSESSIONCOUNT 1000
 #define MAXSESSIONLIFETIME 3600000
 #define STARTSESSIONID 1
     UA_SessionManager_init(&server->sessionManager, MAXSESSIONCOUNT, MAXSESSIONLIFETIME,
-                           STARTSESSIONID, server->config.logger);
+                           STARTSESSIONID, server);
 
     UA_Job cleanup = {.type = UA_JOBTYPE_METHODCALL,
                       .job.methodCall = {.method = UA_Server_cleanup, .data = NULL} };

+ 2 - 2
src/server/ua_server_internal.h

@@ -90,8 +90,8 @@ UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, const U
 
 void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg);
 
-UA_StatusCode UA_Server_addDelayedJob(UA_Server *server, UA_Job job);
-
+UA_StatusCode UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data);
+UA_StatusCode UA_Server_delayedFree(UA_Server *server, void *data);
 void UA_Server_deleteAllRepeatedJobs(UA_Server *server);
 
 #endif /* UA_SERVER_INTERNAL_H_ */

+ 26 - 4
src/server/ua_server_worker.c

@@ -455,20 +455,42 @@ static void addDelayedJobAsync(UA_Server *server, UA_Job *job) {
     UA_free(job);
 }
 
-UA_StatusCode UA_Server_addDelayedJob(UA_Server *server, UA_Job job) {
+static void server_free(UA_Server *server, void *data) {
+    UA_free(data);
+}
+
+UA_StatusCode UA_Server_delayedFree(UA_Server *server, void *data) {
+    UA_Job *j = UA_malloc(sizeof(UA_Job));
+    if(!j)
+        return UA_STATUSCODE_BADOUTOFMEMORY;
+    j->type = UA_JOBTYPE_METHODCALL;
+    j->job.methodCall.data = data;
+    j->job.methodCall.method = server_free;
+    struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
+    mlw->job = (UA_Job) {.type = UA_JOBTYPE_METHODCALL, .job.methodCall =
+                         {.data = j, .method = (UA_ServerCallback)addDelayedJobAsync}};
+    cds_lfs_push(&server->mainLoopJobs, &mlw->node);
+    return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode
+UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback, void *data) {
     UA_Job *j = UA_malloc(sizeof(UA_Job));
     if(!j)
         return UA_STATUSCODE_BADOUTOFMEMORY;
-    *j = job;
+    j->type = UA_JOBTYPE_METHODCALL;
+    j->job.methodCall.data = data;
+    j->job.methodCall.method = callback;
     struct MainLoopJob *mlw = UA_malloc(sizeof(struct MainLoopJob));
     mlw->job = (UA_Job) {.type = UA_JOBTYPE_METHODCALL, .job.methodCall =
-                         {.data = j, .method = (void (*)(UA_Server*, void*))addDelayedJobAsync}};
+                         {.data = j, .method = (UA_ServerCallback)addDelayedJobAsync}};
     cds_lfs_push(&server->mainLoopJobs, &mlw->node);
     return UA_STATUSCODE_GOOD;
 }
 
 /* Find out which delayed jobs can be executed now */
-static void dispatchDelayedJobs(UA_Server *server, void *data /* not used, but needed for the signature*/) {
+static void
+dispatchDelayedJobs(UA_Server *server, void *_) {
     /* start at the second */
     struct DelayedJobs *dw = server->delayedJobs, *beforedw = dw;
     if(dw)

+ 7 - 9
src/server/ua_services_session.c

@@ -3,8 +3,7 @@
 #include "ua_session_manager.h"
 #include "ua_types_generated_encoding_binary.h"
 
-void Service_CreateSession(UA_Server *server, UA_Session *session,
-                           const UA_CreateSessionRequest *request,
+void Service_CreateSession(UA_Server *server, UA_Session *session, const UA_CreateSessionRequest *request,
                            UA_CreateSessionResponse *response) {
     UA_SecureChannel *channel = session->channel;
     if(channel->securityToken.channelId == 0) {
@@ -38,7 +37,7 @@ void Service_CreateSession(UA_Server *server, UA_Session *session,
         response->responseHeader.serviceResult |=
             UA_ByteString_copy(&server->endpointDescriptions->serverCertificate, &response->serverCertificate);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
-        UA_SessionManager_removeSession(&server->sessionManager, server, &newSession->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken);
          return;
     }
     UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
@@ -48,8 +47,7 @@ void Service_CreateSession(UA_Server *server, UA_Session *session,
 }
 
 void
-Service_ActivateSession(UA_Server *server, UA_Session *session,
-                        const UA_ActivateSessionRequest *request,
+Service_ActivateSession(UA_Server *server, UA_Session *session, const UA_ActivateSessionRequest *request,
                         UA_ActivateSessionResponse *response) {
     UA_SecureChannel *channel = session->channel;
     // make the channel know about the session
@@ -59,7 +57,8 @@ Service_ActivateSession(UA_Server *server, UA_Session *session,
 	if(!foundSession) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
         UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
-                     "Processing ActivateSessionRequest on SecureChannel %i, but no session found for the authentication token",
+                     "Processing ActivateSessionRequest on SecureChannel %i, "
+                     "but no session found for the authentication token",
                      channel->securityToken.channelId);
         return;
 	}
@@ -149,12 +148,11 @@ Service_ActivateSession(UA_Server *server, UA_Session *session,
 }
 
 void
-Service_CloseSession(UA_Server *server, UA_Session *session,
-                     const UA_CloseSessionRequest *request,
+Service_CloseSession(UA_Server *server, UA_Session *session, const UA_CloseSessionRequest *request,
                      UA_CloseSessionResponse *response) {
     UA_LOG_DEBUG(server->config.logger, UA_LOGCATEGORY_SESSION,
                  "Processing CloseSessionRequest for Session (ns=%i,i=%i)",
                  session->sessionId.namespaceIndex, session->sessionId.identifier.numeric);
     response->responseHeader.serviceResult =
-        UA_SessionManager_removeSession(&server->sessionManager, server, &session->authenticationToken);
+        UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
 }

+ 45 - 37
src/server/ua_session_manager.c

@@ -1,95 +1,98 @@
 #include "ua_session_manager.h"
-#include "ua_statuscodes.h"
-#include "ua_util.h"
+#include "ua_server_internal.h"
 
 UA_StatusCode
-UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
+UA_SessionManager_init(UA_SessionManager *sm, UA_UInt32 maxSessionCount,
                        UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId,
-                       UA_Logger logger) {
-    LIST_INIT(&sessionManager->sessions);
-    sessionManager->maxSessionCount = maxSessionCount;
-    sessionManager->lastSessionId   = startSessionId;
-    sessionManager->maxSessionLifeTime  = maxSessionLifeTime;
-    sessionManager->currentSessionCount = 0;
-    sessionManager->logger = logger;
+                       UA_Server *server) {
+    LIST_INIT(&sm->sessions);
+    sm->maxSessionCount = maxSessionCount;
+    sm->lastSessionId   = startSessionId;
+    sm->maxSessionLifeTime  = maxSessionLifeTime;
+    sm->currentSessionCount = 0;
+    sm->server = server;
     return UA_STATUSCODE_GOOD;
 }
 
-void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager, UA_Server *server) {
+void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
     session_list_entry *current, *temp;
-    LIST_FOREACH_SAFE(current, &sessionManager->sessions, pointers, temp) {
+    LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
         LIST_REMOVE(current, pointers);
-        UA_Session_deleteMembersCleanup(&current->session, server);
+        UA_Session_deleteMembersCleanup(&current->session, sm->server);
         UA_free(current);
     }
 }
 
-void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager,
-                                       UA_Server* server, UA_DateTime now) {
+void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm, UA_DateTime now) {
     session_list_entry *sentry, *temp;
-    LIST_FOREACH_SAFE(sentry, &sessionManager->sessions, pointers, temp) {
+    LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
         if(sentry->session.validTill < now) {
-            UA_LOG_DEBUG(sessionManager->logger, UA_LOGCATEGORY_SESSION, "Session with token %i has timed out and is removed",
+            UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
+                         "Session with token %i has timed out and is removed",
                          sentry->session.sessionId.identifier.numeric);
             LIST_REMOVE(sentry, pointers);
-            UA_Session_deleteMembersCleanup(&sentry->session, server);
+            UA_Session_deleteMembersCleanup(&sentry->session, sm->server);
+#ifndef UA_ENABLE_MULTITHREADING
+            sm->currentSessionCount--;
             UA_free(sentry);
-            sessionManager->currentSessionCount--;
+#else
+            sm->currentSessionCount = uatomic_add_return(&sm->currentSessionCount, -1);
+            UA_Server_delayedFree(sm->server, sentry);
+#endif
         }
     }
 }
 
 UA_Session *
-UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token) {
+UA_SessionManager_getSession(UA_SessionManager *sm, const UA_NodeId *token) {
     session_list_entry *current = NULL;
-    LIST_FOREACH(current, &sessionManager->sessions, pointers) {
+    LIST_FOREACH(current, &sm->sessions, pointers) {
         if(UA_NodeId_equal(&current->session.authenticationToken, token)) {
             if(UA_DateTime_now() > current->session.validTill) {
-                UA_LOG_DEBUG(sessionManager->logger, UA_LOGCATEGORY_SESSION, "Try to use Session with token %i, but has timed out",
-                             token->identifier.numeric);
+                UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
+                             "Try to use Session with token %i, but has timed out", token->identifier.numeric);
                 return NULL;
             }
             return &current->session;
         }
     }
-    UA_LOG_DEBUG(sessionManager->logger, UA_LOGCATEGORY_SESSION, "Try to use Session with token %i but is not found",
-                 token->identifier.numeric);
+    UA_LOG_DEBUG(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
+                 "Try to use Session with token %i but is not found", token->identifier.numeric);
     return NULL;
 }
 
 /** Creates and adds a session. But it is not yet attached to a secure channel. */
 UA_StatusCode
-UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
+UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
                                 const UA_CreateSessionRequest *request, UA_Session **session) {
-    if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
+    if(sm->currentSessionCount >= sm->maxSessionCount)
         return UA_STATUSCODE_BADTOOMANYSESSIONS;
 
     session_list_entry *newentry = UA_malloc(sizeof(session_list_entry));
     if(!newentry)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
-    sessionManager->currentSessionCount++;
+    sm->currentSessionCount++;
     UA_Session_init(&newentry->session);
-    newentry->session.sessionId = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId++);
+    newentry->session.sessionId = UA_NODEID_NUMERIC(1, sm->lastSessionId++);
     newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
 
-    if(request->requestedSessionTimeout <= sessionManager->maxSessionLifeTime &&
+    if(request->requestedSessionTimeout <= sm->maxSessionLifeTime &&
        request->requestedSessionTimeout > 0)
         newentry->session.timeout = request->requestedSessionTimeout;
     else
-        newentry->session.timeout = sessionManager->maxSessionLifeTime; // todo: remove when the CTT is fixed
+        newentry->session.timeout = sm->maxSessionLifeTime; // todo: remove when the CTT is fixed
 
     UA_Session_updateLifetime(&newentry->session);
-    LIST_INSERT_HEAD(&sessionManager->sessions, newentry, pointers);
+    LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
     *session = &newentry->session;
     return UA_STATUSCODE_GOOD;
 }
 
 UA_StatusCode
-UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
-                                UA_Server* server, const UA_NodeId *token) {
+UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
     session_list_entry *current;
-    LIST_FOREACH(current, &sessionManager->sessions, pointers) {
+    LIST_FOREACH(current, &sm->sessions, pointers) {
         if(UA_NodeId_equal(&current->session.authenticationToken, token))
             break;
     }
@@ -98,8 +101,13 @@ UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
         return UA_STATUSCODE_BADSESSIONIDINVALID;
 
     LIST_REMOVE(current, pointers);
-    UA_Session_deleteMembersCleanup(&current->session, server);
+    UA_Session_deleteMembersCleanup(&current->session, sm->server);
+#ifndef UA_ENABLE_MULTITHREADING
+    sm->currentSessionCount--;
     UA_free(current);
-    sessionManager->currentSessionCount--;
+#else
+    sm->currentSessionCount = uatomic_add_return(&sm->currentSessionCount, -1);
+    UA_Server_delayedFree(sm->server, current);
+#endif
     return UA_STATUSCODE_GOOD;
 }

+ 7 - 9
src/server/ua_session_manager.h

@@ -17,25 +17,23 @@ typedef struct UA_SessionManager {
     UA_UInt32 lastSessionId;
     UA_UInt32 currentSessionCount;
     UA_UInt32 maxSessionLifeTime;    // time in [ms]
-    UA_Logger logger;
+    UA_Server *server;
 } UA_SessionManager;
 
 UA_StatusCode
 UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
-                       UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId, UA_Logger logger);
+                       UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId, UA_Server *server);
 
-void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager, UA_Server *server);
+void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager);
 
-void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_Server *server, UA_DateTime now);
+void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_DateTime now);
 
 UA_StatusCode
-UA_SessionManager_createSession(UA_SessionManager *sessionManager,
-                                UA_SecureChannel *channel, const UA_CreateSessionRequest *request,
-                                UA_Session **session);
+UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
+                                const UA_CreateSessionRequest *request, UA_Session **session);
 
 UA_StatusCode
-UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
-                                UA_Server *server, const UA_NodeId *token);
+UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
 
 UA_Session *
 UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token);