Skip to content

Commit eef3fc5

Browse files
committed
Session (session_list_entry) livetime increased for async method execution
1 parent fe96054 commit eef3fc5

File tree

5 files changed

+103
-15
lines changed

5 files changed

+103
-15
lines changed

include/open62541/server.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,6 +1217,9 @@ UA_Server_getMethodNodeCallback(UA_Server *server,
12171217

12181218
UA_CallMethodResult UA_EXPORT UA_THREADSAFE
12191219
UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request);
1220+
1221+
UA_CallMethodResult UA_EXPORT UA_THREADSAFE
1222+
UA_Server_callEx(UA_Server *server, const UA_CallMethodRequest *request, void* context);
12201223
#endif
12211224

12221225
/**

src/server/ua_server_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ getServerComponentByName(UA_Server *server, UA_String name);
112112
/********************/
113113

114114
typedef struct session_list_entry {
115+
unsigned int nReferences;
115116
UA_DelayedCallback cleanupCallback;
116117
LIST_ENTRY(session_list_entry) pointers;
117118
UA_Session session;
@@ -265,6 +266,9 @@ getSessionByToken(UA_Server *server, const UA_NodeId *token);
265266
UA_Session *
266267
getSessionById(UA_Server *server, const UA_NodeId *sessionId);
267268

269+
session_list_entry *acquireSessionEntryById(UA_Server *server, const UA_NodeId *sessionId, UA_Session **pSession);
270+
void releaseSessionEntry(UA_Server *server, session_list_entry *sentry);
271+
268272
/*****************/
269273
/* Node Handling */
270274
/*****************/

src/server/ua_services_method.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,12 +521,37 @@ void Service_Call(UA_Server *server, UA_Session *session,
521521
&response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT]);
522522
}
523523

524+
UA_CallMethodResult UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
525+
return UA_Server_callEx(server, request, NULL);
526+
}
527+
524528
UA_CallMethodResult
525-
UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) {
529+
UA_Server_callEx(UA_Server *server, const UA_CallMethodRequest *request, void* context) {
526530
UA_CallMethodResult result;
527531
UA_CallMethodResult_init(&result);
528532
UA_LOCK(&server->serviceMutex);
529-
Operation_CallMethod(server, &server->adminSession, NULL, request, &result);
533+
534+
void *sessionToken = NULL;
535+
UA_Session *session = &server->adminSession;
536+
537+
if (NULL != context) {
538+
UA_AsyncOperation *ao = (UA_AsyncOperation*)context;
539+
sessionToken = acquireSessionEntryById(server, &ao->parent->sessionId, &session);
540+
if (NULL == sessionToken)
541+
session = NULL;
542+
}
543+
544+
if (NULL != session)
545+
Operation_CallMethod(server, session, NULL, request, &result);
546+
else
547+
result.statusCode = UA_STATUSCODE_BADSESSIONIDINVALID;
548+
549+
if (NULL != sessionToken) {
550+
UA_assert(NULL != context);
551+
UA_assert(NULL != session);
552+
releaseSessionEntry(server, sessionToken);
553+
}
554+
530555
UA_UNLOCK(&server->serviceMutex);
531556
return result;
532557
}

src/server/ua_services_session.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,31 @@ removeSessionCallback(UA_Server *server, session_list_entry *entry) {
2525
UA_free(entry);
2626
}
2727

28+
static void removeReference(UA_Server *server, session_list_entry *sentry) {
29+
UA_assert(NULL != server);
30+
UA_assert(NULL != sentry);
31+
UA_LOCK_ASSERT(&server->serviceMutex, 1);
32+
33+
if (0 == --sentry->nReferences) {
34+
/* Add a delayed callback to remove the session when the currently
35+
* scheduled jobs have completed */
36+
sentry->cleanupCallback.callback = (UA_Callback)removeSessionCallback;
37+
sentry->cleanupCallback.application = server;
38+
sentry->cleanupCallback.context = sentry;
39+
UA_EventLoop *el = server->config.eventLoop;
40+
el->addDelayedCallback(el, &sentry->cleanupCallback);
41+
}
42+
}
43+
44+
static void addReference(UA_Server *server, session_list_entry *sentry) {
45+
UA_assert(NULL != server);
46+
UA_assert(NULL != sentry);
47+
UA_LOCK_ASSERT(&server->serviceMutex, 1);
48+
49+
UA_assert(0 < sentry->nReferences);
50+
++sentry->nReferences;
51+
}
52+
2853
void
2954
UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
3055
UA_ShutdownReason shutdownReason) {
@@ -46,12 +71,6 @@ UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
4671
}
4772
#endif
4873

49-
/* Callback into userland access control */
50-
if(server->config.accessControl.closeSession) {
51-
server->config.accessControl.
52-
closeSession(server, &server->config.accessControl,
53-
&session->sessionId, session->sessionHandle);
54-
}
5574

5675
/* Detach the Session from the SecureChannel */
5776
UA_Session_detachFromSecureChannel(session);
@@ -88,13 +107,7 @@ UA_Server_removeSession(UA_Server *server, session_list_entry *sentry,
88107
break;
89108
}
90109

91-
/* Add a delayed callback to remove the session when the currently
92-
* scheduled jobs have completed */
93-
sentry->cleanupCallback.callback = (UA_Callback)removeSessionCallback;
94-
sentry->cleanupCallback.application = server;
95-
sentry->cleanupCallback.context = sentry;
96-
UA_EventLoop *el = server->config.eventLoop;
97-
el->addDelayedCallback(el, &sentry->cleanupCallback);
110+
removeReference(server, sentry);
98111
}
99112

100113
UA_StatusCode
@@ -152,6 +165,40 @@ getSessionByToken(UA_Server *server, const UA_NodeId *token) {
152165
return NULL;
153166
}
154167

168+
session_list_entry *acquireSessionEntryById(UA_Server *server, const UA_NodeId *sessionId, UA_Session **pSession) {
169+
UA_assert(NULL != server);
170+
UA_assert(NULL != sessionId);
171+
UA_assert(NULL != pSession);
172+
UA_LOCK_ASSERT(&server->serviceMutex, 1);
173+
174+
session_list_entry *current = NULL;
175+
LIST_FOREACH(current, &server->sessions, pointers) {
176+
/* Token does not match */
177+
if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
178+
continue;
179+
180+
/* Session has timed out */
181+
if(UA_DateTime_nowMonotonic() > current->session.validTill) {
182+
UA_LOG_INFO_SESSION(server->config.logging, &current->session,
183+
"Client tries to use a session that has timed out");
184+
return NULL;
185+
}
186+
187+
addReference(server, current);
188+
*pSession = &current->session;
189+
return current;
190+
}
191+
192+
return NULL;
193+
}
194+
195+
void releaseSessionEntry(UA_Server *server, session_list_entry *sentry) {
196+
UA_LOCK_ASSERT(&server->serviceMutex, 1);
197+
UA_assert(NULL != server);
198+
UA_assert(NULL != sentry);
199+
removeReference(server, sentry);
200+
}
201+
155202
UA_Session *
156203
getSessionById(UA_Server *server, const UA_NodeId *sessionId) {
157204
UA_LOCK_ASSERT(&server->serviceMutex, 1);
@@ -238,6 +285,7 @@ UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
238285

239286
/* Initialize the Session */
240287
UA_Session_init(&newentry->session);
288+
newentry->nReferences = 1;
241289
newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
242290
newentry->session.header.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
243291

@@ -249,6 +297,7 @@ UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel,
249297
/* Attach the session to the channel. But don't activate for now. */
250298
if(channel)
251299
UA_Session_attachToSecureChannel(&newentry->session, channel);
300+
252301
UA_Session_updateLifetime(&newentry->session);
253302

254303
/* Add to the server */

src/server/ua_session.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ void UA_Session_clear(UA_Session *session, UA_Server* server) {
3737
}
3838
#endif
3939

40+
/* Callback into userland access control */
41+
if(server->config.accessControl.closeSession) {
42+
server->config.accessControl.
43+
closeSession(server, &server->config.accessControl,
44+
&session->sessionId, session->sessionHandle);
45+
}
46+
4047
#ifdef UA_ENABLE_DIAGNOSTICS
4148
deleteNode(server, session->sessionId, true);
4249
#endif

0 commit comments

Comments
 (0)