ua_session_manager.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "ua_session_manager.h"
  5. #include "ua_server_internal.h"
  6. UA_StatusCode
  7. UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server) {
  8. LIST_INIT(&sm->sessions);
  9. sm->currentSessionCount = 0;
  10. sm->server = server;
  11. return UA_STATUSCODE_GOOD;
  12. }
  13. void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
  14. session_list_entry *current, *temp;
  15. LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
  16. LIST_REMOVE(current, pointers);
  17. UA_Session_deleteMembersCleanup(&current->session, sm->server);
  18. UA_free(current);
  19. }
  20. }
  21. /* Delayed callback to free the session memory */
  22. static void
  23. removeSessionCallback(UA_Server *server, void *entry) {
  24. session_list_entry *sentry = (session_list_entry*)entry;
  25. UA_Session_deleteMembersCleanup(&sentry->session, server);
  26. UA_free(sentry);
  27. }
  28. static UA_StatusCode
  29. removeSession(UA_SessionManager *sm, session_list_entry *sentry) {
  30. /* Deactivate the session */
  31. sentry->session.activated = false;
  32. /* Add a delayed callback to remove the session when the currently
  33. * scheduled jobs have completed */
  34. UA_StatusCode retval = UA_Server_delayedCallback(sm->server, removeSessionCallback, sentry);
  35. if(retval != UA_STATUSCODE_GOOD) {
  36. UA_LOG_WARNING_SESSION(sm->server->config.logger, &sentry->session,
  37. "Could not remove session with error code %s",
  38. UA_StatusCode_name(retval));
  39. return retval; /* Try again next time */
  40. }
  41. /* Detach the session and make the capacity available */
  42. LIST_REMOVE(sentry, pointers);
  43. UA_atomic_add(&sm->currentSessionCount, (UA_UInt32)-1);
  44. return UA_STATUSCODE_GOOD;
  45. }
  46. void
  47. UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
  48. UA_DateTime nowMonotonic) {
  49. session_list_entry *sentry, *temp;
  50. LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
  51. /* Session has timed out? */
  52. if(sentry->session.validTill >= nowMonotonic)
  53. continue;
  54. UA_LOG_INFO_SESSION(sm->server->config.logger, &sentry->session,
  55. "Session has timed out");
  56. sm->server->config.accessControl.closeSession(&sentry->session.sessionId,
  57. sentry->session.sessionHandle);
  58. removeSession(sm, sentry);
  59. }
  60. }
  61. UA_Session *
  62. UA_SessionManager_getSession(UA_SessionManager *sm, const UA_NodeId *token) {
  63. session_list_entry *current = NULL;
  64. LIST_FOREACH(current, &sm->sessions, pointers) {
  65. /* Token does not match */
  66. if(!UA_NodeId_equal(&current->session.authenticationToken, token))
  67. continue;
  68. /* Session has timed out */
  69. if(UA_DateTime_nowMonotonic() > current->session.validTill) {
  70. UA_LOG_INFO_SESSION(sm->server->config.logger, &current->session,
  71. "Client tries to use a session that has timed out");
  72. return NULL;
  73. }
  74. /* Ok, return */
  75. return &current->session;
  76. }
  77. /* Session not found */
  78. UA_LOG_INFO(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
  79. "Try to use Session with token " UA_PRINTF_GUID_FORMAT " but is not found",
  80. UA_PRINTF_GUID_DATA(token->identifier.guid));
  81. return NULL;
  82. }
  83. /* Creates and adds a session. But it is not yet attached to a secure channel. */
  84. UA_StatusCode
  85. UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
  86. const UA_CreateSessionRequest *request, UA_Session **session) {
  87. if(sm->currentSessionCount >= sm->server->config.maxSessions)
  88. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  89. session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
  90. if(!newentry)
  91. return UA_STATUSCODE_BADOUTOFMEMORY;
  92. UA_atomic_add(&sm->currentSessionCount, 1);
  93. UA_Session_init(&newentry->session);
  94. newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
  95. newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
  96. if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
  97. request->requestedSessionTimeout > 0)
  98. newentry->session.timeout = request->requestedSessionTimeout;
  99. else
  100. newentry->session.timeout = sm->server->config.maxSessionTimeout;
  101. UA_Session_updateLifetime(&newentry->session);
  102. LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
  103. *session = &newentry->session;
  104. return UA_STATUSCODE_GOOD;
  105. }
  106. UA_StatusCode
  107. UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
  108. session_list_entry *current;
  109. LIST_FOREACH(current, &sm->sessions, pointers) {
  110. if(UA_NodeId_equal(&current->session.authenticationToken, token))
  111. break;
  112. }
  113. if(!current)
  114. return UA_STATUSCODE_BADSESSIONIDINVALID;
  115. return removeSession(sm, current);
  116. }