ua_session_manager.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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-2019 (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. #include "ua_subscription.h"
  14. UA_StatusCode
  15. UA_SessionManager_init(UA_SessionManager *sm, UA_Server *server) {
  16. LIST_INIT(&sm->sessions);
  17. sm->currentSessionCount = 0;
  18. sm->server = server;
  19. return UA_STATUSCODE_GOOD;
  20. }
  21. /* Delayed callback to free the session memory */
  22. static void
  23. removeSessionCallback(UA_Server *server, session_list_entry *entry) {
  24. UA_Session_deleteMembersCleanup(&entry->session, server);
  25. }
  26. static void
  27. removeSession(UA_SessionManager *sm, session_list_entry *sentry) {
  28. UA_Server *server = sm->server;
  29. UA_Session *session = &sentry->session;
  30. /* Remove the Subscriptions */
  31. #ifdef UA_ENABLE_SUBSCRIPTIONS
  32. UA_Subscription *sub, *tempsub;
  33. LIST_FOREACH_SAFE(sub, &session->serverSubscriptions, listEntry, tempsub) {
  34. UA_Session_deleteSubscription(server, session, sub->subscriptionId);
  35. }
  36. UA_PublishResponseEntry *entry;
  37. while((entry = UA_Session_dequeuePublishReq(session))) {
  38. UA_PublishResponse_deleteMembers(&entry->response);
  39. UA_free(entry);
  40. }
  41. #endif
  42. /* Callback into userland access control */
  43. if(server->config.accessControl.closeSession)
  44. server->config.accessControl.closeSession(server, &server->config.accessControl,
  45. &session->sessionId, session->sessionHandle);
  46. /* Detach the Session from the SecureChannel */
  47. UA_Session_detachFromSecureChannel(session);
  48. /* Deactivate the session */
  49. sentry->session.activated = false;
  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. /* Add a delayed callback to remove the session when the currently
  55. * scheduled jobs have completed */
  56. sentry->cleanupCallback.callback = (UA_ApplicationCallback)removeSessionCallback;
  57. sentry->cleanupCallback.application = sm->server;
  58. sentry->cleanupCallback.data = sentry;
  59. UA_WorkQueue_enqueueDelayed(&server->workQueue, &sentry->cleanupCallback);
  60. }
  61. void UA_SessionManager_deleteMembers(UA_SessionManager *sm) {
  62. session_list_entry *current, *temp;
  63. LIST_FOREACH_SAFE(current, &sm->sessions, pointers, temp) {
  64. removeSession(sm, current);
  65. }
  66. }
  67. void
  68. UA_SessionManager_cleanupTimedOut(UA_SessionManager *sm,
  69. UA_DateTime nowMonotonic) {
  70. session_list_entry *sentry, *temp;
  71. LIST_FOREACH_SAFE(sentry, &sm->sessions, pointers, temp) {
  72. /* Session has timed out? */
  73. if(sentry->session.validTill >= nowMonotonic)
  74. continue;
  75. UA_LOG_INFO_SESSION(&sm->server->config.logger, &sentry->session,
  76. "Session has timed out");
  77. removeSession(sm, sentry);
  78. }
  79. }
  80. UA_Session *
  81. UA_SessionManager_getSessionByToken(UA_SessionManager *sm, const UA_NodeId *token) {
  82. session_list_entry *current = NULL;
  83. LIST_FOREACH(current, &sm->sessions, pointers) {
  84. /* Token does not match */
  85. if(!UA_NodeId_equal(&current->session.header.authenticationToken, token))
  86. continue;
  87. /* Session has timed out */
  88. if(UA_DateTime_nowMonotonic() > current->session.validTill) {
  89. UA_LOG_INFO_SESSION(&sm->server->config.logger, &current->session,
  90. "Client tries to use a session that has timed out");
  91. return NULL;
  92. }
  93. /* Ok, return */
  94. return &current->session;
  95. }
  96. /* Session not found */
  97. #if UA_LOGLEVEL <= 300
  98. UA_String nodeIdStr = UA_STRING_NULL;
  99. UA_NodeId_toString(token, &nodeIdStr);
  100. UA_LOG_INFO(&sm->server->config.logger, UA_LOGCATEGORY_SESSION,
  101. "Try to use Session with token %.*s but is not found",
  102. (int)nodeIdStr.length, nodeIdStr.data);
  103. UA_String_deleteMembers(&nodeIdStr);
  104. #endif
  105. return NULL;
  106. }
  107. UA_Session *
  108. UA_SessionManager_getSessionById(UA_SessionManager *sm, const UA_NodeId *sessionId) {
  109. session_list_entry *current = NULL;
  110. LIST_FOREACH(current, &sm->sessions, pointers) {
  111. /* Token does not match */
  112. if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
  113. continue;
  114. /* Session has timed out */
  115. if(UA_DateTime_nowMonotonic() > current->session.validTill) {
  116. UA_LOG_INFO_SESSION(&sm->server->config.logger, &current->session,
  117. "Client tries to use a session that has timed out");
  118. return NULL;
  119. }
  120. /* Ok, return */
  121. return &current->session;
  122. }
  123. /* Session not found */
  124. UA_String sessionIdStr = UA_STRING_NULL;
  125. UA_NodeId_toString(sessionId, &sessionIdStr);
  126. UA_LOG_INFO(&sm->server->config.logger, UA_LOGCATEGORY_SESSION,
  127. "Try to use Session with identifier %.*s but is not found",
  128. (int)sessionIdStr.length, sessionIdStr.data);
  129. UA_String_deleteMembers(&sessionIdStr);
  130. return NULL;
  131. }
  132. /* Creates and adds a session. But it is not yet attached to a secure channel. */
  133. UA_StatusCode
  134. UA_SessionManager_createSession(UA_SessionManager *sm, UA_SecureChannel *channel,
  135. const UA_CreateSessionRequest *request, UA_Session **session) {
  136. if(sm->currentSessionCount >= sm->server->config.maxSessions)
  137. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  138. session_list_entry *newentry = (session_list_entry *)UA_malloc(sizeof(session_list_entry));
  139. if(!newentry)
  140. return UA_STATUSCODE_BADOUTOFMEMORY;
  141. UA_atomic_addUInt32(&sm->currentSessionCount, 1);
  142. UA_Session_init(&newentry->session);
  143. newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
  144. newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
  145. if(request->requestedSessionTimeout <= sm->server->config.maxSessionTimeout &&
  146. request->requestedSessionTimeout > 0)
  147. newentry->session.timeout = request->requestedSessionTimeout;
  148. else
  149. newentry->session.timeout = sm->server->config.maxSessionTimeout;
  150. UA_Session_updateLifetime(&newentry->session);
  151. LIST_INSERT_HEAD(&sm->sessions, newentry, pointers);
  152. *session = &newentry->session;
  153. return UA_STATUSCODE_GOOD;
  154. }
  155. UA_StatusCode
  156. UA_SessionManager_removeSession(UA_SessionManager *sm, const UA_NodeId *token) {
  157. session_list_entry *current;
  158. LIST_FOREACH(current, &sm->sessions, pointers) {
  159. if(UA_NodeId_equal(&current->session.header.authenticationToken, token))
  160. break;
  161. }
  162. if(!current)
  163. return UA_STATUSCODE_BADSESSIONIDINVALID;
  164. removeSession(sm, current);
  165. return UA_STATUSCODE_GOOD;
  166. }