ua_session_manager.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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. *
  5. * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
  6. * Copyright 2014, 2017 (c) Florian Palm
  7. * Copyright 2015 (c) Sten Grüner
  8. * Copyright 2015 (c) Oleksiy Vasylyev
  9. * Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  10. */
  11. #include "ua_session_manager.h"
  12. #include "ua_server_internal.h"
  13. UA_StatusCode
  14. UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server) {
  15. LIST_INIT(&sm->sessions);
  16. sm->currentSessionCount = 0;
  17. sm->server = server;
  18. return UA_STATUSCODE_GOOD;
  19. }
  20. void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
  21. session_list_entry *current, *temp;
  22. LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
  23. LIST_REMOVE(current, pointers);
  24. UA_Session_deleteMembersCleanup(&current->session, sm->server);
  25. UA_free(current);
  26. }
  27. }
  28. /* Delayed callback to free the session memory */
  29. static void
  30. removeSessionCallback(UA_Server *server, void *entry) {
  31. session_list_entry *sentry = (session_list_entry*)entry;
  32. UA_Session_deleteMembersCleanup(&sentry->session, server);
  33. UA_free(sentry);
  34. }
  35. static UA_StatusCode
  36. removeSession(UA_SessionManager *sm, session_list_entry *sentry) {
  37. /* Detach the Session from the SecureChannel */
  38. UA_Session_detachFromSecureChannel(&sentry->session);
  39. /* Deactivate the session */
  40. sentry->session.activated = false;
  41. /* Add a delayed callback to remove the session when the currently
  42. * scheduled jobs have completed */
  43. UA_StatusCode retval = UA_Server_delayedCallback(sm->server, removeSessionCallback, sentry);
  44. if(retval != UA_STATUSCODE_GOOD) {
  45. UA_LOG_WARNING_SESSION(sm->server->config.logger, &sentry->session,
  46. "Could not remove session with error code %s",
  47. UA_StatusCode_name(retval));
  48. return retval; /* Try again next time */
  49. }
  50. /* Detach the session from the session manager and make the capacity
  51. * available */
  52. LIST_REMOVE(sentry, pointers);
  53. UA_atomic_subUInt32(&sm->currentSessionCount, 1);
  54. return UA_STATUSCODE_GOOD;
  55. }
  56. void
  57. UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
  58. UA_DateTime nowMonotonic) {
  59. session_list_entry *sentry, *temp;
  60. LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
  61. /* Session has timed out? */
  62. if(sentry->session.validTill >= nowMonotonic)
  63. continue;
  64. UA_LOG_INFO_SESSION(sm->server->config.logger, &sentry->session,
  65. "Session has timed out");
  66. sm->server->config.accessControl.closeSession(sm->server,
  67. &sm->server->config.accessControl,
  68. &sentry->session.sessionId,
  69. sentry->session.sessionHandle);
  70. removeSession(sm, sentry);
  71. }
  72. }
  73. UA_Session *
  74. UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *token) {
  75. session_list_entry *current = NULL;
  76. LIST_FOREACH(current, &sm->sessions, pointers) {
  77. /* Token does not match */
  78. if(!UA_NodeId_equal(&current->session.header.authenticationToken, token))
  79. continue;
  80. /* Session has timed out */
  81. if(UA_DateTime_nowMonotonic() > current->session.validTill) {
  82. UA_LOG_INFO_SESSION(sm->server->config.logger, &current->session,
  83. "Client tries to use a session that has timed out");
  84. return NULL;
  85. }
  86. /* Ok, return */
  87. return &current->session;
  88. }
  89. /* Session not found */
  90. UA_String nodeIdStr = UA_STRING_NULL;
  91. UA_NodeId_toString(token, &nodeIdStr);
  92. UA_LOG_INFO(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
  93. "Try to use Session with token %.*s but is not found",
  94. (int)nodeIdStr.length, nodeIdStr.data);
  95. UA_String_deleteMembers(&nodeIdStr);
  96. return NULL;
  97. }
  98. UA_Session *
  99. UA_SessionManager_getSessionById(UA_SessionManager *sm, const UA_NodeId *sessionId) {
  100. session_list_entry *current = NULL;
  101. LIST_FOREACH(current, &sm->sessions, pointers) {
  102. /* Token does not match */
  103. if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
  104. continue;
  105. /* Session has timed out */
  106. if(UA_DateTime_nowMonotonic() > current->session.validTill) {
  107. UA_LOG_INFO_SESSION(sm->server->config.logger, &current->session,
  108. "Client tries to use a session that has timed out");
  109. return NULL;
  110. }
  111. /* Ok, return */
  112. return &current->session;
  113. }
  114. /* Session not found */
  115. UA_String sessionIdStr = UA_STRING_NULL;
  116. UA_NodeId_toString(sessionId, &sessionIdStr);
  117. UA_LOG_INFO(sm->server->config.logger, UA_LOGCATEGORY_SESSION,
  118. "Try to use Session with identifier %.*s but is not found",
  119. (int)sessionIdStr.length, sessionIdStr.data);
  120. UA_String_deleteMembers(&sessionIdStr);
  121. return NULL;
  122. }
  123. /* Creates and adds a session. But it is not yet attached to a secure channel. */
  124. UA_StatusCode
  125. UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
  126. const UA_CreateSessionRequest *request, UA_Session **session) {
  127. if(sm->currentSessionCount >= sm->server->config.maxSessions)
  128. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  129. session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
  130. if(!newentry)
  131. return UA_STATUSCODE_BADOUTOFMEMORY;
  132. UA_atomic_addUInt32(&sm->currentSessionCount, 1);
  133. UA_Session_init(&newentry->session);
  134. newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
  135. newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
  136. if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
  137. request->requestedSessionTimeout > 0)
  138. newentry->session.timeout = request->requestedSessionTimeout;
  139. else
  140. newentry->session.timeout = sm->server->config.maxSessionTimeout;
  141. UA_Session_updateLifetime(&newentry->session);
  142. LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
  143. *session = &newentry->session;
  144. return UA_STATUSCODE_GOOD;
  145. }
  146. UA_StatusCode
  147. UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
  148. session_list_entry *current;
  149. LIST_FOREACH(current, &sm->sessions, pointers) {
  150. if(UA_NodeId_equal(&current->session.header.authenticationToken, token))
  151. break;
  152. }
  153. if(!current)
  154. return UA_STATUSCODE_BADSESSIONIDINVALID;
  155. return removeSession(sm, current);
  156. }