ua_session_manager.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. struct session_list_entry {
  10. UA_Session session;
  11. LIST_ENTRY(session_list_entry) pointers;
  12. };
  13. UA_StatusCode UA_SessionManager_init(UA_SessionManager *sessionManager, UA_UInt32 maxSessionCount,
  14. UA_UInt32 sessionTimeout, UA_UInt32 startSessionId) {
  15. LIST_INIT(&sessionManager->sessions);
  16. sessionManager->maxSessionCount = maxSessionCount;
  17. sessionManager->lastSessionId = startSessionId;
  18. sessionManager->sessionTimeout = sessionTimeout;
  19. sessionManager->currentSessionCount = 0;
  20. return UA_STATUSCODE_GOOD;
  21. }
  22. void UA_SessionManager_deleteMembers(UA_SessionManager *sessionManager) {
  23. struct session_list_entry *current;
  24. struct session_list_entry *next = LIST_FIRST(&sessionManager->sessions);
  25. while(next) {
  26. current = next;
  27. next = LIST_NEXT(current, pointers);
  28. LIST_REMOVE(current, pointers);
  29. if(current->session.channel)
  30. current->session.channel->session = UA_NULL; // the channel is no longer attached to a session
  31. UA_Session_deleteMembers(&current->session);
  32. UA_free(current);
  33. }
  34. }
  35. UA_StatusCode UA_SessionManager_getSessionById(UA_SessionManager *sessionManager, const UA_NodeId *sessionId,
  36. UA_Session **session) {
  37. if(sessionManager == UA_NULL) {
  38. *session = UA_NULL;
  39. return UA_STATUSCODE_BADINTERNALERROR;
  40. }
  41. struct session_list_entry *current = UA_NULL;
  42. LIST_FOREACH(current, &sessionManager->sessions, pointers) {
  43. if(UA_NodeId_equal(&current->session.sessionId, sessionId))
  44. break;
  45. }
  46. if(!current) {
  47. *session = UA_NULL;
  48. return UA_STATUSCODE_BADINTERNALERROR;
  49. }
  50. // Lifetime handling is not done here, but in a regular cleanup by the
  51. // server. If the session still exists, then it is valid.
  52. *session = &current->session;
  53. return UA_STATUSCODE_GOOD;
  54. }
  55. UA_StatusCode UA_SessionManager_getSessionByToken(UA_SessionManager *sessionManager, const UA_NodeId *token,
  56. UA_Session **session) {
  57. if(sessionManager == UA_NULL) {
  58. *session = UA_NULL;
  59. return UA_STATUSCODE_BADINTERNALERROR;
  60. }
  61. struct session_list_entry *current = UA_NULL;
  62. LIST_FOREACH(current, &sessionManager->sessions, pointers) {
  63. if(UA_NodeId_equal(&current->session.authenticationToken, token))
  64. break;
  65. }
  66. if(!current) {
  67. *session = UA_NULL;
  68. return UA_STATUSCODE_BADINTERNALERROR;
  69. }
  70. // Lifetime handling is not done here, but in a regular cleanup by the
  71. // server. If the session still exists, then it is valid.
  72. *session = &current->session;
  73. return UA_STATUSCODE_GOOD;
  74. }
  75. /** Creates and adds a session. */
  76. UA_StatusCode UA_SessionManager_createSession(UA_SessionManager *sessionManager, UA_SecureChannel *channel,
  77. UA_Session **session) {
  78. if(sessionManager->currentSessionCount >= sessionManager->maxSessionCount)
  79. return UA_STATUSCODE_BADTOOMANYSESSIONS;
  80. struct session_list_entry *newentry = UA_malloc(sizeof(struct session_list_entry));
  81. if(!newentry)
  82. return UA_STATUSCODE_BADOUTOFMEMORY;
  83. UA_Session_init(&newentry->session);
  84. newentry->session.sessionId = (UA_NodeId) {.namespaceIndex = 1, .identifierType = UA_NODEIDTYPE_NUMERIC,
  85. .identifier.numeric = sessionManager->lastSessionId++ };
  86. newentry->session.authenticationToken = (UA_NodeId) {.namespaceIndex = 1,
  87. .identifierType = UA_NODEIDTYPE_NUMERIC,
  88. .identifier.numeric = sessionManager->lastSessionId };
  89. newentry->session.channel = channel;
  90. newentry->session.timeout = 3600 * 1000; // 1h
  91. UA_Session_setExpirationDate(&newentry->session);
  92. sessionManager->currentSessionCount++;
  93. LIST_INSERT_HEAD(&sessionManager->sessions, newentry, pointers);
  94. *session = &newentry->session;
  95. return UA_STATUSCODE_GOOD;
  96. }
  97. UA_StatusCode UA_SessionManager_removeSession(UA_SessionManager *sessionManager, const UA_NodeId *sessionId) {
  98. struct session_list_entry *current = UA_NULL;
  99. LIST_FOREACH(current, &sessionManager->sessions, pointers) {
  100. if(UA_NodeId_equal(&current->session.sessionId, sessionId))
  101. break;
  102. }
  103. if(!current)
  104. return UA_STATUSCODE_BADINTERNALERROR;
  105. LIST_REMOVE(current, pointers);
  106. if(current->session.channel)
  107. current->session.channel->session = UA_NULL; // the channel is no longer attached to a session
  108. UA_Session_deleteMembers(&current->session);
  109. UA_free(current);
  110. return UA_STATUSCODE_GOOD;
  111. }