Coverage Report

Created: 2026-04-12 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/ClientServer/services/sopc_services_api.c
Line
Count
Source
1
/*
2
 * Licensed to Systerel under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work
4
 * for additional information regarding copyright ownership.
5
 * Systerel licenses this file to you under the Apache
6
 * License, Version 2.0 (the "License"); you may not use this
7
 * file except in compliance with the License. You may obtain
8
 * a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
#include <inttypes.h>
21
#include <stdbool.h>
22
#include <stdio.h>
23
24
#include "sopc_array.h"
25
#include "sopc_assert.h"
26
#include "sopc_date_time.h"
27
#include "sopc_enums.h"
28
#include "sopc_helper_string.h"
29
#include "sopc_internal_app_dispatcher.h"
30
#include "sopc_logger.h"
31
#include "sopc_macros.h"
32
#include "sopc_mem_alloc.h"
33
#include "sopc_mutexes.h"
34
#include "sopc_secure_channels_api.h"
35
#include "sopc_services_api.h"
36
#include "sopc_services_api_internal.h"
37
#include "sopc_toolkit_config.h"
38
#include "sopc_toolkit_config_internal.h"
39
#include "sopc_user_app_itf.h"
40
41
#include "io_dispatch_mgr.h"
42
#include "monitored_item_pointer_bs.h"
43
#include "service_mgr_bs.h"
44
#include "toolkit_header_init.h"
45
#include "util_b2c.h"
46
47
/**
48
 * \brief Indicates whether the server configuration is locked (configured) or not.
49
 *        When unlocked, ignore the server related events until it is locked again.
50
 */
51
static bool isServerConfigurationLocked = false;
52
53
static SOPC_Looper* servicesLooper = NULL;
54
static SOPC_EventHandler* secureChannelsEventHandler = NULL;
55
static SOPC_EventHandler* servicesEventHandler = NULL;
56
57
// Structure used to close all connections in a synchronous way
58
// (necessary on toolkit clear)
59
static struct
60
{
61
    SOPC_Mutex mutex;
62
    SOPC_Condition cond;
63
    bool allDisconnectedFlag;
64
    bool requestedFlag;
65
    bool clientOnlyFlag;
66
} closeAllConnectionsSync = {.allDisconnectedFlag = false, .requestedFlag = false, .clientOnlyFlag = false};
67
68
SOPC_EventHandler* SOPC_Services_GetEventHandler(void)
69
0
{
70
0
    return servicesEventHandler;
71
0
}
72
73
static void SOPC_Internal_AllClientSecureChannelsDisconnected(bool clientOnly)
74
0
{
75
0
    SOPC_Mutex_Lock(&closeAllConnectionsSync.mutex);
76
0
    SOPC_ASSERT(closeAllConnectionsSync.clientOnlyFlag == clientOnly);
77
0
    if (closeAllConnectionsSync.requestedFlag)
78
0
    {
79
0
        closeAllConnectionsSync.allDisconnectedFlag = true;
80
0
        SOPC_Condition_SignalAll(&closeAllConnectionsSync.cond);
81
0
    }
82
0
    SOPC_Mutex_Unlock(&closeAllConnectionsSync.mutex);
83
0
}
84
85
static void onSecureChannelEvent(SOPC_EventHandler* handler,
86
                                 int32_t event,
87
                                 uint32_t id,
88
                                 uintptr_t params,
89
                                 uintptr_t auxParam)
90
0
{
91
0
    SOPC_UNUSED_ARG(handler);
92
0
    SOPC_SecureChannels_OutputEvent scEvent = (SOPC_SecureChannels_OutputEvent) event;
93
0
    bool bres = false;
94
0
    uint32_t channel_config_idx = 0;
95
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
96
97
0
    switch (scEvent)
98
0
    {
99
0
    case EP_CONNECTED:
100
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
101
0
                               "ServicesMgr: SC_EP_SC_CONNECTED epCfgIdx=%" PRIu32 " scCfgIdx=%" PRIuPTR
102
0
                               " scIdx=%" PRIuPTR,
103
0
                               id, params, auxParam);
104
105
        // id ==  endpoint configuration index
106
        // params = channel configuration index
107
        // auxParam == connection Id
108
0
        SOPC_ASSERT(id <= INT32_MAX);
109
0
        channel_config_idx = (uint32_t) params;
110
0
        SOPC_ASSERT(channel_config_idx <= constants__t_channel_config_idx_i_max);
111
0
        SOPC_ASSERT(auxParam <= constants__t_channel_i_max);
112
113
0
        io_dispatch_mgr__server_channel_connected_event(id, channel_config_idx, (uint32_t) auxParam, &bres);
114
0
        if (bres == false)
115
0
        {
116
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
117
0
                                   "Services: channel state incoherent or maximum reached epCfgIdx=%" PRIu32
118
0
                                   " scIdx=%" PRIuPTR,
119
0
                                   id, auxParam);
120
121
0
            SOPC_SecureChannels_EnqueueEvent(SC_DISCONNECT, (uint32_t) auxParam,
122
0
                                             (uintptr_t) OpcUa_BadSecureChannelClosed, 0);
123
0
        }
124
125
0
        break;
126
0
    case EP_CLOSED:
127
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
128
0
                               "ServicesMgr: SC_EP_CLOSED epCfgIdx=%" PRIu32 " returnStatus=%" PRIuPTR, id, auxParam);
129
        // id == endpoint configuration index
130
        // params = NULL
131
        // auxParam == status
132
        // => B model entry point to add
133
0
        status = SOPC_App_EnqueueComEvent(SE_CLOSED_ENDPOINT, id, (uintptr_t) NULL, auxParam);
134
0
        SOPC_ASSERT(status == SOPC_STATUS_OK);
135
0
        break;
136
0
    case EP_REVERSE_CLOSED:
137
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
138
0
                               "ServicesMgr: EP_REVERSE_CLOSED reverseEpCfgIdx=%" PRIu32 " returnStatus=%" PRIuPTR, id,
139
0
                               auxParam);
140
        //  id = reverse endpoint config index,
141
        // auxParams = SOPC_ReturnStatus
142
0
        status = SOPC_App_EnqueueComEvent(SE_REVERSE_ENDPOINT_CLOSED, id, (uintptr_t) NULL, auxParam);
143
0
        SOPC_ASSERT(status == SOPC_STATUS_OK);
144
0
        break;
145
0
    case SC_CONNECTED:
146
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
147
0
                               "ServicesMgr: SC_SC_CONNECTED scIdx=%" PRIu32 " scCfgIdx=%" PRIuPTR, id, auxParam);
148
        // id == connection Id
149
        // auxParam == secure channel configuration index
150
        // => B model entry point to add
151
0
        SOPC_ASSERT(id <= constants__t_channel_i_max);
152
0
        SOPC_ASSERT(auxParam <= constants__t_channel_config_idx_i_max);
153
0
        io_dispatch_mgr__client_channel_connected_event((uint32_t) auxParam,
154
0
                                                        constants__c_reverse_endpoint_config_idx_indet, id);
155
0
        break;
156
0
    case SC_REVERSE_CONNECTED:
157
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
158
0
                               "ServicesMgr: SC_REVERSE_CONNECTED scIdx=%" PRIu32 " scCfgIdx=%" PRIuPTR, id, auxParam);
159
        // id = secure channel connection index,
160
        // params = (uint32_t) secure channel configuration index,
161
        // auxParams = (uint32) reverse endpoint configuration index
162
        // => B model entry point to add
163
0
        SOPC_ASSERT(id <= constants__t_channel_i_max);
164
0
        SOPC_ASSERT(auxParam <= constants__t_channel_config_idx_i_max);
165
0
        io_dispatch_mgr__client_channel_connected_event((uint32_t) params, (uint32_t) auxParam, id);
166
0
        break;
167
0
    case SC_CONNECTION_TIMEOUT:
168
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: SC_SC_CONNECTION_TIMEOUT scCfgIdx=%" PRIu32,
169
0
                               id);
170
171
        // id == secure channel configuration index
172
        // => B model entry point to add
173
0
        SOPC_ASSERT(id <= constants_bs__t_channel_config_idx_i_max);
174
0
        io_dispatch_mgr__client_secure_channel_timeout(id);
175
0
        break;
176
0
    case SC_DISCONNECTED:
177
0
        channel_config_idx = (uint32_t) params;
178
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
179
0
                               "ServicesMgr: SC_SC_DISCONNECTED scIdx=%" PRIu32 " scCfgIdx=%" PRIu32
180
0
                               " with status=x%08" PRIX32,
181
0
                               id, channel_config_idx, (uint32_t) auxParam);
182
        // id == connection Id
183
        // params == secure channel configuration index (server only)
184
        // auxParam = status
185
0
        io_dispatch_mgr__secure_channel_lost(id);
186
        // Acknowledge the disconnected state is set in service layer to free the connection index
187
0
        SOPC_SecureChannels_EnqueueEvent(SC_DISCONNECTED_ACK, id, params, 0);
188
0
        break;
189
0
    case SC_SERVICE_RCV_MSG:
190
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
191
0
                               "ServicesMgr: SC_SC_SERVICE_RCV_MSG scIdx=%" PRIu32 " reqId/0=%" PRIuPTR, id, auxParam);
192
193
        // id ==  connection Id
194
        // params = message content (byte buffer)
195
        // auxParam == requestId (server) / 0 (client)
196
0
        SOPC_ASSERT(NULL != (void*) params);
197
0
        io_dispatch_mgr__receive_msg_buffer(id, (constants__t_byte_buffer_i) params,
198
0
                                            (constants__t_request_context_i) auxParam, &bres);
199
0
        if (!bres)
200
0
        {
201
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
202
0
                                   "ServicesMgr: SC_SC_SERVICE_RCV_MSG scIdx=%" PRIu32 " reqId/0=%" PRIuPTR
203
0
                                   " received message considered invalid",
204
0
                                   id, auxParam);
205
0
        }
206
        // params is freed by services manager
207
0
        break;
208
0
    case SC_SND_FAILURE:
209
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
210
0
                               "ServicesMgr: SC_SND_FAILURE scIdx=%" PRIu32 " reqId/Handle=%" PRIuPTR
211
0
                               " statusCode=%" PRIXPTR,
212
0
                               id, (uintptr_t) params, auxParam);
213
214
0
        constants_statuscodes_bs__t_StatusCode_i statusCode;
215
0
        util_status_code__C_to_B((SOPC_StatusCode) auxParam, &statusCode);
216
0
        io_dispatch_mgr__snd_msg_failure(id, (constants__t_request_context_i) params, statusCode);
217
0
        break;
218
0
    case SC_REQUEST_TIMEOUT:
219
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
220
0
                               "ServicesMgr: SC_REQUEST_TIMEOUT scIdx=%" PRIu32 " reqHandle=%" PRIuPTR, id, auxParam);
221
222
        /* id = secure channel connection index,
223
           auxParam = request handle */
224
0
        SOPC_ASSERT(id <= constants__t_channel_i_max);
225
0
        SOPC_ASSERT(auxParam <= SOPC_MAX_PENDING_REQUESTS);
226
0
        io_dispatch_mgr__client_request_timeout(id, (uint32_t) auxParam);
227
0
        break;
228
0
    default:
229
0
        SOPC_ASSERT(false && "Unknown event");
230
0
    }
231
0
}
232
233
static void SOPC_Array_Free_WriteDataChanged(void* data)
234
0
{
235
0
    SOPC_WriteDataChanged* writeDataChanged = (SOPC_WriteDataChanged*) data;
236
0
    OpcUa_WriteValue_Clear(writeDataChanged->oldValue);
237
0
    SOPC_Free(writeDataChanged->oldValue);
238
0
    OpcUa_WriteValue_Clear(writeDataChanged->newValue);
239
0
    SOPC_Free(writeDataChanged->newValue);
240
0
}
241
242
static void SOPC_Array_Free_NodeChanged(void* data)
243
0
{
244
0
    SOPC_NodeChanged* nodeChanged = (SOPC_NodeChanged*) data;
245
0
    SOPC_NodeId_Clear(nodeChanged->nodeId);
246
0
    SOPC_Free(nodeChanged->nodeId);
247
0
}
248
249
static bool filterServerEvents(SOPC_Services_Event event, uint32_t id, uintptr_t params, uintptr_t auxParam)
250
0
{
251
0
    SOPC_UNUSED_ARG(id);
252
0
    SOPC_UNUSED_ARG(auxParam);
253
0
    SOPC_ReturnStatus status = SOPC_STATUS_OK;
254
0
    bool bParam = false;
255
0
    bool treatEvent = false;
256
0
    switch (event)
257
0
    {
258
0
    case APP_TO_SE_SERVER_CONFIGURED:
259
0
        bParam = (bool) params;
260
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
261
0
                               "ServicesMgr: APP_TO_SE_SERVER_CONFIGURED active=%" PRIuPTR, params);
262
0
        if (isServerConfigurationLocked == bParam)
263
0
        {
264
0
            SOPC_Logger_TraceWarning(
265
0
                SOPC_LOG_MODULE_CLIENTSERVER,
266
0
                "ServicesMgr: APP_TO_SE_SERVER_CONFIGURED IGNORED: received with same lock state=%s",
267
0
                bParam ? "locked" : "unlocked");
268
0
        }
269
0
        else
270
0
        {
271
0
            status = SOPC_ToolkitServer_UsingLockedConfig(bParam);
272
0
            if (SOPC_STATUS_OK == status)
273
0
            {
274
0
                isServerConfigurationLocked = bParam;
275
                // Forward to SC layer
276
0
                status = SOPC_SecureChannels_EnqueueEvent(SE_TO_SCS_SERVER_CONFIGURED, 0, (uintptr_t) params, 0);
277
0
                SOPC_ASSERT(SOPC_STATUS_OK == status);
278
0
            }
279
0
            else
280
0
            {
281
0
                SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
282
0
                                       "ServicesMgr: APP_TO_SE_SERVER_CONFIGURED FAILED: error in setting "
283
0
                                       "server config as used: %s",
284
0
                                       bParam ? "locked" : "unlocked");
285
0
            }
286
0
            if (!isServerConfigurationLocked)
287
0
            {
288
                // Clear server context in B model if configuration is unlocked (not configured anymore)
289
0
                io_dispatch_mgr__clear_server_configuration_context();
290
0
            }
291
0
        }
292
0
        break;
293
0
    case SE_TO_SE_SERVER_DATA_CHANGED:
294
0
    case SE_TO_SE_SERVER_NODE_CHANGED:
295
0
    case SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO:
296
0
        if (!isServerConfigurationLocked)
297
0
        {
298
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
299
0
                                   "filterServerEvents: %s IGNORED: server configuration is not locked (configured)",
300
0
                                   SE_TO_SE_SERVER_DATA_CHANGED == event ? "SE_TO_SE_SERVER_DATA_CHANGED"
301
0
                                   : SE_TO_SE_SERVER_NODE_CHANGED == event
302
0
                                       ? "SE_TO_SE_SERVER_NODE_CHANGED"
303
0
                                       : "SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO");
304
0
        }
305
0
        else
306
0
        {
307
0
            treatEvent = true;
308
0
        }
309
0
        break;
310
    /* Note: since sessions are now closed by SOPC_HelperInternal_ActualShutdownServer on Stop
311
             and clear_server_configuration_context on clear, all
312
             sessions / subscriptions  should be terminated when configuration has been cleared.
313
             But avoid inhibiting timeout and closing operations of sessions/subscriptions
314
             as those do not use the configuration at all.
315
    case SE_TO_SE_SERVER_INACTIVATED_SESSION_PRIO:
316
    case SE_TO_SE_SERVER_ASYNC_CLOSE_SUBSCRIPTION:
317
    case TIMER_SE_EVAL_SESSION_TIMEOUT:
318
    case TIMER_SE_PUBLISH_CYCLE_TIMEOUT:
319
    */
320
0
    case APP_TO_SE_OPEN_ENDPOINT:
321
0
    case APP_TO_SE_CLOSE_ENDPOINT:
322
0
    case APP_TO_SE_LOCAL_SERVICE_REQUEST:
323
0
    case APP_TO_SE_TRIGGER_EVENT:
324
0
    case APP_TO_SE_EVAL_USR_CRT_SESSIONS:
325
0
        if (!isServerConfigurationLocked)
326
0
        {
327
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
328
0
                                   "filterServerEvents: %s IGNORED: server configuration is not locked (configured)",
329
0
                                   APP_TO_SE_OPEN_ENDPOINT == event           ? "APP_TO_SE_OPEN_ENDPOINT"
330
0
                                   : APP_TO_SE_CLOSE_ENDPOINT == event        ? "APP_TO_SE_CLOSE_ENDPOINT"
331
0
                                   : APP_TO_SE_LOCAL_SERVICE_REQUEST == event ? "APP_TO_SE_LOCAL_SERVICE_REQUEST"
332
0
                                   : APP_TO_SE_TRIGGER_EVENT == event         ? "APP_TO_SE_TRIGGER_EVENT"
333
0
                                                                              : "APP_TO_SE_EVAL_USR_CRT_SESSIONS");
334
0
        }
335
0
        else
336
0
        {
337
0
            treatEvent = true;
338
0
        }
339
0
        break;
340
0
    default:
341
0
        treatEvent = true;
342
0
        break;
343
0
    }
344
0
    SOPC_Internal_EventContext* eventContext = NULL;
345
0
    SOPC_Internal_AsyncSendMsgData* msg_data = NULL;
346
0
    if (!treatEvent)
347
0
    {
348
        // Clear provided data
349
0
        switch (event)
350
0
        {
351
0
        case SE_TO_SE_SERVER_DATA_CHANGED:
352
0
            SOPC_Array_Set_Free_Func((SOPC_Array*) params, &SOPC_Array_Free_WriteDataChanged);
353
0
            SOPC_Array_Delete((SOPC_Array*) params);
354
0
            break;
355
0
        case SE_TO_SE_SERVER_NODE_CHANGED:
356
0
            SOPC_Array_Set_Free_Func((SOPC_Array*) params, &SOPC_Array_Free_NodeChanged);
357
0
            SOPC_Array_Delete((SOPC_Array*) params);
358
0
            break;
359
0
        case SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO:
360
0
            msg_data = (SOPC_Internal_AsyncSendMsgData*) params;
361
0
            SOPC_EncodeableObject_Delete(*(SOPC_EncodeableType**) msg_data->msgToSend, (void**) &msg_data->msgToSend);
362
0
            SOPC_Free(msg_data);
363
0
            break;
364
0
        case APP_TO_SE_EVAL_USR_CRT_SESSIONS:
365
0
            break; // Nothing to clear
366
0
        case APP_TO_SE_OPEN_ENDPOINT:
367
0
        case APP_TO_SE_CLOSE_ENDPOINT:
368
0
            break; // Nothing to clear
369
0
        case APP_TO_SE_LOCAL_SERVICE_REQUEST:
370
0
            SOPC_EncodeableObject_Delete(*(SOPC_EncodeableType**) params, (void**) &params);
371
            // Note: the response context is not returned to application,
372
            // this is managed in server wrapper by using the waiting request context list
373
0
            break;
374
0
        case APP_TO_SE_TRIGGER_EVENT:
375
            // params =  (SOPC_Internal_EventContext*)
376
0
            eventContext = (SOPC_Internal_EventContext*) params;
377
0
            SOPC_ASSERT(NULL != eventContext);
378
0
            SOPC_NodeId_Clear(&eventContext->notifierNodeId);
379
0
            SOPC_Event_Delete(&eventContext->event);
380
0
            SOPC_Free(eventContext);
381
0
            break;
382
0
        default:
383
0
            break;
384
0
        }
385
0
    }
386
0
    return treatEvent;
387
0
}
388
389
static void onServiceEvent(SOPC_EventHandler* handler,
390
                           int32_t scEvent,
391
                           uint32_t id,
392
                           uintptr_t params,
393
                           uintptr_t auxParam)
394
0
{
395
0
    SOPC_Services_Event event = (SOPC_Services_Event) scEvent;
396
0
    SOPC_ReturnStatus status = SOPC_STATUS_OK;
397
0
    SOPC_Endpoint_Config* epConfig = NULL;
398
0
    constants_statuscodes_bs__t_StatusCode_i sCode = constants_statuscodes_bs__e_sc_ok;
399
0
    SOPC_EncodeableType* encType = NULL;
400
0
    bool lbres = false;
401
0
    bool bres = false;
402
0
    void* msg = NULL;
403
0
    size_t length = 0;
404
0
    SOPC_Array* dataOrNodeChangedArray = NULL;
405
0
    SOPC_WriteDataChanged* writeDataChanged = NULL;
406
0
    SOPC_NodeChanged* nodeChanged = NULL;
407
0
    OpcUa_WriteValue* old_value = NULL;
408
0
    OpcUa_WriteValue* new_value = NULL;
409
0
    SOPC_Internal_AsyncSendMsgData* msg_data;
410
0
    const SOPC_NodeId* nodeId2 = NULL;
411
0
    char* nodeIdStr = NULL;
412
0
    char* nodeIdStr2 = NULL;
413
0
    const char* reverseEndpointURL = NULL;
414
0
    SOPC_Internal_SessionAppContext* sessionContext = NULL;
415
0
    SOPC_ExtensionObject* userToken = NULL;
416
0
    SOPC_Internal_DiscoveryContext* discoveryContext = NULL;
417
0
    SOPC_Internal_EventContext* eventContext = NULL;
418
0
    SOPC_DateTime currentTime = 0;
419
420
0
    bool treatEvent = filterServerEvents(event, id, params, auxParam);
421
0
    if (!treatEvent)
422
0
    {
423
0
        return;
424
0
    }
425
426
0
    switch (event)
427
0
    {
428
0
    case SE_TO_SE_SC_ALL_DISCONNECTED:
429
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
430
0
                               "ServicesMgr: SE_TO_SE_SC_ALL_DISCONNECTED clientOnly=%" PRIuPTR, params);
431
        // Call directly toolkit configuration callback
432
0
        SOPC_Internal_AllClientSecureChannelsDisconnected((bool) params);
433
0
        break;
434
435
0
    case SE_TO_SE_ACTIVATE_ORPHANED_SESSION:
436
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
437
0
                               "ServicesMgr: SE_TO_SE_ACTIVATE_ORPHANED_SESSION session=%" PRIu32 " scCfgIdx=%" PRIuPTR,
438
0
                               id, auxParam);
439
440
0
        SOPC_ASSERT(auxParam <= constants__t_channel_config_idx_i_max);
441
0
        io_dispatch_mgr__internal_client_activate_orphaned_session(id, (constants__t_channel_config_idx_i) auxParam);
442
0
        break;
443
0
    case SE_TO_SE_CREATE_SESSION:
444
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
445
0
                               "ServicesMgr: SE_TO_SE_CREATE_SESSION session=%" PRIu32 " scCfgIdx=%" PRIuPTR, id,
446
0
                               auxParam);
447
0
        SOPC_ASSERT(auxParam <= constants__t_channel_config_idx_i_max);
448
0
        io_dispatch_mgr__internal_client_create_session((constants__t_session_i) id,
449
0
                                                        (constants__t_channel_config_idx_i) auxParam);
450
0
        break;
451
0
    case SE_TO_SE_ACTIVATE_SESSION:
452
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: SE_TO_SE_ACTIVATE_SESSION session=%" PRIu32,
453
0
                               id);
454
455
0
        if (NULL != (void*) params)
456
0
        {
457
0
            io_dispatch_mgr__client_reactivate_session_new_user(id, (constants__t_user_token_i) params);
458
0
        }
459
0
        else
460
0
        {
461
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
462
0
                                   "ServicesMgr: SE_TO_SE_ACTIVATE_SESSION session=%" PRIu32 " user parameter is NULL",
463
0
                                   id);
464
0
            sCode = constants_statuscodes_bs__e_sc_bad_generic;
465
0
        }
466
0
        break;
467
0
    case SE_TO_SE_SERVER_DATA_CHANGED:
468
        /* Server side only:
469
           params = (SOPC_Array*) array of SOPC_WriteDataChanged
470
         */
471
0
        SOPC_ASSERT((void*) params != NULL);
472
473
0
        dataOrNodeChangedArray = (SOPC_Array*) params;
474
0
        bres = true;
475
0
        length = SOPC_Array_Size(dataOrNodeChangedArray);
476
0
        for (size_t i = 0; i < length; i++)
477
0
        {
478
0
            writeDataChanged = (SOPC_WriteDataChanged*) SOPC_Array_Get_Ptr(dataOrNodeChangedArray, i);
479
0
            SOPC_ASSERT(writeDataChanged != NULL);
480
0
            old_value = writeDataChanged->oldValue;
481
0
            new_value = writeDataChanged->newValue;
482
            /* Note: write values deallocation managed by B model */
483
0
            io_dispatch_mgr__internal_server_data_changed(old_value, new_value, &lbres);
484
0
            bres = bres && lbres;
485
0
        }
486
0
        SOPC_Array_Delete(dataOrNodeChangedArray);
487
0
        if (bres == false)
488
0
        {
489
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
490
0
                                   "ServicesMgr: SE_TO_SE_SERVER_DATA_CHANGED session=%" PRIu32 " treatment failed",
491
0
                                   id);
492
0
        }
493
0
        break;
494
0
    case SE_TO_SE_SERVER_NODE_CHANGED:
495
        /* Server side only:
496
           params = (SOPC_Array*) array of SOPC_NodeChanged
497
         */
498
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
499
0
                               "ServicesMgr: SE_TO_SE_SERVER_NODE_CHANGED batched notifications");
500
501
0
        SOPC_ASSERT(NULL != (void*) params);
502
0
        dataOrNodeChangedArray = (SOPC_Array*) params;
503
0
        length = SOPC_Array_Size(dataOrNodeChangedArray);
504
0
        lbres = SOPC_LOG_LEVEL_DEBUG == SOPC_Logger_GetTraceLogLevel();
505
0
        for (size_t i = 0; i < length; i++)
506
0
        {
507
0
            nodeChanged = (SOPC_NodeChanged*) SOPC_Array_Get_Ptr(dataOrNodeChangedArray, i);
508
0
            SOPC_ASSERT(NULL != nodeChanged);
509
0
            if (lbres)
510
0
            {
511
0
                nodeIdStr = SOPC_NodeId_ToCString(nodeChanged->nodeId);
512
0
                SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
513
0
                                       "ServicesMgr: SE_TO_SE_SERVER_NODE_CHANGED %s nodeId: %s",
514
0
                                       nodeChanged->added ? "added" : "deleted", nodeIdStr);
515
0
                SOPC_Free(nodeIdStr);
516
0
            }
517
0
            io_dispatch_mgr__internal_server_node_changed(nodeChanged->added, nodeChanged->nodeId);
518
0
            SOPC_NodeId_Clear(nodeChanged->nodeId);
519
0
            SOPC_Free(nodeChanged->nodeId);
520
0
        }
521
0
        SOPC_Array_Delete(dataOrNodeChangedArray);
522
0
        break;
523
0
    case SE_TO_SE_SERVER_INACTIVATED_SESSION_PRIO:
524
        /* Server side only:
525
           id = session id
526
           auxParam = (int32_t) session state
527
         */
528
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
529
0
                               "ServicesMgr: SE_TO_SE_SERVER_INACTIVATED_SESSION_PRIO session=%" PRIu32
530
0
                               " sessionState=%" PRIuPTR,
531
0
                               id, auxParam);
532
533
0
        io_dispatch_mgr__internal_server_inactive_session_prio_event((constants__t_session_i) id,
534
0
                                                                     (constants__t_sessionState_i) auxParam, &bres);
535
536
0
        if (bres == false)
537
0
        {
538
0
            SOPC_Logger_TraceError(
539
0
                SOPC_LOG_MODULE_CLIENTSERVER,
540
0
                "ServicesMgr: SE_TO_SE_SERVER_INACTIVATED_SESSION_PRIO session=%" PRIu32 " treatment failed", id);
541
0
        }
542
0
        break;
543
0
    case SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO:
544
        /* Server side only:
545
           id = session id
546
           params = (SOPC_Internal_AsyncSendMsgData*)
547
         */
548
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
549
0
                               "ServicesMgr: SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO session=%" PRIu32, id);
550
551
0
        msg_data = (void*) params;
552
0
        SOPC_ASSERT(msg_data != NULL);
553
554
0
        io_dispatch_mgr__internal_server_send_publish_response_prio_event(
555
0
            (constants__t_session_i) id, msg_data->requestHandle, msg_data->requestId, msg_data->msgToSend,
556
0
            (constants_statuscodes_bs__t_StatusCode_i) msg_data->bStatusCode, &bres);
557
0
        SOPC_Free(msg_data);
558
559
0
        if (!bres)
560
0
        {
561
0
            SOPC_Logger_TraceError(
562
0
                SOPC_LOG_MODULE_CLIENTSERVER,
563
0
                "ServicesMgr: SE_TO_SE_SERVER_SEND_ASYNC_PUB_RESP_PRIO session=%" PRIu32 " treatment failed", id);
564
0
        }
565
0
        break;
566
0
    case SE_TO_SE_SERVER_ASYNC_CLOSE_SUBSCRIPTION:
567
        /* Server side only:
568
           id = subscription id
569
         */
570
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
571
0
                               "ServicesMgr: SE_TO_SE_SERVER_ASYNC_CLOSE_SUBSCRIPTION subscription=%" PRIu32, id);
572
573
0
        io_dispatch_mgr__internal_server_close_subscription((constants__t_subscription_i) id, &bres);
574
575
0
        if (!bres)
576
0
        {
577
0
            SOPC_Logger_TraceError(
578
0
                SOPC_LOG_MODULE_CLIENTSERVER,
579
0
                "ServicesMgr: SE_TO_SE_SERVER_ASYNC_CLOSE_SUBSCRIPTION subscription=%" PRIu32 " treatment failed", id);
580
0
        }
581
0
        break;
582
0
    case TIMER_SE_EVAL_SESSION_TIMEOUT:
583
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
584
0
                               "ServicesMgr: TIMER_SE_EVAL_SESSION_TIMEOUT session=%" PRIu32, id);
585
0
        io_dispatch_mgr__internal_server_evaluate_session_timeout((constants__t_session_i) id);
586
0
        break;
587
0
    case TIMER_SE_PUBLISH_CYCLE_TIMEOUT:
588
        /* Server side only: id = subscription id */
589
0
        io_dispatch_mgr__internal_server_subscription_publish_timeout((constants__t_subscription_i) id, &bres);
590
0
        if (bres == false)
591
0
        {
592
0
            SOPC_Logger_TraceError(
593
0
                SOPC_LOG_MODULE_CLIENTSERVER,
594
0
                "ServicesMgr: TIMER_SE_PUBLISH_CYCLE_TIMEOUT subscription=%" PRIu32 " treatment failed", id);
595
0
        }
596
0
        break;
597
598
    /* App to Services events */
599
0
    case APP_TO_SE_SERVER_CONFIGURED:
600
        /* Already managed in filterServerEvents */
601
0
        break;
602
0
    case APP_TO_SE_OPEN_ENDPOINT:
603
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_OPEN_ENDPOINT epCfgIdx=%" PRIu32,
604
0
                               id);
605
606
        // id ==  endpoint configuration index
607
        // => B model entry point to add
608
0
        epConfig = SOPC_ToolkitServer_GetEndpointConfig(id);
609
0
        if (NULL == epConfig)
610
0
        {
611
0
            status = SOPC_App_EnqueueComEvent(SE_CLOSED_ENDPOINT, id, (uintptr_t) NULL, SOPC_STATUS_INVALID_PARAMETERS);
612
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
613
0
        }
614
0
        else
615
0
        {
616
0
            status = SOPC_SecureChannels_EnqueueEvent(EP_OPEN,
617
0
                                                      id, // Server endpoint config idx
618
0
                                                      (uintptr_t) NULL, 0);
619
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
620
0
        }
621
0
        break;
622
0
    case APP_TO_SE_CLOSE_ENDPOINT:
623
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_CLOSE_ENDPOINT epCfgIdx=%" PRIu32,
624
0
                               id);
625
626
        // id ==  endpoint configuration index
627
        // => B model entry point to add
628
0
        epConfig = SOPC_ToolkitServer_GetEndpointConfig(id);
629
0
        if (NULL == epConfig)
630
0
        {
631
0
            status = SOPC_App_EnqueueComEvent(SE_CLOSED_ENDPOINT, id, (uintptr_t) NULL, SOPC_STATUS_INVALID_PARAMETERS);
632
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
633
0
        }
634
0
        else
635
0
        {
636
0
            status = SOPC_SecureChannels_EnqueueEvent(EP_CLOSE, id, (uintptr_t) NULL, 0);
637
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
638
0
        }
639
0
        break;
640
641
0
    case APP_TO_SE_LOCAL_SERVICE_REQUEST:
642
0
        if ((void*) params != NULL)
643
0
        {
644
0
            encType = *(SOPC_EncodeableType**) params;
645
0
        }
646
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
647
0
                               "ServicesMgr: APP_TO_SE_LOCAL_SERVICE_REQUEST epCfgIdx=%" PRIu32
648
0
                               " msgType=%s ctx=%" PRIuPTR,
649
0
                               id, SOPC_EncodeableType_GetName(encType), auxParam);
650
651
        // id =  endpoint configuration index
652
        // params = local service request
653
        // auxParam = user application session context
654
0
        SOPC_ASSERT(id <= INT32_MAX);
655
656
0
        io_dispatch_mgr__server_treat_local_service_request(id, (constants__t_msg_i) params, auxParam, &sCode);
657
0
        if (constants_statuscodes_bs__e_sc_ok != sCode)
658
0
        {
659
            // Error case
660
0
            status = SOPC_EncodeableObject_Create(&OpcUa_ServiceFault_EncodeableType, &msg);
661
0
            if (SOPC_STATUS_OK == status && NULL != msg)
662
0
            {
663
0
                util_status_code__B_to_C(sCode, &((OpcUa_ServiceFault*) msg)->ResponseHeader.ServiceResult);
664
0
            }
665
0
            else
666
0
            {
667
0
                msg = NULL;
668
0
            }
669
0
            status = SOPC_App_EnqueueComEvent(SE_LOCAL_SERVICE_RESPONSE, id, (uintptr_t) msg, auxParam);
670
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
671
0
            SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_CLIENTSERVER,
672
0
                                     "ServicesMgr: APP_TO_SE_LOCAL_SERVICE_REQUEST failed epCfgIdx=%" PRIu32
673
0
                                     " msgType=%s ctx=%" PRIuPTR,
674
0
                                     id, SOPC_EncodeableType_GetName(encType), auxParam);
675
0
        }
676
0
        break;
677
0
    case APP_TO_SE_TRIGGER_EVENT:
678
        // params =  (SOPC_Internal_EventContext*)
679
0
        eventContext = (SOPC_Internal_EventContext*) params;
680
0
        SOPC_ASSERT(NULL != eventContext);
681
0
        nodeIdStr = SOPC_NodeId_ToCString(&eventContext->notifierNodeId);
682
0
        nodeId2 = SOPC_Event_GetEventTypeId(eventContext->event);
683
0
        nodeIdStr2 = (NULL == nodeId2 ? SOPC_strdup("") : SOPC_NodeId_ToCString(nodeId2));
684
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
685
0
                               "ServicesMgr: APP_TO_SE_TRIGGER_EVENT eventTypeId=%s, notifierId=%s", nodeIdStr2,
686
0
                               nodeIdStr);
687
688
        // Update the receiveTime variable (and time variable if not set)
689
0
        currentTime = SOPC_Time_GetCurrentTimeUTC();
690
0
        status = SOPC_Event_SetReceiveTime(eventContext->event, currentTime);
691
0
        SOPC_ASSERT(SOPC_STATUS_OK == status);
692
0
        if (0 == SOPC_Event_GetTime(eventContext->event))
693
0
        {
694
0
            status = SOPC_Event_SetTime(eventContext->event, currentTime);
695
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
696
0
        }
697
698
0
        io_dispatch_mgr__internal_server_event_triggered(&eventContext->notifierNodeId, eventContext->event,
699
0
                                                         eventContext->optSessionId, eventContext->optSubscriptionId,
700
0
                                                         eventContext->optMonitoredItemId, &bres);
701
0
        if (!bres)
702
0
        {
703
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
704
0
                                   "ServicesMgr: failure in treatment of APP_TO_SE_TRIGGER_EVENT eventTypeId=%s, "
705
0
                                   "notifierId=%s",
706
0
                                   nodeIdStr2, nodeIdStr);
707
0
        }
708
0
        SOPC_Free(nodeIdStr);
709
0
        SOPC_Free(nodeIdStr2);
710
711
0
        SOPC_NodeId_Clear(&eventContext->notifierNodeId);
712
0
        SOPC_Event_Delete(&eventContext->event);
713
0
        SOPC_Free(eventContext);
714
0
        break;
715
0
    case APP_TO_SE_OPEN_REVERSE_ENDPOINT:
716
        /* id = reverse endpoint description config index */
717
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
718
0
                               "ServicesMgr: APP_TO_SE_OPEN_REVERSE_ENDPOINT reverseEpCfgIdx=%" PRIu32, id);
719
        // Check config index is valid
720
0
        reverseEndpointURL = SOPC_ToolkitClient_GetReverseEndpointURL(id);
721
0
        SOPC_ASSERT(NULL != reverseEndpointURL && "Invalid reverse endpoint configuration index provided");
722
0
        status = SOPC_SecureChannels_EnqueueEvent(REVERSE_EP_OPEN,
723
0
                                                  id, // Reverse endpoint config idx
724
0
                                                  (uintptr_t) NULL, 0);
725
0
        SOPC_ASSERT(SOPC_STATUS_OK == status);
726
0
        break;
727
0
    case APP_TO_SE_CLOSE_REVERSE_ENDPOINT:
728
        /* id = reverse endpoint description config index */
729
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
730
0
                               "ServicesMgr: APP_TO_SE_CLOSE_REVERSE_ENDPOINT reverseEpCfgIdx=%" PRIu32, id);
731
        // Check config index is valid
732
0
        reverseEndpointURL = SOPC_ToolkitClient_GetReverseEndpointURL(id);
733
0
        SOPC_ASSERT(NULL != reverseEndpointURL && "Invalid reverse endpoint configuration index provided");
734
0
        status = SOPC_SecureChannels_EnqueueEvent(REVERSE_EP_CLOSE, id, (uintptr_t) NULL, 0);
735
0
        SOPC_ASSERT(SOPC_STATUS_OK == status);
736
0
        break;
737
0
    case APP_TO_SE_ACTIVATE_SESSION:
738
        // id = secure channel config index,
739
        // params = reverse endpoint connection index or 0 if not a reverse connection
740
        // auxParam = (SOPC_Internal_SessionAppContext*)
741
0
        SOPC_ASSERT(id <= constants__t_channel_config_idx_i_max);
742
0
        SOPC_ASSERT((void*) auxParam != NULL);
743
0
        sessionContext = (SOPC_Internal_SessionAppContext*) auxParam;
744
0
        userToken = sessionContext->userToken;
745
0
        sessionContext->userToken = NULL; // Provided as separated parameter
746
747
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
748
0
                               "ServicesMgr: APP_TO_SE_ACTIVATE_SESSION scCfgIdx=%" PRIu32 " reverseEpCfgIdx=%" PRIuPTR
749
0
                               " ctx=%" PRIuPTR,
750
0
                               id, params, sessionContext->userSessionContext);
751
752
0
        io_dispatch_mgr__client_activate_new_session(id, (uint32_t) params, userToken, sessionContext, &bres);
753
754
0
        if (!bres)
755
0
        {
756
0
            SOPC_App_EnqueueComEvent(SE_SESSION_ACTIVATION_FAILURE,
757
0
                                     0,                                   // session id (not yet defined)
758
0
                                     (uintptr_t) NULL,                    // user ?
759
0
                                     sessionContext->userSessionContext); // user application session context
760
0
            SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_CLIENTSERVER,
761
0
                                     "ServicesMgr: APP_TO_SE_ACTIVATE_SESSION failed scCfgIdx=%" PRIu32
762
0
                                     " reverseEpCfgIdx=%" PRIuPTR " ctx=%" PRIuPTR,
763
0
                                     id, params, auxParam);
764
0
            SOPC_ExtensionObject_Clear(userToken);
765
0
            SOPC_Free(userToken);
766
0
            SOPC_Free(sessionContext);
767
0
        }
768
0
        break;
769
0
    case APP_TO_SE_SEND_SESSION_REQUEST:
770
0
        if ((void*) params != NULL)
771
0
        {
772
0
            encType = *(SOPC_EncodeableType**) params;
773
0
        }
774
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
775
0
                               "ServicesMgr: APP_TO_SE_SEND_SESSION_REQUEST  session=%" PRIu32
776
0
                               " msgType=%s ctx=%" PRIuPTR,
777
0
                               id, SOPC_EncodeableType_GetName(encType), auxParam);
778
779
        // id == session id
780
        // params = request
781
0
        SOPC_ASSERT(id <= constants__t_session_i_max);
782
783
0
        io_dispatch_mgr__client_send_service_request(id, (constants__t_msg_i) params, auxParam, &sCode);
784
0
        if (sCode != constants_statuscodes_bs__e_sc_ok)
785
0
        {
786
0
            status = SOPC_App_EnqueueComEvent(SE_SND_REQUEST_FAILED, util_status_code__B_to_return_status_C(sCode),
787
0
                                              (uintptr_t) encType, auxParam);
788
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
789
790
0
            SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_CLIENTSERVER,
791
0
                                     "ServicesMgr: APP_TO_SE_SEND_SESSION_REQUEST failed session=%" PRIu32
792
0
                                     " msgType=%s ctx=%" PRIuPTR,
793
0
                                     id, SOPC_EncodeableType_GetName(encType), auxParam);
794
0
        }
795
0
        break;
796
0
    case APP_TO_SE_CLOSE_SESSION:
797
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_CLOSE_SESSION  session=%" PRIu32,
798
0
                               id);
799
800
        // id == session id
801
0
        SOPC_ASSERT(id <= constants__t_session_i_max);
802
803
0
        io_dispatch_mgr__client_send_close_session_request(id, &sCode);
804
0
        if (sCode != constants_statuscodes_bs__e_sc_ok)
805
0
        {
806
0
            SOPC_Logger_TraceError(SOPC_LOG_MODULE_CLIENTSERVER,
807
0
                                   "ServicesMgr: APP_TO_SE_CLOSE_SESSION failed session=%" PRIu32, id);
808
0
        }
809
0
        break;
810
0
    case APP_TO_SE_CLOSE_CONNECTION:
811
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
812
0
                               "ServicesMgr: APP_TO_SE_CLOSE_CONNECTION  scCfgIdx=%" PRIu32, id);
813
        // id = secure channel config index
814
0
        io_dispatch_mgr__client_close_channel(id, auxParam, &bres);
815
0
        if (!bres)
816
0
        {
817
0
            SOPC_App_EnqueueComEvent(SE_CLOSED_CHANNEL, id, (uintptr_t) false, auxParam);
818
0
        }
819
0
        break;
820
0
    case APP_TO_SE_SEND_DISCOVERY_REQUEST:
821
        // id = secure channel config index,
822
        // params = reverse endpoint connection index or 0 if not a reverse connection
823
        // auxParam = (SOPC_Internal_DiscoveryContext*)
824
0
        SOPC_ASSERT(id <= constants_bs__t_channel_config_idx_i_max);
825
0
        SOPC_ASSERT((void*) auxParam != NULL);
826
827
0
        discoveryContext = (SOPC_Internal_DiscoveryContext*) auxParam;
828
829
0
        if (discoveryContext->opcuaMessage != NULL)
830
0
        {
831
0
            encType = *(SOPC_EncodeableType**) discoveryContext->opcuaMessage;
832
0
        }
833
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
834
0
                               "ServicesMgr: APP_TO_SE_SEND_DISCOVERY_REQUEST scCfgIdx=%" PRIu32
835
0
                               " reverseEpCfgIdx=%" PRIuPTR " msgType=%s ctx=%" PRIuPTR,
836
0
                               id, params, SOPC_EncodeableType_GetName(encType), discoveryContext->discoveryAppContext);
837
838
0
        io_dispatch_mgr__client_send_discovery_request(id, (uint32_t) params,
839
0
                                                       (constants__t_msg_i) discoveryContext->opcuaMessage,
840
0
                                                       discoveryContext->discoveryAppContext, &sCode);
841
0
        if (sCode != constants_statuscodes_bs__e_sc_ok)
842
0
        {
843
0
            status = SOPC_App_EnqueueComEvent(SE_SND_REQUEST_FAILED, util_status_code__B_to_return_status_C(sCode),
844
0
                                              (uintptr_t) encType, discoveryContext->discoveryAppContext);
845
0
            SOPC_ASSERT(SOPC_STATUS_OK == status);
846
847
0
            SOPC_Logger_TraceWarning(SOPC_LOG_MODULE_CLIENTSERVER,
848
0
                                     "ServicesMgr: APP_TO_SE_SEND_DISCOVERY_REQUEST failed scCfgIdx=%" PRIu32
849
0
                                     " reverseEpCfgIdx=%" PRIuPTR " msgType=%s ctx=%" PRIuPTR,
850
0
                                     id, params, SOPC_EncodeableType_GetName(encType), auxParam);
851
0
        }
852
0
        SOPC_Free(discoveryContext);
853
0
        break;
854
0
    case APP_TO_SE_CLOSE_ALL_CONNECTIONS:
855
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
856
0
                               "ServicesMgr: APP_TO_SE_CLOSE_ALL_CONNECTIONS clientOnly=%" PRIuPTR, params);
857
858
0
        io_dispatch_mgr__close_all_active_connections((bool) params, &bres);
859
0
        if (!bres)
860
0
        {
861
            // All connections already closed: simulate new service event
862
0
            onServiceEvent(handler, SE_TO_SE_SC_ALL_DISCONNECTED, id, params, auxParam);
863
0
        }
864
0
        break;
865
0
    case APP_TO_SE_REEVALUATE_SCS:
866
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER,
867
0
                               "ServicesMgr: APP_TO_SE_REEVALUATE_SCS isServer=%" PRIuPTR " isOwnCert=%" PRIuPTR,
868
0
                               params, auxParam);
869
0
        status = SOPC_SecureChannels_EnqueueEvent(SCS_REEVALUATE_SCS, id, params, auxParam);
870
0
        SOPC_ASSERT(SOPC_STATUS_OK == status);
871
0
        break;
872
0
    case APP_TO_SE_EVAL_USR_CRT_SESSIONS:
873
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_EVAL_USR_CRT_SESSION");
874
0
        io_dispatch_mgr__internal_server_evaluate_all_session_user_cert();
875
0
        break;
876
0
    case APP_TO_SE_UNINITIALIZE_SERVICES:
877
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_UNINITIALIZE_SERVICES");
878
0
        io_dispatch_mgr__UNINITIALISATION();
879
0
        break;
880
0
    case APP_TO_SE_CLOSE_SERVER_SESSIONS:
881
0
        SOPC_Logger_TraceDebug(SOPC_LOG_MODULE_CLIENTSERVER, "ServicesMgr: APP_TO_SE_CLOSE_SERVER_SESSIONS");
882
0
        io_dispatch_mgr__server_close_sessions((SOPC_SessionId) id);
883
0
        break;
884
0
    default:
885
0
        SOPC_ASSERT(false);
886
0
    }
887
0
}
888
889
void SOPC_Services_EnqueueEvent(SOPC_Services_Event seEvent, uint32_t id, uintptr_t params, uintptr_t auxParam)
890
0
{
891
0
    SOPC_ASSERT(servicesEventHandler != NULL);
892
0
    SOPC_EventHandler_Post(servicesEventHandler, (int32_t) seEvent, id, params, auxParam);
893
0
}
894
895
uint32_t SOPC_Services_Get_QueueSize(void)
896
0
{
897
0
    return SOPC_EventHandler_Get_QueueSize(servicesEventHandler);
898
0
}
899
900
void SOPC_Services_Initialize(SOPC_SetListenerFunc* setSecureChannelsListener)
901
0
{
902
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
903
904
0
    servicesLooper = SOPC_Looper_Create("Services");
905
0
    SOPC_ASSERT(servicesLooper != NULL);
906
907
0
    servicesEventHandler = SOPC_EventHandler_Create(servicesLooper, onServiceEvent);
908
0
    SOPC_ASSERT(servicesEventHandler != NULL);
909
910
0
    secureChannelsEventHandler = SOPC_EventHandler_Create(servicesLooper, onSecureChannelEvent);
911
0
    SOPC_ASSERT(secureChannelsEventHandler != NULL);
912
913
    // Init async close management flag
914
0
    status = SOPC_Mutex_Initialization(&closeAllConnectionsSync.mutex);
915
0
    SOPC_ASSERT(status == SOPC_STATUS_OK);
916
917
0
    status = SOPC_Condition_Init(&closeAllConnectionsSync.cond);
918
0
    SOPC_ASSERT(status == SOPC_STATUS_OK);
919
920
0
    setSecureChannelsListener(secureChannelsEventHandler);
921
922
    /* Init B model */
923
0
    INITIALISATION();
924
0
}
925
926
void SOPC_Services_CloseAllSCs(bool clientOnly)
927
0
{
928
0
    SOPC_Mutex_Lock(&closeAllConnectionsSync.mutex);
929
0
    closeAllConnectionsSync.requestedFlag = true;
930
0
    closeAllConnectionsSync.clientOnlyFlag = clientOnly;
931
    // Do a synchronous connections closed (effective on client only)
932
0
    SOPC_EventHandler_Post(servicesEventHandler, APP_TO_SE_CLOSE_ALL_CONNECTIONS, 0, (uintptr_t) clientOnly, 0);
933
0
    while (!closeAllConnectionsSync.allDisconnectedFlag)
934
0
    {
935
0
        SOPC_Mutex_UnlockAndWaitCond(&closeAllConnectionsSync.cond, &closeAllConnectionsSync.mutex);
936
0
    }
937
0
    closeAllConnectionsSync.allDisconnectedFlag = false;
938
0
    closeAllConnectionsSync.clientOnlyFlag = false;
939
0
    closeAllConnectionsSync.requestedFlag = false;
940
0
    SOPC_Mutex_Unlock(&closeAllConnectionsSync.mutex);
941
0
}
942
943
void SOPC_Services_Clear(void)
944
0
{
945
0
    SOPC_EventHandler_Post(servicesEventHandler, APP_TO_SE_UNINITIALIZE_SERVICES, 0, 0, 0);
946
947
    // Set to NULL handlers deallocated by SOPC_Looper_Delete call
948
0
    servicesEventHandler = NULL;
949
0
    secureChannelsEventHandler = NULL;
950
0
    SOPC_Looper_Delete(servicesLooper);
951
0
    servicesLooper = NULL;
952
953
0
    closeAllConnectionsSync.allDisconnectedFlag = false;
954
0
    closeAllConnectionsSync.clientOnlyFlag = false;
955
    closeAllConnectionsSync.requestedFlag = false;
956
0
    SOPC_Mutex_Clear(&closeAllConnectionsSync.mutex);
957
0
    SOPC_Condition_Clear(&closeAllConnectionsSync.cond);
958
0
}