Преглед на файлове

handle multiple sessions per securechannel

Julius Pfrommer преди 10 години
родител
ревизия
e249b82f2a

+ 6 - 26
src/server/ua_securechannel_manager.c

@@ -14,17 +14,12 @@ UA_StatusCode UA_SecureChannelManager_init(UA_SecureChannelManager *cm, UA_UInt3
 }
 
 void UA_SecureChannelManager_deleteMembers(UA_SecureChannelManager *cm) {
-    channel_list_entry *current, *next = LIST_FIRST(&cm->channels);
-    while(next) {
-        current = next;
-        next = LIST_NEXT(current, pointers);
+    channel_list_entry *current = LIST_FIRST(&cm->channels);
+    while(current) {
         LIST_REMOVE(current, pointers);
-        if(current->channel.session)
-            current->channel.session->channel = UA_NULL;
-        if(current->channel.connection)
-            current->channel.connection->channel = UA_NULL;
-        UA_SecureChannel_deleteMembers(&current->channel);
+        UA_SecureChannel_deleteMembersCleanup(&current->channel);
         UA_free(current);
+        current = LIST_FIRST(&cm->channels);
     }
 }
 
@@ -40,13 +35,7 @@ void UA_SecureChannelManager_cleanupTimedOut(UA_SecureChannelManager *cm, UA_Dat
         else {
             channel_list_entry *next = LIST_NEXT(entry, pointers);
             LIST_REMOVE(entry, pointers);
-            UA_Connection *c = entry->channel.connection;
-            if(c) {
-                UA_Connection_detachSecureChannel(c);
-                c->close(c);
-            }
-            UA_SecureChannel_detachSession(&entry->channel);
-            UA_SecureChannel_deleteMembers(&entry->channel);
+            UA_SecureChannel_deleteMembersCleanup(&entry->channel);
             UA_free(entry);
             entry = next;
         }
@@ -127,7 +116,6 @@ UA_StatusCode UA_SecureChannelManager_renew(UA_SecureChannelManager *cm, UA_Conn
     UA_SecureChannel_generateNonce(&channel->serverNonce);
     UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
     UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
-
     return UA_STATUSCODE_GOOD;
 }
 
@@ -141,7 +129,6 @@ UA_SecureChannel * UA_SecureChannelManager_get(UA_SecureChannelManager *cm, UA_U
 }
 
 UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt32 channelId) {
-    // TODO lock access
     channel_list_entry *entry;
     LIST_FOREACH(entry, &cm->channels, pointers) {
         if(entry->channel.securityToken.channelId == channelId)
@@ -149,15 +136,8 @@ UA_StatusCode UA_SecureChannelManager_close(UA_SecureChannelManager *cm, UA_UInt
     }
     if(!entry)
         return UA_STATUSCODE_BADINTERNALERROR;
-
     LIST_REMOVE(entry, pointers);
-    UA_Connection *c = entry->channel.connection;
-    if(c) {
-        UA_Connection_detachSecureChannel(c);
-        c->close(c);
-    }
-    UA_SecureChannel_detachSession(&entry->channel);
-    UA_SecureChannel_deleteMembers(&entry->channel);
+    UA_SecureChannel_deleteMembersCleanup(&entry->channel);
     UA_free(entry);
     return UA_STATUSCODE_GOOD;
 }

+ 15 - 10
src/server/ua_server_binary.c

@@ -128,18 +128,23 @@ static void invoke_service(UA_Server *server, UA_SecureChannel *channel,
                            UA_RequestHeader *request, UA_ResponseHeader *response,
                            void (*service)(UA_Server*, UA_Session*, void*, void*)) {
     init_response_header(request, response);
-    if(!channel->session ||
-        !UA_NodeId_equal(&channel->session->authenticationToken,
-                         &request->authenticationToken))
+    /* try to get the session from the securechannel first */
+    UA_Session *session = UA_SecureChannel_getSession(channel, &request->authenticationToken);
+    if(!session)
+        session = UA_SessionManager_getSession(&server->sessionManager, &request->authenticationToken);
+    if(!session)
+        response->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
+    else if(session->activated == UA_FALSE) {
+        response->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
+        /* the session is invalidated */
+        UA_SessionManager_removeSession(&server->sessionManager, &request->authenticationToken);
+    }
+    else if(session->channel != channel)
         response->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
-    else if(channel->session->channel != channel)
-            response->serviceResult = UA_STATUSCODE_BADSECURECHANNELIDINVALID;
-    else if(channel->session->activated == UA_FALSE)
-            response->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED;
     else {
-            UA_Session_updateLifetime(channel->session);
-            service(server, channel->session, request, response);
-        }
+            UA_Session_updateLifetime(session);
+            service(server, session, request, response);
+    }
 }
 
 #define INVOKE_SERVICE(TYPE) do {                                       \

+ 16 - 25
src/server/ua_services_session.c

@@ -7,7 +7,6 @@
 void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
                            const UA_CreateSessionRequest *request,
                            UA_CreateSessionResponse *response) {
-
     response->serverEndpoints = UA_malloc(sizeof(UA_EndpointDescription));
     if(!response->serverEndpoints || (response->responseHeader.serviceResult =
         UA_EndpointDescription_copy(server->endpointDescriptions, response->serverEndpoints)) !=
@@ -15,17 +14,12 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
         return;
     response->serverEndpointsSize = 1;
 
-    // creates a session and adds a pointer to the channel. Only when the
-    // session is activated will the channel point to the session as well
 	UA_Session *newSession;
     response->responseHeader.serviceResult = UA_SessionManager_createSession(&server->sessionManager,
                                                                              channel, request, &newSession);
 	if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD)
 		return;
 
-	//bind session to channel
-	channel->session = newSession;
-
     //TODO get maxResponseMessageSize internally
     newSession->maxResponseMessageSize = request->maxResponseMessageSize;
     response->sessionId = newSession->sessionId;
@@ -36,12 +30,12 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
         response->responseHeader.serviceResult |=
             UA_ByteString_copy(&server->endpointDescriptions->serverCertificate, &response->serverCertificate);
     if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) {
-        UA_SessionManager_removeSession(&server->sessionManager, &newSession->sessionId);
+        UA_SessionManager_removeSession(&server->sessionManager, &newSession->authenticationToken);
          return;
     }
 }
 
-void Service_ActivateSession(UA_Server *server,UA_SecureChannel *channel,
+void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
                              const UA_ActivateSessionRequest *request,
                              UA_ActivateSessionResponse *response) {
     // make the channel know about the session
@@ -49,12 +43,10 @@ void Service_ActivateSession(UA_Server *server,UA_SecureChannel *channel,
         UA_SessionManager_getSession(&server->sessionManager,
                                      (const UA_NodeId*)&request->requestHeader.authenticationToken);
 
-	if(foundSession == UA_NULL){
+	if(foundSession == UA_NULL) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
         return;
-	}
-
-	if(foundSession->validTill < UA_DateTime_now()){
+	} else if(foundSession->validTill < UA_DateTime_now()) {
         response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
         return;
 	}
@@ -70,14 +62,16 @@ void Service_ActivateSession(UA_Server *server,UA_SecureChannel *channel,
     if(token.policyId.data == UA_NULL) {
         /* 1) no policy defined */
         response->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
-    } else if(server->config.Login_enableAnonymous && UA_String_equalchars(&token.policyId, ANONYMOUS_POLICY)) {
+    } else if(server->config.Login_enableAnonymous &&
+              UA_String_equalchars(&token.policyId, ANONYMOUS_POLICY)) {
         /* 2) anonymous logins */
-        if(foundSession->channel)
-            UA_Session_detachSecureChannel(foundSession);
+        if(foundSession->channel && foundSession->channel != channel)
+            UA_SecureChannel_detachSession(foundSession->channel, foundSession);
         UA_SecureChannel_attachSession(channel, foundSession);
         foundSession->activated = UA_TRUE;
         UA_Session_updateLifetime(foundSession);
-    } else if(server->config.Login_enableUsernamePassword && UA_String_equalchars(&token.policyId, USERNAME_POLICY)) {
+    } else if(server->config.Login_enableUsernamePassword &&
+              UA_String_equalchars(&token.policyId, USERNAME_POLICY)) {
         /* 3) username logins */
         offset = 0;
         UA_UserNameIdentityToken_decodeBinary(&request->userIdentityToken.body, &offset, &username_token);
@@ -94,8 +88,8 @@ void Service_ActivateSession(UA_Server *server,UA_SecureChannel *channel,
                 if(UA_String_equalchars(&username_token.userName, server->config.Login_usernames[i])
                     && UA_String_equalchars(&username_token.password, server->config.Login_passwords[i])) {
                     /* success - activate */
-                    if(foundSession->channel)
-                        UA_Session_detachSecureChannel(foundSession);
+                    if(foundSession->channel && foundSession->channel != channel)
+                        UA_SecureChannel_detachSession(foundSession->channel, foundSession);
                     UA_SecureChannel_attachSession(channel, foundSession);
                     foundSession->activated = UA_TRUE;
                     UA_Session_updateLifetime(foundSession);
@@ -119,12 +113,9 @@ void Service_CloseSession(UA_Server *server, UA_Session *session, const UA_Close
 	UA_Session *foundSession =
         UA_SessionManager_getSession(&server->sessionManager,
 		                             (const UA_NodeId*)&request->requestHeader.authenticationToken);
-
-	if(foundSession == UA_NULL){
+	if(foundSession == UA_NULL)
 		response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
-		return;
-	}
-
-	response->responseHeader.serviceResult =
-        UA_SessionManager_removeSession(&server->sessionManager, &session->sessionId);
+	else 
+        response->responseHeader.serviceResult =
+            UA_SessionManager_removeSession(&server->sessionManager, &session->authenticationToken);
 }

+ 18 - 40
src/server/ua_session_manager.c

@@ -2,12 +2,6 @@
 #include "ua_statuscodes.h"
 #include "ua_util.h"
 
-/**
- The functions in this file are not thread-safe. For multi-threaded access, a
- second implementation should be provided. See for example, how a nodestore
- implementation is choosen based on whether multithreading is enabled or not.
- */
-
 UA_StatusCode UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
                                     UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId) {
     LIST_INIT(&sessionManager->sessions);
@@ -19,14 +13,10 @@ UA_StatusCode UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt3
 }
 
 void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager) {
-    session_list_entry *current, *next = LIST_FIRST(&sessionManager->sessions);
-    while(next) {
-        current = next;
-        next = LIST_NEXT(current, pointers);
+    session_list_entry *current;
+    while((current = LIST_FIRST(&sessionManager->sessions))) {
         LIST_REMOVE(current, pointers);
-        if(current->session.channel)
-            UA_SecureChannel_detachSession(current->session.channel);
-        UA_Session_deleteMembers(&current->session);
+        UA_Session_deleteMembersCleanup(&current->session);
         UA_free(current);
     }
 }
@@ -37,10 +27,9 @@ void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_Dat
         if(sentry->session.validTill < now) {
             session_list_entry *next = LIST_NEXT(sentry, pointers);
             LIST_REMOVE(sentry, pointers);
-            if(sentry->session.channel)
-                UA_SecureChannel_detachSession(sentry->session.channel);
-            UA_Session_deleteMembers(&sentry->session);
+            UA_Session_deleteMembersCleanup(&sentry->session);
             UA_free(sentry);
+            sessionManager->currentSessionCount--;
             sentry = next;
         } else {
             sentry = LIST_NEXT(sentry, pointers);
@@ -59,52 +48,41 @@ UA_Session * UA_SessionManager_getSession(UA_SessionManager *sessionManager, con
     return &current->session;
 }
 
-/** Creates and adds a session. */
-UA_StatusCode
-UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
-                                const UA_CreateSessionRequest *request, UA_Session **session)
-{
+/** 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,
+                                              const UA_CreateSessionRequest *request, UA_Session **session) {
     if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
         return UA_STATUSCODE_BADTOOMANYSESSIONS;
-
-    if(channel->session != UA_NULL)
-        return UA_STATUSCODE_BADTOOMANYSESSIONS;
-
     session_list_entry *newentry = UA_malloc(sizeof(session_list_entry));
     if(!newentry)
         return UA_STATUSCODE_BADOUTOFMEMORY;
-
+    sessionManager->currentSessionCount++;
     UA_Session_init(&newentry->session);
     newentry->session.sessionId = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId++);
-    newentry->session.authenticationToken = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId);
-    newentry->session.channel = channel;
+    UA_UInt32 randSeed = sessionManager->lastSessionId;
+    newentry->session.authenticationToken =
+        UA_NODEID_GUID(1, UA_Guid_random(&randSeed));
     newentry->session.timeout =
         (request->requestedSessionTimeout <= sessionManager->maxSessionLifeTime &&
          request->requestedSessionTimeout>0) ?
         request->requestedSessionTimeout : sessionManager->maxSessionLifeTime;
     UA_Session_updateLifetime(&newentry->session);
-
-    sessionManager->currentSessionCount++;
     LIST_INSERT_HEAD(&sessionManager->sessions, newentry, pointers);
     *session = &newentry->session;
     return UA_STATUSCODE_GOOD;
 }
 
-UA_StatusCode
-UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *sessionId)
-{
+UA_StatusCode UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *token) {
     session_list_entry *current;
     LIST_FOREACH(current, &sessionManager->sessions, pointers) {
-        if(UA_NodeId_equal(&current->session.sessionId, sessionId))
+        if(UA_NodeId_equal(&current->session.authenticationToken, token))
             break;
     }
-
     if(!current)
-        return UA_STATUSCODE_BADINTERNALERROR;
-
+        return UA_STATUSCODE_BADSESSIONIDINVALID;
     LIST_REMOVE(current, pointers);
-    UA_SecureChannel_detachSession(current->session.channel);
-    UA_Session_deleteMembers(&current->session);
+    UA_Session_deleteMembersCleanup(&current->session);
     UA_free(current);
+    sessionManager->currentSessionCount--;
     return UA_STATUSCODE_GOOD;
-}
+}

+ 4 - 4
src/server/ua_session_manager.h

@@ -7,8 +7,8 @@
 #include "ua_session.h"
 
 typedef struct session_list_entry {
-    UA_Session session;
     LIST_ENTRY(session_list_entry) pointers;
+    UA_Session session;
 } session_list_entry;
 
 typedef struct UA_SessionManager {
@@ -27,10 +27,10 @@ void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager);
 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_SecureChannel *channel, const UA_CreateSessionRequest *request,
+                                              UA_Session **session);
 
-UA_StatusCode UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
-                                              const UA_NodeId *sessionId);
+UA_StatusCode UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *token);
 
 /** Finds the session which is identified by the authentication token */
 UA_Session * UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token);

+ 26 - 0
src/ua_connection.c

@@ -1,6 +1,7 @@
 #include "ua_util.h"
 #include "ua_connection.h"
 #include "ua_types_encoding_binary.h"
+#include "ua_securechannel.h"
 
 const char *UA_LoggerCategoryNames[4] = {"communication", "server", "client", "userland"};
 
@@ -98,3 +99,28 @@ UA_ByteString UA_Connection_completeMessages(UA_Connection *connection, UA_ByteS
     }
     return current;
 }
+
+void UA_Connection_detachSecureChannel(UA_Connection *connection) {
+#ifdef UA_MULTITHREADING
+    UA_SecureChannel *channel = connection->channel;
+    if(channel)
+        uatomic_cmpxchg(&channel->connection, connection, UA_NULL);
+    uatomic_set(&connection->channel, UA_NULL);
+#else
+    if(connection->channel)
+        connection->channel->connection = UA_NULL;
+    connection->channel = UA_NULL;
+#endif
+}
+
+void UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
+#ifdef UA_MULTITHREADING
+    if(uatomic_cmpxchg(&channel->connection, UA_NULL, connection) == UA_NULL)
+        uatomic_set(&connection->channel, channel);
+#else
+    if(channel->connection != UA_NULL)
+        return;
+    channel->connection = connection;
+    connection->channel = channel;
+#endif
+}

+ 51 - 21
src/ua_securechannel.c

@@ -1,5 +1,6 @@
 #include "ua_util.h"
 #include "ua_securechannel.h"
+#include "ua_session.h"
 #include "ua_statuscodes.h"
 
 void UA_SecureChannel_init(UA_SecureChannel *channel) {
@@ -12,15 +13,25 @@ void UA_SecureChannel_init(UA_SecureChannel *channel) {
     channel->requestId = 0;
     channel->sequenceNumber = 0;
     channel->connection = UA_NULL;
-    channel->session    = UA_NULL;
+    LIST_INIT(&channel->sessions);
 }
 
-void UA_SecureChannel_deleteMembers(UA_SecureChannel *channel) {
+void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel) {
     UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->serverAsymAlgSettings);
     UA_ByteString_deleteMembers(&channel->serverNonce);
     UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&channel->clientAsymAlgSettings);
     UA_ByteString_deleteMembers(&channel->clientNonce);
     UA_ChannelSecurityToken_deleteMembers(&channel->securityToken);
+    UA_Connection *c = channel->connection;
+    if(c) {
+        UA_Connection_detachSecureChannel(c);
+        c->close(c);
+    }
+    /* just remove the pointers and free the linked list (not the sessions) */
+    struct SessionEntry *se;
+    while((se = LIST_FIRST(&channel->sessions))) {
+        UA_SecureChannel_detachSession(channel, se->session); /* the se is deleted inside */
+    }
 }
 
 //TODO implement real nonce generator - DUMMY function
@@ -48,28 +59,47 @@ UA_StatusCode UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, U
     return UA_STATUSCODE_GOOD;
 }
 
-/* these need ua_securechannel.h */
-void UA_Connection_detachSecureChannel(UA_Connection *connection) {
+void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
+    struct SessionEntry *se = UA_malloc(sizeof(struct SessionEntry));
+    if(!se)
+        return;
+    se->session = session;
 #ifdef UA_MULTITHREADING
-    UA_SecureChannel *channel = connection->channel;
-    if(channel)
-        uatomic_cmpxchg(&channel->connection, connection, UA_NULL);
-    uatomic_set(&connection->channel, UA_NULL);
+    if(uatomic_cmpxchg(&session->channel, UA_NULL, channel) != UA_NULL) {
+        UA_free(se);
+        return;
+    }
 #else
-    if(connection->channel)
-        connection->channel->connection = UA_NULL;
-    connection->channel = UA_NULL;
+    if(session->channel != UA_NULL) {
+        UA_free(se);
+        return;
+    }
+    session->channel = channel;
 #endif
+    LIST_INSERT_HEAD(&channel->sessions, se, pointers);
 }
 
-void UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel) {
-#ifdef UA_MULTITHREADING
-    if(uatomic_cmpxchg(&channel->connection, UA_NULL, connection) == UA_NULL)
-        uatomic_set(&connection->channel, channel);
-#else
-    if(channel->connection != UA_NULL)
-        return;
-    channel->connection = connection;
-    connection->channel = channel;
-#endif
+void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session) {
+    if(session)
+        session->channel = UA_NULL;
+    struct SessionEntry *se;
+    LIST_FOREACH(se, &channel->sessions, pointers) {
+        if(se->session != session)
+            continue;
+        LIST_REMOVE(se, pointers);
+        UA_free(se);
+        break;
+    }
+}
+
+UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token) {
+    struct SessionEntry *se;
+    LIST_FOREACH(se, &channel->sessions, pointers) {
+        if(UA_NodeId_equal(&se->session->authenticationToken, token))
+            break;
+    }
+    if(se)
+        return se->session;
+    else
+        return UA_NULL;
 }

+ 10 - 3
src/ua_securechannel.h

@@ -1,6 +1,7 @@
 #ifndef UA_SECURECHANNEL_H_
 #define UA_SECURECHANNEL_H_
 
+#include "queue.h"
 #include "ua_types_generated.h"
 #include "ua_transport_generated.h"
 #include "ua_connection.h"
@@ -14,6 +15,11 @@
 struct UA_Session;
 typedef struct UA_Session UA_Session;
 
+struct SessionEntry {
+    LIST_ENTRY(SessionEntry) pointers;
+    UA_Session *session; // Just a pointer. The session is held in the session manager or the client
+};
+
 struct UA_SecureChannel {
     UA_MessageSecurityMode  securityMode;
     UA_ChannelSecurityToken securityToken; // the channelId is contained in the securityToken
@@ -24,18 +30,19 @@ struct UA_SecureChannel {
     UA_UInt32      requestId;
     UA_UInt32      sequenceNumber;
     UA_Connection *connection;
-    UA_Session    *session;
+    LIST_HEAD(session_pointerlist, SessionEntry) sessions;
 };
 
 void UA_SecureChannel_init(UA_SecureChannel *channel);
-void UA_SecureChannel_deleteMembers(UA_SecureChannel *channel);
+void UA_SecureChannel_deleteMembersCleanup(UA_SecureChannel *channel);
 
 UA_StatusCode UA_SecureChannel_generateNonce(UA_ByteString *nonce);
 UA_StatusCode UA_SecureChannel_updateRequestId(UA_SecureChannel *channel, UA_UInt32 requestId);
 UA_StatusCode UA_SecureChannel_updateSequenceNumber(UA_SecureChannel *channel, UA_UInt32 sequenceNumber);
 
 void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session);
-void UA_SecureChannel_detachSession(UA_SecureChannel *channel);
+void UA_SecureChannel_detachSession(UA_SecureChannel *channel, UA_Session *session);
+UA_Session * UA_SecureChannel_getSession(UA_SecureChannel *channel, UA_NodeId *token);
 
 /** @} */
 

+ 3 - 41
src/ua_session.c

@@ -44,12 +44,11 @@ void UA_Session_init(UA_Session *session) {
     LIST_INIT(&session->continuationPoints);
 }
 
-void UA_Session_deleteMembers(UA_Session *session) {
+void UA_Session_deleteMembersCleanup(UA_Session *session) {
     UA_ApplicationDescription_deleteMembers(&session->clientDescription);
     UA_NodeId_deleteMembers(&session->authenticationToken);
     UA_NodeId_deleteMembers(&session->sessionId);
     UA_String_deleteMembers(&session->sessionName);
-    session->channel = UA_NULL;
     struct ContinuationPointEntry *cp;
     while((cp = LIST_FIRST(&session->continuationPoints))) {
         UA_ByteString_deleteMembers(&cp->identifier);
@@ -57,47 +56,10 @@ void UA_Session_deleteMembers(UA_Session *session) {
         LIST_REMOVE(cp, pointers);
         UA_free(cp);
     }
+    if(session->channel)
+        UA_SecureChannel_detachSession(session->channel, session);
 }
 
 void UA_Session_updateLifetime(UA_Session *session) {
     session->validTill = UA_DateTime_now() + session->timeout * 10000; //timeout in ms
 }
-
-void UA_Session_detachSecureChannel(UA_Session *session) {
-#ifdef UA_MULTITHREADING
-    UA_SecureChannel *channel = session->channel;
-    if(channel)
-        uatomic_cmpxchg(&channel->session, session, UA_NULL);
-    uatomic_set(&session->channel, UA_NULL);
-#else
-    if(session->channel)
-        session->channel->session = UA_NULL;
-    session->channel = UA_NULL;
-#endif
-}
-
-/* these functions are here, since they need to include ua_session.h */
-void UA_SecureChannel_attachSession(UA_SecureChannel *channel, UA_Session *session) {
-#ifdef UA_MULTITHREADING
-    if(uatomic_cmpxchg(&session->channel, UA_NULL, channel) == UA_NULL)
-        uatomic_set(&channel->session, session);
-#else
-    if(session->channel != UA_NULL)
-        return;
-    session->channel = channel;
-    channel->session = session;
-#endif
-}
-
-void UA_SecureChannel_detachSession(UA_SecureChannel *channel) {
-#ifdef UA_MULTITHREADING
-    UA_Session *session = channel->session;
-    if(session)
-        uatomic_cmpxchg(&session->channel, channel, UA_NULL);
-    uatomic_set(&channel->session, UA_NULL);
-#else
-    if(channel->session)
-        channel->session->channel = UA_NULL;
-    channel->session = UA_NULL;
-#endif
-}

+ 2 - 4
src/ua_session.h

@@ -1,9 +1,9 @@
 #ifndef UA_SESSION_H_
 #define UA_SESSION_H_
 
+#include "queue.h"
 #include "ua_types.h"
 #include "ua_securechannel.h"
-#include "queue.h"
 
 /**
  *  @ingroup communication
@@ -37,13 +37,11 @@ extern UA_Session anonymousSession; ///< If anonymous access is allowed, this se
 extern UA_Session adminSession; ///< Local access to the services (for startup and maintenance) uses this Session with all possible access rights (Session ID: 1)
 
 void UA_Session_init(UA_Session *session);
-void UA_Session_deleteMembers(UA_Session *session);
+void UA_Session_deleteMembersCleanup(UA_Session *session);
 
 /** If any activity on a session happens, the timeout is extended */
 void UA_Session_updateLifetime(UA_Session *session);
 
-void UA_Session_detachSecureChannel(UA_Session *session);
-
 /** @} */
 
 #endif /* UA_SESSION_H_ */