ua_session_manager.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "ua_session_manager.h"
  2. #include "ua_statuscodes.h"
  3. #include "ua_util.h"
  4. /**
  5. The functions in this file are not thread-safe. For multi-threaded access, a
  6. second implementation should be provided. See for example, how a nodestore
  7. implementation is choosen based on whether multithreading is enabled or not.
  8. */
  9. UA_StatusCode UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
  10. UA_UInt32 maxSessionLifeTime, UA_UInt32 startSessionId) {
  11. LIST_INIT(&sessionManager->sessions);
  12. sessionManager->maxSessionCount = maxSessionCount;
  13. sessionManager->lastSessionId = startSessionId;
  14. sessionManager->maxSessionLifeTime = maxSessionLifeTime;
  15. sessionManager->currentSessionCount = 0;
  16. return UA_STATUSCODE_GOOD;
  17. }
  18. void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager) {
  19. session_list_entry *current, *next = LIST_FIRST(&sessionManager->sessions);
  20. while(next) {
  21. current = next;
  22. next = LIST_NEXT(current, pointers);
  23. LIST_REMOVE(current, pointers);
  24. if(current->session.channel)
  25. UA_SecureChannel_detachSession(current->session.channel);
  26. UA_Session_deleteMembers(&current->session);
  27. UA_free(current);
  28. }
  29. }
  30. void UA_SessionManager_cleanupTimedOut(UA_SessionManager *sessionManager, UA_DateTime now) {
  31. session_list_entry *sentry = LIST_FIRST(&sessionManager->sessions);
  32. while(sentry) {
  33. if(sentry->session.validTill < now) {
  34. session_list_entry *next = LIST_NEXT(sentry, pointers);
  35. LIST_REMOVE(sentry, pointers);
  36. if(sentry->session.channel)
  37. UA_SecureChannel_detachSession(sentry->session.channel);
  38. UA_Session_deleteMembers(&sentry->session);
  39. UA_free(sentry);
  40. sentry = next;
  41. } else {
  42. sentry = LIST_NEXT(sentry, pointers);
  43. }
  44. }
  45. }
  46. UA_Session * UA_SessionManager_getSession(UA_SessionManager *sessionManager, const UA_NodeId *token) {
  47. session_list_entry *current = UA_NULL;
  48. LIST_FOREACH(current, &sessionManager->sessions, pointers) {
  49. if(UA_NodeId_equal(&current->session.authenticationToken, token))
  50. break;
  51. }
  52. if(!current || UA_DateTime_now() > current->session.validTill)
  53. return UA_NULL;
  54. return &current->session;
  55. }
  56. /** Creates and adds a session. */
  57. UA_StatusCode
  58. UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
  59. const UA_CreateSessionRequest *request, UA_Session **session)
  60. {
  61. if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
  62. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  63. if(channel->session != UA_NULL)
  64. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  65. session_list_entry *newentry = UA_malloc(sizeof(session_list_entry));
  66. if(!newentry)
  67. return UA_STATUSCODE_BADOUTOFMEMORY;
  68. UA_Session_init(&newentry->session);
  69. newentry->session.sessionId = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId++);
  70. newentry->session.authenticationToken = UA_NODEID_NUMERIC(1, sessionManager->lastSessionId);
  71. newentry->session.channel = channel;
  72. newentry->session.timeout =
  73. (request->requestedSessionTimeout <= sessionManager->maxSessionLifeTime &&
  74. request->requestedSessionTimeout>0) ?
  75. request->requestedSessionTimeout : sessionManager->maxSessionLifeTime;
  76. UA_Session_updateLifetime(&newentry->session);
  77. sessionManager->currentSessionCount++;
  78. LIST_INSERT_HEAD(&sessionManager->sessions, newentry, pointers);
  79. *session = &newentry->session;
  80. return UA_STATUSCODE_GOOD;
  81. }
  82. UA_StatusCode
  83. UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *sessionId)
  84. {
  85. session_list_entry *current;
  86. LIST_FOREACH(current, &sessionManager->sessions, pointers) {
  87. if(UA_NodeId_equal(&current->session.sessionId, sessionId))
  88. break;
  89. }
  90. if(!current)
  91. return UA_STATUSCODE_BADINTERNALERROR;
  92. LIST_REMOVE(current, pointers);
  93. UA_SecureChannel_detachSession(current->session.channel);
  94. UA_Session_deleteMembers(&current->session);
  95. UA_free(current);
  96. return UA_STATUSCODE_GOOD;
  97. }