|
@@ -1,9 +1,19 @@
|
|
|
#include "ua_session_manager.h"
|
|
|
-#include "util/ua_util.h"
|
|
|
-#include "util/ua_list.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.
|
|
|
+ */
|
|
|
+
|
|
|
+struct session_list_entry {
|
|
|
+ UA_Session session;
|
|
|
+ LIST_ENTRY(session_list_entry) pointers;
|
|
|
+};
|
|
|
|
|
|
struct UA_SessionManager {
|
|
|
- UA_list_List sessions;
|
|
|
+ LIST_HEAD(session_list, session_list_entry) sessions;
|
|
|
UA_UInt32 maxSessionCount;
|
|
|
UA_Int32 lastSessionId;
|
|
|
UA_UInt32 currentSessionCount;
|
|
@@ -17,7 +27,7 @@ UA_Int32 UA_SessionManager_new(UA_SessionManager **sessionManager, UA_UInt32 max
|
|
|
retval |= UA_alloc((void **)sessionManager, sizeof(UA_SessionManager));
|
|
|
if(retval != UA_SUCCESS)
|
|
|
return UA_ERROR;
|
|
|
- retval |= UA_list_init(&(*sessionManager)->sessions);
|
|
|
+ LIST_INIT(&(*sessionManager)->sessions);
|
|
|
(*sessionManager)->maxSessionCount = maxSessionCount;
|
|
|
(*sessionManager)->lastSessionId = startSessionId;
|
|
|
(*sessionManager)->sessionTimeout = sessionTimeout;
|
|
@@ -29,119 +39,86 @@ UA_Int32 UA_SessionManager_delete(UA_SessionManager *sessionManager) {
|
|
|
return UA_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-UA_Boolean UA_SessionManager_sessionExists(UA_SessionManager *sessionManager,
|
|
|
- UA_Session *session) {
|
|
|
- if(sessionManager == UA_NULL)
|
|
|
- return UA_FALSE;
|
|
|
-
|
|
|
- if(UA_list_search(&sessionManager->sessions,
|
|
|
- (UA_list_PayloadComparer)UA_Session_compare, (void *)session)) {
|
|
|
- UA_Double pendingLifetime;
|
|
|
- UA_Session_getPendingLifetime(session, &pendingLifetime);
|
|
|
+UA_Int32 UA_SessionManager_getSessionById(UA_SessionManager *sessionManager, UA_NodeId *sessionId, UA_Session **session) {
|
|
|
+ if(sessionManager == UA_NULL) {
|
|
|
+ *session = UA_NULL;
|
|
|
+ return UA_ERROR;
|
|
|
+ }
|
|
|
|
|
|
- if(pendingLifetime > 0)
|
|
|
- return UA_TRUE;
|
|
|
+ struct session_list_entry *current = UA_NULL;
|
|
|
+ LIST_FOREACH(current, &sessionManager->sessions, pointers) {
|
|
|
+ if(UA_NodeId_equal(¤t->session.sessionId, sessionId) == UA_EQUAL)
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
- //timeout of session reached so remove it
|
|
|
- UA_NodeId *sessionId = &session->sessionId;
|
|
|
- UA_SessionManager_removeSession(sessionManager, sessionId);
|
|
|
+ if(!current) {
|
|
|
+ *session = UA_NULL;
|
|
|
+ return UA_ERROR;
|
|
|
}
|
|
|
- return UA_FALSE;
|
|
|
+
|
|
|
+ // Lifetime handling is not done here, but in a regular cleanup by the
|
|
|
+ // server. If the session still exists, then it is valid.
|
|
|
+ *session = ¤t->session;
|
|
|
+ return UA_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-UA_Int32 UA_SessionManager_getSessionById(UA_SessionManager *sessionManager,
|
|
|
- UA_NodeId *sessionId, UA_Session **session) {
|
|
|
+UA_Int32 UA_SessionManager_getSessionByToken(UA_SessionManager *sessionManager, UA_NodeId *token, UA_Session **session) {
|
|
|
if(sessionManager == UA_NULL) {
|
|
|
*session = UA_NULL;
|
|
|
return UA_ERROR;
|
|
|
}
|
|
|
|
|
|
- UA_list_Element *current = sessionManager->sessions.first;
|
|
|
- while(current) {
|
|
|
- if(current->payload) {
|
|
|
- UA_list_Element *elem = (UA_list_Element *)current;
|
|
|
- *session = ((UA_Session *)(elem->payload));
|
|
|
- if(UA_NodeId_equal(&(*session)->sessionId, sessionId) == UA_EQUAL) {
|
|
|
- UA_Double pendingLifetime;
|
|
|
- UA_Session_getPendingLifetime(*session, &pendingLifetime);
|
|
|
-
|
|
|
- if(pendingLifetime > 0)
|
|
|
- return UA_SUCCESS;
|
|
|
-
|
|
|
- //session not valid anymore -> remove it
|
|
|
- UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
|
|
|
- *session = UA_NULL;
|
|
|
- return UA_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
- current = current->next;
|
|
|
+ struct session_list_entry *current = UA_NULL;
|
|
|
+ LIST_FOREACH(current, &sessionManager->sessions, pointers) {
|
|
|
+ if(UA_NodeId_equal(¤t->session.authenticationToken, token) == UA_EQUAL)
|
|
|
+ break;
|
|
|
}
|
|
|
- *session = UA_NULL;
|
|
|
- return UA_ERROR;
|
|
|
-}
|
|
|
|
|
|
-UA_Int32 UA_SessionManager_getSessionByToken(UA_SessionManager *sessionManager,
|
|
|
- UA_NodeId *token, UA_Session **session) {
|
|
|
- if(sessionManager == UA_NULL) {
|
|
|
+ if(!current) {
|
|
|
*session = UA_NULL;
|
|
|
return UA_ERROR;
|
|
|
}
|
|
|
|
|
|
- UA_list_Element *current = sessionManager->sessions.first;
|
|
|
- while(current) {
|
|
|
- if(current->payload) {
|
|
|
- UA_list_Element *elem = (UA_list_Element *)current;
|
|
|
- *session = ((UA_Session *)(elem->payload));
|
|
|
-
|
|
|
- if(UA_NodeId_equal(&(*session)->authenticationToken, token) == UA_EQUAL) {
|
|
|
- UA_Double pendingLifetime;
|
|
|
- UA_Session_getPendingLifetime(*session, &pendingLifetime);
|
|
|
-
|
|
|
- if(pendingLifetime > 0)
|
|
|
- return UA_SUCCESS;
|
|
|
-
|
|
|
- //session not valid anymore -> remove it
|
|
|
- UA_list_removeElement(elem, (UA_list_PayloadVisitor)UA_Session_delete);
|
|
|
- *session = UA_NULL;
|
|
|
- return UA_ERROR;
|
|
|
- }
|
|
|
- }
|
|
|
- current = current->next;
|
|
|
- }
|
|
|
- *session = UA_NULL;
|
|
|
- return UA_ERROR;
|
|
|
+ // Lifetime handling is not done here, but in a regular cleanup by the
|
|
|
+ // server. If the session still exists, then it is valid.
|
|
|
+ *session = ¤t->session;
|
|
|
+ return UA_SUCCESS;
|
|
|
}
|
|
|
|
|
|
/** Creates and adds a session. */
|
|
|
-UA_Int32 UA_SessionManager_createSession(UA_SessionManager *sessionManager,
|
|
|
- UA_SecureChannel *channel, UA_Session **session) {
|
|
|
- UA_Int32 retval = UA_SUCCESS;
|
|
|
+UA_Int32 UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel, UA_Session **session) {
|
|
|
if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
|
|
|
return UA_ERROR;
|
|
|
- UA_Session_new(session);
|
|
|
- (*session)->sessionId = (UA_NodeId) {.namespaceIndex = 1, .identifierType = UA_NODEIDTYPE_NUMERIC,
|
|
|
- .identifier.numeric = sessionManager->lastSessionId++ };
|
|
|
- (*session)->authenticationToken = (UA_NodeId) {.namespaceIndex = 1,
|
|
|
- .identifierType = UA_NODEIDTYPE_NUMERIC,
|
|
|
- .identifier.numeric = sessionManager->lastSessionId };
|
|
|
- (*session)->channel = channel;
|
|
|
- (*session)->timeout = 3600 * 1000; // 1h
|
|
|
- UA_Session_setExpirationDate((*session));
|
|
|
+
|
|
|
+ struct session_list_entry *newentry;
|
|
|
+ if(UA_alloc((void **)&newentry, sizeof(struct session_list_entry)) != UA_SUCCESS)
|
|
|
+ return UA_ERROR;
|
|
|
+
|
|
|
+ UA_Session_init(&newentry->session);
|
|
|
+ newentry->session.sessionId = (UA_NodeId) {.namespaceIndex = 1, .identifierType = UA_NODEIDTYPE_NUMERIC,
|
|
|
+ .identifier.numeric = sessionManager->lastSessionId++ };
|
|
|
+ newentry->session.authenticationToken = (UA_NodeId) {.namespaceIndex = 1, .identifierType = UA_NODEIDTYPE_NUMERIC,
|
|
|
+ .identifier.numeric = sessionManager->lastSessionId };
|
|
|
+ newentry->session.channel = channel;
|
|
|
+ newentry->session.timeout = 3600 * 1000; // 1h
|
|
|
+ UA_Session_setExpirationDate(&newentry->session);
|
|
|
+
|
|
|
sessionManager->currentSessionCount++;
|
|
|
- UA_list_addPayloadToFront(&sessionManager->sessions, *session);
|
|
|
- return retval;
|
|
|
+ LIST_INSERT_HEAD(&sessionManager->sessions, newentry, pointers);
|
|
|
+ *session = &newentry->session;
|
|
|
+ return UA_SUCCESS;
|
|
|
}
|
|
|
|
|
|
-UA_Int32 UA_SessionManager_removeSession(UA_SessionManager *sessionManager,
|
|
|
- UA_NodeId *sessionId) {
|
|
|
- UA_Int32 retval = UA_SUCCESS;
|
|
|
- UA_list_Element *element =
|
|
|
- UA_list_search(&sessionManager->sessions, (UA_list_PayloadComparer)UA_Session_compare,
|
|
|
- sessionId);
|
|
|
- if(element) {
|
|
|
- retval |= UA_list_removeElement(element, (UA_list_PayloadVisitor)UA_Session_delete);
|
|
|
- printf("UA_SessionManager_removeSession - session removed, current count: %i \n",
|
|
|
- sessionManager->sessions.size);
|
|
|
+UA_Int32 UA_SessionManager_removeSession(UA_SessionManager *sessionManager, UA_NodeId *sessionId) {
|
|
|
+ struct session_list_entry *current = UA_NULL;
|
|
|
+ LIST_FOREACH(current, &sessionManager->sessions, pointers) {
|
|
|
+ if(UA_NodeId_equal(¤t->session.sessionId, sessionId) == UA_EQUAL)
|
|
|
+ break;
|
|
|
}
|
|
|
- return retval;
|
|
|
+
|
|
|
+ if(!current)
|
|
|
+ return UA_ERROR;
|
|
|
+
|
|
|
+ LIST_REMOVE(current, pointers);
|
|
|
+ return UA_SUCCESS;
|
|
|
}
|