Coverage Report

Created: 2025-07-11 06:29

/src/S2OPC/src/PubSub/common/sopc_pubsub_conf.c
Line
Count
Source (jump to first uncovered line)
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 <errno.h>
21
#include <inttypes.h>
22
#include <stdbool.h>
23
#include <stdint.h>
24
#include <stdio.h>
25
#include <string.h>
26
27
#include "sopc_assert.h"
28
#include "sopc_logger.h"
29
#include "sopc_mem_alloc.h"
30
#include "sopc_pubsub_conf.h"
31
32
/**
33
 * Defines a source of Data Items
34
 */
35
typedef struct SOPC_PublishedDataItemsData
36
{
37
    uint16_t length;
38
    SOPC_PublishedVariable* publishedData;
39
} SOPC_PublishedDataItemsData;
40
41
struct SOPC_PublishedVariable
42
{
43
    SOPC_NodeId* nodeId;
44
    uint32_t attributeId;
45
    char* indexRange;
46
};
47
48
/**
49
 * Defines a source of Events
50
 */
51
52
struct SOPC_PubSubConfiguration
53
{
54
    uint32_t pub_connection_length;
55
    SOPC_PubSubConnection* pub_connection;
56
57
    uint32_t sub_connection_length;
58
    SOPC_PubSubConnection* sub_connection;
59
60
    uint32_t publishedDataSet_length;
61
    SOPC_PublishedDataSet* publishedDataSet;
62
};
63
64
struct SOPC_PubSubConnection
65
{
66
    SOPC_PubSubConnection_Type type;
67
    char* name;
68
    bool enabled;
69
    SOPC_Conf_PublisherId publisherId;
70
    // Give Network and Transport Protocol as URI
71
    char* transportProfileUri;
72
    // Network interface name (Ethernet only): mandatory for Publisher
73
    char* interfaceName;
74
    // NetworkAddressDataType is string
75
    char* address;
76
    uint16_t writerGroups_length;
77
    SOPC_WriterGroup* writerGroups;
78
    uint16_t readerGroups_length;
79
    SOPC_ReaderGroup* readerGroups;
80
    // Username for MQTT protocol
81
    char* mqttUsername;
82
    // Password for MQTT protocol
83
    char* mqttPassword;
84
85
    bool acyclicPublisher;
86
87
    SOPC_PubSub_OnFatalError* onFatalError;
88
    SOPC_Pub_SignatureFailed* onPubSignatureFailed;
89
    SOPC_Sub_SignatureCheckFailed* onSubSignatureCheckFailed;
90
    // For the next version:
91
    // uint32_t connectionPropertiesLength: not used;
92
    // KeyValuePair *connectionProperties: not used;
93
    // ConnectionTransportDataType transportSettings: not used;
94
};
95
96
struct SOPC_DataSetMetaData
97
{
98
    // char* name;
99
    uint16_t fields_length;
100
    SOPC_FieldMetaData* fields;
101
102
    // configurationVersion
103
};
104
105
struct SOPC_PublishedDataSet
106
{
107
    SOPC_DataSetMetaData dataSetMetaData;
108
    // SOPC_PublishedDataSetSource dataSetSource;
109
    SOPC_PublishedDataSetSourceType dataSetSourceType;
110
111
    // For the next version:
112
    // char **dataSetFolder
113
    // KeyValuePair *extensionFields
114
};
115
116
typedef struct SOPC_UadpWriterGroup
117
{
118
    uint32_t version;
119
    SOPC_UadpNetworkMessageContentMask contentMask;
120
121
    // For the next version:
122
    // dataSetOrdering
123
    // samplingOffset
124
    // publishingOffset
125
126
} SOPC_UadpWriterGroup;
127
128
struct SOPC_WriterGroup
129
{
130
    SOPC_PubSubConnection* parent;
131
    uint16_t id;
132
    double publishingIntervalMs;
133
    int32_t publishingOffsetMs;
134
    SOPC_UadpWriterGroup messageSettings;
135
136
    uint8_t dataSetWriters_length;
137
    SOPC_DataSetWriter* dataSetWriters;
138
139
    SOPC_SecurityMode_Type securityMode;
140
141
    // Topic Specific to Mqtt
142
    char* mqttTopic;
143
144
    double keepAliveTimeMs;
145
146
    SOPC_Pubsub_MessageEncodingType messageEncoding;
147
148
    char* securityGroupId;
149
    SOPC_SecurityKeyServices* securityKeyServices;
150
    uint32_t securityKeyServices_length;
151
    SOPC_WriterGroup_Options options;
152
    // For the next version:
153
    // Priority
154
    // LocaleIds
155
    // transportSettings
156
};
157
158
struct SOPC_SecurityKeyServices
159
{
160
    char* endpointUrl;
161
    SOPC_SerializedCertificate* serverCertificate;
162
};
163
164
struct SOPC_DataSetWriter
165
{
166
    uint16_t id;
167
    // dataSetName in structure defined in Spec 1.4
168
    SOPC_PublishedDataSet*
169
        dataSet; /* IMPORTANT NOTE: memory management of field not managed here (see global config struct)*/
170
    SOPC_DataSetWriter_Options options;
171
    // For the next version:
172
    // name
173
    // enabled
174
    // dataSetFieldContentMask
175
    // keyFrameCount
176
    // dataSetWriterProperties
177
    // transportSettings
178
    // messageSettings
179
};
180
181
struct SOPC_ReaderGroup
182
{
183
    SOPC_SecurityMode_Type securityMode;
184
185
    SOPC_Conf_PublisherId publisherId;
186
187
    char* securityGroupId;
188
189
    SOPC_SecurityKeyServices* securityKeyServices;
190
    uint32_t securityKeyServices_length;
191
192
    uint8_t dataSetReaders_length;
193
    SOPC_DataSetReader* dataSetReaders;
194
    uint16_t groupId;
195
    uint32_t groupVersion;
196
197
    // Topic Specific to Mqtt
198
    char* mqttTopic;
199
};
200
201
struct SOPC_DataSetReader
202
{
203
    struct SOPC_ReaderGroup* group;
204
    uint16_t dataSetWriterId;
205
    SOPC_DataSetMetaData metaData;
206
    SOPC_SubscribedDataSetType targetType;
207
    double messageReceiveTimeout; /* ms */
208
209
    // These fields below are defined in Spec but not used
210
    // DataSetFieldContentMask
211
212
    // SecurityMode
213
    // SecurityGroupId
214
    // SecurityKeyServices
215
    // DataSetReaderProperties
216
    // transportSettings
217
    // messageSettings
218
};
219
220
struct SOPC_FieldTarget
221
{
222
    // numeric range format
223
    char* receiverIndexRange;
224
    SOPC_NodeId* nodeId;
225
    uint32_t attributeId;
226
    // numeric range format
227
    char* writeIndexRange;
228
229
    // override value is not managed
230
    // overrideValueHandling
231
    // overrideValue
232
};
233
234
struct SOPC_FieldMetaData
235
{
236
    // char* name;
237
    SOPC_BuiltinId builtinType;
238
    SOPC_PubSub_ArrayDimension arrDimension;
239
240
    // other field are not used
241
    // only one element. used for subscriber
242
    SOPC_FieldTarget* targetVariable;
243
    // only one element. used for publisher
244
    SOPC_PublishedVariable* publishedVariable;
245
};
246
247
static bool SOPC_PubSubConfiguration_Allocate_PubSubConnection_Array(SOPC_PubSubConfiguration* configuration,
248
                                                                     uint32_t nb,
249
                                                                     SOPC_PubSubConnection** arrayPtr,
250
                                                                     uint32_t* lengthPtr,
251
                                                                     SOPC_PubSubConnection_Type type);
252
253
static char* SOPC_PubSub_String_Copy(const char* src);
254
255
static void SOPC_PubSubConnection_Clear(SOPC_PubSubConnection* connection);
256
257
static void SOPC_PublishedDataSet_Clear(SOPC_PublishedDataSet* dataset);
258
259
static void SOPC_WriterGroup_Clear(SOPC_WriterGroup* group);
260
261
static void SOPC_SecurityKeyServices_Clear(SOPC_SecurityKeyServices* sks);
262
263
static void SOPC_ReaderGroup_Clear(SOPC_ReaderGroup* group);
264
265
static void SOPC_DataSetMetaData_Clear(SOPC_DataSetMetaData* metaData);
266
267
static void SOPC_FieldTarget_Clear(SOPC_FieldTarget* target);
268
269
static void SOPC_PublishedVariable_Clear(SOPC_PublishedVariable* variable);
270
271
static void SOPC_Conf_PublisherId_Clear(SOPC_Conf_PublisherId* pubId);
272
273
SOPC_PubSubConfiguration* SOPC_PubSubConfiguration_Create(void)
274
2
{
275
    // free in SOPC_PubSubConfiguration_Delete
276
2
    SOPC_PubSubConfiguration* configuration = SOPC_Calloc(1, sizeof(SOPC_PubSubConfiguration));
277
2
    if (NULL == configuration)
278
0
    {
279
0
        return NULL;
280
0
    }
281
2
    return configuration;
282
2
}
283
284
void SOPC_PubSubConfiguration_Delete(SOPC_PubSubConfiguration* configuration)
285
0
{
286
0
    if (NULL == configuration)
287
0
    {
288
0
        return;
289
0
    }
290
0
    for (uint32_t i = 0; i < configuration->pub_connection_length; i++)
291
0
    {
292
0
        SOPC_PubSubConnection_Clear(&(configuration->pub_connection[i]));
293
0
    }
294
0
    SOPC_Free(configuration->pub_connection);
295
0
    for (uint32_t i = 0; i < configuration->sub_connection_length; i++)
296
0
    {
297
0
        SOPC_PubSubConnection_Clear(&(configuration->sub_connection[i]));
298
0
    }
299
0
    SOPC_Free(configuration->sub_connection);
300
0
    for (uint32_t i = 0; i < configuration->publishedDataSet_length; i++)
301
0
    {
302
0
        SOPC_PublishedDataSet_Clear(&(configuration->publishedDataSet[i]));
303
0
    }
304
0
    SOPC_Free(configuration->publishedDataSet);
305
0
    SOPC_Free(configuration);
306
0
}
307
308
static bool SOPC_PubSubConfiguration_Allocate_PubSubConnection_Array(SOPC_PubSubConfiguration* configuration,
309
                                                                     uint32_t nb,
310
                                                                     SOPC_PubSubConnection** arrayPtr,
311
                                                                     uint32_t* lengthPtr,
312
                                                                     SOPC_PubSubConnection_Type type)
313
2
{
314
2
    SOPC_ASSERT(NULL != configuration && NULL != arrayPtr && NULL != lengthPtr);
315
    // free in SOPC_PubSubConfiguration_Delete
316
2
    *arrayPtr = SOPC_Calloc(nb, sizeof(SOPC_PubSubConnection));
317
2
    if (NULL == *arrayPtr)
318
0
    {
319
0
        return false;
320
0
    }
321
2
    *lengthPtr = nb;
322
4
    for (uint32_t i = 0; i < nb; i++)
323
2
    {
324
2
        (*arrayPtr)[i].type = type;
325
2
        (*arrayPtr)[i].publisherId.type = SOPC_Null_PublisherId;
326
2
    }
327
328
2
    return true;
329
2
}
330
331
bool SOPC_PubSubConfiguration_Allocate_PubConnection_Array(SOPC_PubSubConfiguration* configuration, uint32_t nb)
332
0
{
333
0
    return SOPC_PubSubConfiguration_Allocate_PubSubConnection_Array(configuration, nb, &(configuration->pub_connection),
334
0
                                                                    &(configuration->pub_connection_length),
335
0
                                                                    SOPC_PubSubConnection_Pub);
336
0
}
337
338
uint32_t SOPC_PubSubConfiguration_Nb_PubConnection(const SOPC_PubSubConfiguration* configuration)
339
0
{
340
0
    SOPC_ASSERT(NULL != configuration);
341
0
    return configuration->pub_connection_length;
342
0
}
343
344
SOPC_PubSubConnection* SOPC_PubSubConfiguration_Get_PubConnection_At(const SOPC_PubSubConfiguration* configuration,
345
                                                                     uint32_t index)
346
0
{
347
0
    SOPC_ASSERT(NULL != configuration && index < configuration->pub_connection_length);
348
0
    return &(configuration->pub_connection[index]);
349
0
}
350
351
bool SOPC_PubSubConfiguration_Allocate_SubConnection_Array(SOPC_PubSubConfiguration* configuration, uint32_t nb)
352
2
{
353
2
    return SOPC_PubSubConfiguration_Allocate_PubSubConnection_Array(configuration, nb, &(configuration->sub_connection),
354
2
                                                                    &(configuration->sub_connection_length),
355
2
                                                                    SOPC_PubSubConnection_Sub);
356
2
}
357
358
uint32_t SOPC_PubSubConfiguration_Nb_SubConnection(const SOPC_PubSubConfiguration* configuration)
359
0
{
360
0
    SOPC_ASSERT(NULL != configuration);
361
0
    return configuration->sub_connection_length;
362
0
}
363
364
SOPC_PubSubConnection* SOPC_PubSubConfiguration_Get_SubConnection_At(const SOPC_PubSubConfiguration* configuration,
365
                                                                     uint32_t index)
366
2
{
367
2
    SOPC_ASSERT(NULL != configuration && index < configuration->sub_connection_length);
368
2
    return &(configuration->sub_connection[index]);
369
2
}
370
371
bool SOPC_PubSubConfiguration_Allocate_PublishedDataSet_Array(SOPC_PubSubConfiguration* configuration, uint32_t nb)
372
0
{
373
0
    SOPC_ASSERT(NULL != configuration);
374
    // free in SOPC_PubSubConfiguration_Delete
375
0
    configuration->publishedDataSet = SOPC_Calloc(nb, sizeof(SOPC_PublishedDataSet));
376
0
    if (NULL == configuration->publishedDataSet)
377
0
    {
378
0
        return false;
379
0
    }
380
0
    configuration->publishedDataSet_length = nb;
381
0
    return true;
382
0
}
383
384
uint32_t SOPC_PubSubConfiguration_Nb_PublishedDataSet(const SOPC_PubSubConfiguration* configuration)
385
0
{
386
0
    SOPC_ASSERT(NULL != configuration);
387
0
    return configuration->publishedDataSet_length;
388
0
}
389
390
SOPC_PublishedDataSet* SOPC_PubSubConfiguration_Get_PublishedDataSet_At(const SOPC_PubSubConfiguration* configuration,
391
                                                                        uint16_t index)
392
0
{
393
0
    SOPC_ASSERT(NULL != configuration && index < configuration->publishedDataSet_length);
394
0
    return &(configuration->publishedDataSet[index]);
395
0
}
396
397
void SOPC_PubSubConnection_Set_AcyclicPublisher(SOPC_PubSubConnection* connection, bool acyclicPublisher)
398
0
{
399
0
    SOPC_ASSERT(NULL != connection);
400
0
    connection->acyclicPublisher = acyclicPublisher;
401
0
}
402
403
bool SOPC_PubSubConnection_Get_AcyclicPublisher(const SOPC_PubSubConnection* connection)
404
0
{
405
0
    SOPC_ASSERT(NULL != connection);
406
0
    return connection->acyclicPublisher;
407
0
}
408
409
static void SOPC_PubSubConnection_Clear(SOPC_PubSubConnection* connection)
410
0
{
411
0
    if (NULL != connection)
412
0
    {
413
0
        SOPC_Free(connection->name);
414
0
        SOPC_Conf_PublisherId_Clear(&connection->publisherId);
415
0
        SOPC_Free(connection->address);
416
0
        SOPC_Free(connection->interfaceName);
417
0
        SOPC_Free(connection->mqttUsername);
418
0
        SOPC_Free(connection->mqttPassword);
419
0
        SOPC_Free(connection->transportProfileUri);
420
0
        SOPC_String_Clear(&connection->publisherId.data.string);
421
0
        for (int i = 0; i < connection->writerGroups_length; i++)
422
0
        {
423
0
            SOPC_WriterGroup_Clear(&(connection->writerGroups[i]));
424
0
        }
425
0
        SOPC_Free(connection->writerGroups);
426
0
        for (int i = 0; i < connection->readerGroups_length; i++)
427
0
        {
428
0
            SOPC_ReaderGroup_Clear(&(connection->readerGroups[i]));
429
0
        }
430
0
        SOPC_Free(connection->readerGroups);
431
0
    }
432
0
}
433
434
const char* SOPC_PubSubConnection_Get_Name(const SOPC_PubSubConnection* connection)
435
0
{
436
0
    return connection->name;
437
0
}
438
439
bool SOPC_PubSubConnection_Set_Name(SOPC_PubSubConnection* connection, const char* name)
440
0
{
441
0
    SOPC_ASSERT(NULL != connection);
442
    // free in SOPC_PubSubConnection_Clear
443
0
    connection->name = SOPC_PubSub_String_Copy(name);
444
0
    return (NULL != connection->name);
445
0
}
446
447
bool SOPC_PubSubConnection_Is_Enabled(const SOPC_PubSubConnection* connection)
448
0
{
449
0
    SOPC_ASSERT(NULL != connection);
450
0
    return connection->enabled;
451
0
}
452
453
void SOPC_PubSubConnection_Set_Enabled(SOPC_PubSubConnection* connection, bool enabled)
454
0
{
455
0
    SOPC_ASSERT(NULL != connection);
456
0
    connection->enabled = enabled;
457
0
}
458
459
void SOPC_PubSubConfiguration_Set_FatalError_Callback(SOPC_PubSubConnection* connection,
460
                                                      SOPC_PubSub_OnFatalError* callback)
461
0
{
462
0
    SOPC_ASSERT(NULL != connection);
463
0
    connection->onFatalError = callback;
464
0
}
465
466
SOPC_PubSub_OnFatalError* SOPC_PubSubConfiguration_Get_FatalError_Callback(SOPC_PubSubConnection* connection)
467
0
{
468
0
    SOPC_ASSERT(NULL != connection);
469
0
    return connection->onFatalError;
470
0
}
471
472
void SOPC_PubSubConfiguration_Set_PubSignatureFailed_Callback(SOPC_PubSubConnection* connection,
473
                                                              SOPC_Pub_SignatureFailed* callback)
474
0
{
475
0
    if (connection != NULL)
476
0
    {
477
0
        connection->onPubSignatureFailed = callback;
478
0
    }
479
0
}
480
481
void SOPC_PubSubConfiguration_Set_SubSignatureCheckFailed_Callback(SOPC_PubSubConnection* connection,
482
                                                                   SOPC_Sub_SignatureCheckFailed* callback)
483
0
{
484
0
    if (connection != NULL)
485
0
    {
486
0
        connection->onSubSignatureCheckFailed = callback;
487
0
    }
488
0
}
489
490
SOPC_Pub_SignatureFailed* SOPC_PubSubConfiguration_Get_PubSignatureFailed_Callback(
491
    const SOPC_PubSubConnection* connection)
492
0
{
493
0
    if (connection != NULL)
494
0
    {
495
0
        return connection->onPubSignatureFailed;
496
0
    }
497
0
    return NULL;
498
0
}
499
500
SOPC_Sub_SignatureCheckFailed* SOPC_PubSubConfiguration_Get_SubSignatureCheckFailed_Callback(
501
    const SOPC_PubSubConnection* connection)
502
0
{
503
0
    if (connection != NULL)
504
0
    {
505
0
        return connection->onSubSignatureCheckFailed;
506
0
    }
507
0
    return NULL;
508
0
}
509
510
// PublisherId
511
512
static void SOPC_Conf_PublisherId_Clear(SOPC_Conf_PublisherId* pubId)
513
0
{
514
0
    if (NULL != pubId && SOPC_String_PublisherId == pubId->type)
515
0
    {
516
0
        SOPC_String_Clear(&pubId->data.string);
517
0
    }
518
0
}
519
520
const SOPC_Conf_PublisherId* SOPC_PubSubConnection_Get_PublisherId(const SOPC_PubSubConnection* connection)
521
0
{
522
0
    SOPC_ASSERT(NULL != connection);
523
0
    return &(connection->publisherId);
524
0
}
525
526
void SOPC_PubSubConnection_Set_PublisherId_UInteger(SOPC_PubSubConnection* connection, uint64_t id)
527
0
{
528
0
    SOPC_ASSERT(NULL != connection && SOPC_PubSubConnection_Pub == connection->type);
529
0
    connection->publisherId.type = SOPC_UInteger_PublisherId;
530
0
    connection->publisherId.data.uint = id;
531
0
}
532
533
bool SOPC_PubSubConnection_Set_PublisherId_String(SOPC_PubSubConnection* connection, const SOPC_String* id)
534
0
{
535
0
    SOPC_ASSERT(NULL != connection && NULL != id && SOPC_PubSubConnection_Pub == connection->type);
536
0
    connection->publisherId.type = SOPC_String_PublisherId;
537
0
    SOPC_String_Initialize(&connection->publisherId.data.string);
538
0
    SOPC_ReturnStatus status = SOPC_String_Copy(&connection->publisherId.data.string, id);
539
0
    return (SOPC_STATUS_OK == status);
540
0
}
541
542
const char* SOPC_PubSubConnection_Get_TransportProfileUri(const SOPC_PubSubConnection* connection)
543
0
{
544
0
    SOPC_ASSERT(NULL != connection);
545
0
    return connection->transportProfileUri;
546
0
}
547
548
bool SOPC_PubSubConnection_Set_TransportProfileUri(SOPC_PubSubConnection* connection, const char* uri)
549
0
{
550
0
    SOPC_ASSERT(NULL != connection);
551
    // free in SOPC_PubSubConnection_Clear
552
0
    connection->transportProfileUri = SOPC_PubSub_String_Copy(uri);
553
0
    return (NULL != connection->transportProfileUri);
554
0
}
555
556
const char* SOPC_PubSubConnection_Get_Address(const SOPC_PubSubConnection* connection)
557
0
{
558
0
    SOPC_ASSERT(NULL != connection);
559
0
    return connection->address;
560
0
}
561
562
bool SOPC_PubSubConnection_Set_Address(SOPC_PubSubConnection* connection, const char* address)
563
0
{
564
0
    SOPC_ASSERT(NULL != connection);
565
    // free in SOPC_PubSubConnection_Clear
566
0
    connection->address = SOPC_PubSub_String_Copy(address);
567
0
    return (NULL != connection->address);
568
0
}
569
570
const char* SOPC_PubSubConnection_Get_InterfaceName(const SOPC_PubSubConnection* connection)
571
0
{
572
0
    SOPC_ASSERT(NULL != connection);
573
0
    return connection->interfaceName;
574
0
}
575
576
bool SOPC_PubSubConnection_Set_InterfaceName(SOPC_PubSubConnection* connection, const char* interfaceName)
577
0
{
578
0
    SOPC_ASSERT(NULL != connection);
579
    // free in SOPC_PubSubConnection_Clear
580
0
    connection->interfaceName = SOPC_PubSub_String_Copy(interfaceName);
581
0
    return (NULL != connection->interfaceName);
582
0
}
583
584
const char* SOPC_PubSubConnection_Get_MqttUsername(const SOPC_PubSubConnection* connection)
585
0
{
586
0
    SOPC_ASSERT(NULL != connection);
587
0
    return connection->mqttUsername;
588
0
}
589
590
bool SOPC_PubSubConnection_Set_MqttUsername(SOPC_PubSubConnection* connection, const char* username)
591
0
{
592
0
    SOPC_ASSERT(NULL != username);
593
0
    connection->mqttUsername = SOPC_PubSub_String_Copy(username);
594
0
    return (NULL != connection->mqttUsername);
595
0
}
596
597
const char* SOPC_PubSubConnection_Get_MqttPassword(const SOPC_PubSubConnection* connection)
598
0
{
599
0
    SOPC_ASSERT(NULL != connection);
600
0
    return connection->mqttPassword;
601
0
}
602
603
bool SOPC_PubSubConnection_Set_MqttPassword(SOPC_PubSubConnection* connection, const char* password)
604
0
{
605
0
    SOPC_ASSERT(NULL != password);
606
0
    connection->mqttPassword = SOPC_PubSub_String_Copy(password);
607
0
    return (NULL != connection->mqttPassword);
608
0
}
609
610
bool SOPC_PubSubConnection_Allocate_WriterGroup_Array(SOPC_PubSubConnection* connection, uint16_t nb)
611
0
{
612
0
    SOPC_ASSERT(NULL != connection && SOPC_PubSubConnection_Pub == connection->type);
613
    // free in SOPC_PubSubConnection_Clear
614
0
    connection->writerGroups = SOPC_Calloc(nb, sizeof(SOPC_WriterGroup));
615
0
    if (NULL == connection->writerGroups)
616
0
    {
617
0
        return false;
618
0
    }
619
0
    connection->writerGroups_length = nb;
620
0
    for (int i = 0; i < nb; i++)
621
0
    {
622
0
        connection->writerGroups[i].parent = connection;
623
        // As publishingOffsetMs is optional, it shall be initialized here
624
0
        connection->writerGroups[i].publishingOffsetMs = -1;
625
0
    }
626
0
    return true;
627
0
}
628
629
uint16_t SOPC_PubSubConnection_Nb_WriterGroup(const SOPC_PubSubConnection* connection)
630
0
{
631
0
    SOPC_ASSERT(NULL != connection);
632
0
    return connection->writerGroups_length;
633
0
}
634
635
SOPC_WriterGroup* SOPC_PubSubConnection_Get_WriterGroup_At(const SOPC_PubSubConnection* connection, uint16_t index)
636
0
{
637
0
    SOPC_ASSERT(NULL != connection && index < connection->writerGroups_length);
638
0
    return &connection->writerGroups[index];
639
0
}
640
641
bool SOPC_PubSubConnection_Allocate_ReaderGroup_Array(SOPC_PubSubConnection* connection, uint16_t nb)
642
2
{
643
2
    SOPC_ASSERT(NULL != connection && SOPC_PubSubConnection_Sub == connection->type);
644
    // free in SOPC_PubSubConnection_Clear
645
2
    connection->readerGroups = SOPC_Calloc(nb, sizeof(SOPC_ReaderGroup));
646
2
    if (NULL == connection->readerGroups)
647
0
    {
648
0
        return false;
649
0
    }
650
2
    connection->readerGroups_length = nb;
651
6
    for (int i = 0; i < nb; i++)
652
4
    {
653
4
        memset(&connection->readerGroups[i], 0, sizeof(SOPC_ReaderGroup));
654
4
        connection->readerGroups[i].publisherId.type = SOPC_Null_PublisherId;
655
4
    }
656
2
    return true;
657
2
}
658
659
uint16_t SOPC_PubSubConnection_Nb_ReaderGroup(const SOPC_PubSubConnection* connection)
660
7.36k
{
661
7.36k
    SOPC_ASSERT(NULL != connection);
662
7.36k
    return connection->readerGroups_length;
663
7.36k
}
664
665
SOPC_ReaderGroup* SOPC_PubSubConnection_Get_ReaderGroup_At(const SOPC_PubSubConnection* connection, uint16_t index)
666
7.70k
{
667
7.70k
    SOPC_ASSERT(NULL != connection && index < connection->readerGroups_length);
668
7.70k
    return &connection->readerGroups[index];
669
7.70k
}
670
671
/** Reader Group **/
672
673
SOPC_SecurityMode_Type SOPC_ReaderGroup_Get_SecurityMode(const SOPC_ReaderGroup* group)
674
0
{
675
0
    SOPC_ASSERT(NULL != group);
676
0
    return group->securityMode;
677
0
}
678
679
void SOPC_ReaderGroup_Set_SecurityMode(SOPC_ReaderGroup* group, SOPC_SecurityMode_Type mode)
680
4
{
681
4
    SOPC_ASSERT(NULL != group);
682
4
    group->securityMode = mode;
683
4
}
684
685
const char* SOPC_ReaderGroup_Get_SecurityGroupId(const SOPC_ReaderGroup* group)
686
0
{
687
0
    SOPC_ASSERT(NULL != group);
688
0
    return group->securityGroupId;
689
0
}
690
691
void SOPC_ReaderGroup_Set_SecurityGroupId(SOPC_ReaderGroup* group, const char* securityGroupId)
692
0
{
693
0
    SOPC_ASSERT(NULL != group);
694
0
    if (NULL == securityGroupId)
695
0
    {
696
0
        group->securityGroupId = NULL;
697
0
    }
698
0
    else
699
0
    {
700
0
        group->securityGroupId = SOPC_PubSub_String_Copy(securityGroupId);
701
0
        SOPC_ASSERT(NULL != group->securityGroupId);
702
0
    }
703
0
}
704
705
bool SOPC_ReaderGroup_Allocate_SecurityKeyServices_Array(SOPC_ReaderGroup* group, uint32_t nb)
706
0
{
707
0
    SOPC_ASSERT(NULL != group);
708
    // free in SOPC_ReaderGroup_Clear
709
0
    group->securityKeyServices = SOPC_Calloc(nb, sizeof(SOPC_SecurityKeyServices));
710
0
    if (NULL == group->securityKeyServices)
711
0
    {
712
0
        return false;
713
0
    }
714
0
    group->securityKeyServices_length = nb;
715
0
    return true;
716
0
}
717
718
uint32_t SOPC_ReaderGroup_Nb_SecurityKeyServices(const SOPC_ReaderGroup* group)
719
0
{
720
0
    SOPC_ASSERT(NULL != group);
721
0
    return group->securityKeyServices_length;
722
0
}
723
724
SOPC_SecurityKeyServices* SOPC_ReaderGroup_Get_SecurityKeyServices_At(const SOPC_ReaderGroup* group, uint32_t index)
725
0
{
726
0
    SOPC_ASSERT(NULL != group);
727
0
    SOPC_ASSERT(index < group->securityKeyServices_length);
728
0
    SOPC_ASSERT(NULL != group->securityKeyServices);
729
0
    return &group->securityKeyServices[index];
730
0
}
731
732
bool SOPC_ReaderGroup_Allocate_DataSetReader_Array(SOPC_ReaderGroup* group, uint8_t nb)
733
4
{
734
4
    SOPC_ASSERT(NULL != group);
735
    // free in SOPC_ReaderGroup_Clear
736
4
    group->dataSetReaders = SOPC_Calloc(nb, sizeof(SOPC_DataSetReader));
737
4
    if (NULL == group->dataSetReaders)
738
0
    {
739
0
        return false;
740
0
    }
741
8
    for (size_t i = 0; i < nb; i++)
742
4
    {
743
4
        group->dataSetReaders[i].group = group;
744
4
    }
745
4
    group->dataSetReaders_length = nb;
746
4
    return true;
747
4
}
748
749
uint8_t SOPC_ReaderGroup_Nb_DataSetReader(const SOPC_ReaderGroup* group)
750
10.8k
{
751
10.8k
    SOPC_ASSERT(NULL != group);
752
10.8k
    return group->dataSetReaders_length;
753
10.8k
}
754
755
SOPC_DataSetReader* SOPC_ReaderGroup_Get_DataSetReader_At(const SOPC_ReaderGroup* group, uint8_t index)
756
10.8k
{
757
10.8k
    SOPC_ASSERT(NULL != group && index < group->dataSetReaders_length);
758
10.8k
    return &group->dataSetReaders[index];
759
10.8k
}
760
761
uint16_t SOPC_ReaderGroup_Get_GroupId(const SOPC_ReaderGroup* group)
762
7.25k
{
763
7.25k
    SOPC_ASSERT(NULL != group);
764
7.25k
    return group->groupId;
765
7.25k
}
766
767
void SOPC_ReaderGroup_Set_GroupId(SOPC_ReaderGroup* group, uint16_t id)
768
4
{
769
4
    SOPC_ASSERT(NULL != group);
770
4
    group->groupId = id;
771
4
}
772
773
uint32_t SOPC_ReaderGroup_Get_GroupVersion(const SOPC_ReaderGroup* group)
774
69
{
775
69
    SOPC_ASSERT(NULL != group);
776
69
    return group->groupVersion;
777
69
}
778
779
void SOPC_ReaderGroup_Set_GroupVersion(SOPC_ReaderGroup* group, uint32_t version)
780
4
{
781
4
    SOPC_ASSERT(NULL != group);
782
4
    group->groupVersion = version;
783
4
}
784
785
const SOPC_Conf_PublisherId* SOPC_ReaderGroup_Get_PublisherId(const SOPC_ReaderGroup* group)
786
577
{
787
577
    SOPC_ASSERT(NULL != group);
788
577
    return &(group->publisherId);
789
577
}
790
791
void SOPC_ReaderGroup_Set_PublisherId_UInteger(SOPC_ReaderGroup* group, uint64_t id)
792
2
{
793
2
    SOPC_ASSERT(NULL != group);
794
2
    group->publisherId.type = SOPC_UInteger_PublisherId;
795
2
    group->publisherId.data.uint = id;
796
2
}
797
798
bool SOPC_ReaderGroup_Set_PublisherId_String(SOPC_ReaderGroup* group, const SOPC_String* id)
799
0
{
800
0
    SOPC_ASSERT(NULL != group && NULL != id);
801
0
    group->publisherId.type = SOPC_String_PublisherId;
802
0
    SOPC_String_Initialize(&group->publisherId.data.string);
803
0
    SOPC_ReturnStatus status = SOPC_String_Copy(&group->publisherId.data.string, id);
804
0
    return (SOPC_STATUS_OK == status);
805
0
}
806
807
/** DataSetReader **/
808
809
static void SOPC_DataSetMetaData_Clear(SOPC_DataSetMetaData* metaData)
810
0
{
811
0
    for (int i = 0; i < metaData->fields_length; i++)
812
0
    {
813
0
        SOPC_FieldTarget_Clear(metaData->fields[i].targetVariable);
814
0
        SOPC_Free(metaData->fields[i].targetVariable);
815
0
        SOPC_PublishedVariable_Clear(metaData->fields[i].publishedVariable);
816
0
        SOPC_Free(metaData->fields[i].publishedVariable);
817
0
        SOPC_Free(metaData->fields[i].arrDimension.arrayDimensions);
818
0
    }
819
0
    metaData->fields_length = 0;
820
0
    SOPC_Free(metaData->fields);
821
0
    metaData->fields = NULL;
822
0
}
823
824
SOPC_ReaderGroup* SOPC_DataSetReader_Get_ReaderGroup(const SOPC_DataSetReader* reader)
825
0
{
826
0
    SOPC_ASSERT(NULL != reader);
827
0
    return reader->group;
828
0
}
829
830
uint16_t SOPC_DataSetReader_Get_DataSetWriterId(const SOPC_DataSetReader* reader)
831
10.8k
{
832
10.8k
    SOPC_ASSERT(NULL != reader);
833
10.8k
    return reader->dataSetWriterId;
834
10.8k
}
835
836
void SOPC_DataSetReader_Set_DataSetWriterId(SOPC_DataSetReader* reader, uint16_t id)
837
4
{
838
4
    SOPC_ASSERT(NULL != reader && id > 0);
839
840
4
    reader->dataSetWriterId = id;
841
4
}
842
843
const char* SOPC_ReaderGroup_Get_MqttTopic(const SOPC_ReaderGroup* reader)
844
0
{
845
0
    SOPC_ASSERT(NULL != reader);
846
0
    return reader->mqttTopic;
847
0
}
848
849
void SOPC_ReaderGroup_Set_MqttTopic(SOPC_ReaderGroup* reader, const char* topic)
850
0
{
851
0
    SOPC_ASSERT(NULL != reader);
852
0
    if (NULL != reader->mqttTopic)
853
0
    {
854
0
        SOPC_Free(reader->mqttTopic);
855
0
    }
856
0
    if (NULL == topic)
857
0
    {
858
0
        reader->mqttTopic = NULL;
859
0
    }
860
0
    else
861
0
    {
862
0
        reader->mqttTopic = SOPC_PubSub_String_Copy(topic);
863
0
        SOPC_ASSERT(NULL != reader->mqttTopic);
864
0
    }
865
0
}
866
867
char* SOPC_Allocate_MQTT_DefaultTopic(const SOPC_Conf_PublisherId* publisherId, uint16_t groupId)
868
0
{
869
0
    SOPC_ASSERT(NULL != publisherId);
870
0
    char* defaultTopic = NULL;
871
0
    int res = 0;
872
0
    static const size_t length_max_default_topic =
873
0
        SOPC_MAX_LENGTH_UINT64_TO_STRING + 1 + SOPC_MAX_LENGTH_UINT16_TO_STRING;
874
875
0
    if (SOPC_UInteger_PublisherId == publisherId->type)
876
0
    {
877
0
        defaultTopic =
878
0
            SOPC_Calloc(length_max_default_topic + 1, sizeof(char)); // + 1 to store the terminating null character
879
0
        SOPC_ASSERT(NULL != defaultTopic);
880
0
        res = snprintf(defaultTopic, length_max_default_topic + 1, "%" PRIu64 ".%" PRIu16, publisherId->data.uint,
881
0
                       groupId);
882
0
    }
883
0
    SOPC_ASSERT(SOPC_String_PublisherId != publisherId->type); // Not handled in current version
884
0
    SOPC_ASSERT(res > 0 && res < (int) length_max_default_topic + 1);
885
0
    return defaultTopic;
886
0
}
887
888
bool SOPC_DataSetReader_Allocate_FieldMetaData_Array(SOPC_DataSetReader* reader,
889
                                                     SOPC_SubscribedDataSetType type,
890
                                                     uint16_t nb)
891
4
{
892
4
    SOPC_ASSERT(NULL != reader);
893
4
    reader->targetType = type;
894
    // free in SOPC_DataSetMetaData_Clear
895
4
    reader->metaData.fields = SOPC_Calloc(nb, sizeof(SOPC_FieldMetaData));
896
4
    if (NULL == reader->metaData.fields)
897
0
    {
898
0
        return false;
899
0
    }
900
4
    reader->metaData.fields_length = nb;
901
22
    for (int i = 0; i < nb; i++)
902
18
    {
903
        // free in SOPC_DataSetMetaData_Clear
904
18
        SOPC_FieldTarget* target = SOPC_Calloc(1, sizeof(SOPC_FieldTarget));
905
18
        if (NULL == target)
906
0
        {
907
0
            SOPC_DataSetMetaData_Clear(&(reader->metaData));
908
0
            return false;
909
0
        }
910
18
        reader->metaData.fields[i].targetVariable = target;
911
18
    }
912
4
    return true;
913
4
}
914
915
uint16_t SOPC_DataSetReader_Nb_FieldMetaData(const SOPC_DataSetReader* reader)
916
410
{
917
410
    SOPC_ASSERT(NULL != reader);
918
410
    return reader->metaData.fields_length;
919
410
}
920
921
SOPC_FieldMetaData* SOPC_DataSetReader_Get_FieldMetaData_At(const SOPC_DataSetReader* reader, uint16_t index)
922
689
{
923
689
    SOPC_ASSERT(NULL != reader);
924
689
    SOPC_ASSERT(index < reader->metaData.fields_length);
925
689
    return &(reader->metaData.fields[index]);
926
689
}
927
928
SOPC_SubscribedDataSetType SOPC_DataSetReader_Get_DataSet_TargetType(const SOPC_DataSetReader* reader)
929
0
{
930
0
    SOPC_ASSERT(NULL != reader);
931
0
    return reader->targetType;
932
0
}
933
934
double SOPC_DataSetReader_Get_ReceiveTimeout(const SOPC_DataSetReader* reader)
935
0
{
936
0
    SOPC_ASSERT(NULL != reader);
937
0
    return reader->messageReceiveTimeout;
938
0
}
939
940
void SOPC_DataSetReader_Set_ReceiveTimeout(SOPC_DataSetReader* reader, double timeout_ms)
941
0
{
942
0
    SOPC_ASSERT(NULL != reader);
943
0
    reader->messageReceiveTimeout = timeout_ms;
944
0
}
945
946
/** SOPC_FieldTarget **/
947
948
const char* SOPC_FieldTarget_Get_SourceIndexRange(const SOPC_FieldTarget* target)
949
0
{
950
0
    return target->receiverIndexRange;
951
0
}
952
953
bool SOPC_FieldTarget_Set_SourceIndexRange(SOPC_FieldTarget* target, const char* sourceIndexRange)
954
0
{
955
0
    SOPC_ASSERT(NULL != target && NULL != sourceIndexRange);
956
    // free in SOPC_FieldTarget_Clear
957
0
    target->receiverIndexRange = SOPC_PubSub_String_Copy(sourceIndexRange);
958
0
    return (NULL != target->receiverIndexRange);
959
0
}
960
961
const SOPC_NodeId* SOPC_FieldTarget_Get_NodeId(const SOPC_FieldTarget* target)
962
205
{
963
205
    SOPC_ASSERT(NULL != target);
964
205
    return target->nodeId;
965
205
}
966
967
void SOPC_FieldTarget_Set_NodeId(SOPC_FieldTarget* target, SOPC_NodeId* nodeId)
968
0
{
969
0
    SOPC_ASSERT(NULL != target && NULL != nodeId);
970
    // free in SOPC_FieldTarget_Clear
971
0
    target->nodeId = nodeId;
972
0
}
973
974
uint32_t SOPC_FieldTarget_Get_AttributeId(const SOPC_FieldTarget* target)
975
0
{
976
0
    SOPC_ASSERT(NULL != target);
977
0
    return target->attributeId;
978
0
}
979
980
void SOPC_FieldTarget_Set_AttributeId(SOPC_FieldTarget* target, uint32_t attributeId)
981
0
{
982
0
    SOPC_ASSERT(NULL != target);
983
0
    target->attributeId = attributeId;
984
0
}
985
986
const char* SOPC_FieldTarget_Get_TargetIndexRange(const SOPC_FieldTarget* target)
987
0
{
988
0
    return target->writeIndexRange;
989
0
}
990
991
bool SOPC_FieldTarget_Set_TargetIndexRange(SOPC_FieldTarget* target, const char* targetIndexRange)
992
0
{
993
0
    SOPC_ASSERT(NULL != target && NULL != targetIndexRange);
994
    // free in SOPC_FieldTarget_Clear
995
0
    target->writeIndexRange = SOPC_PubSub_String_Copy(targetIndexRange);
996
0
    return (NULL != target->writeIndexRange);
997
0
}
998
999
/** Writer Group **/
1000
const SOPC_PubSubConnection* SOPC_WriterGroup_Get_Connection(const SOPC_WriterGroup* group)
1001
0
{
1002
0
    SOPC_ASSERT(NULL != group);
1003
0
    return group->parent;
1004
0
}
1005
1006
const SOPC_WriterGroup_Options* SOPC_WriterGroup_Get_Options(const SOPC_WriterGroup* group)
1007
0
{
1008
0
    SOPC_ASSERT(NULL != group);
1009
0
    return &group->options;
1010
0
}
1011
1012
void SOPC_WriterGroup_Set_Options(SOPC_WriterGroup* group, const SOPC_WriterGroup_Options* options)
1013
0
{
1014
0
    SOPC_ASSERT(NULL != group);
1015
0
    group->options = *options;
1016
0
}
1017
1018
uint16_t SOPC_WriterGroup_Get_Id(const SOPC_WriterGroup* group)
1019
0
{
1020
0
    SOPC_ASSERT(NULL != group);
1021
0
    return group->id;
1022
0
}
1023
1024
void SOPC_WriterGroup_Set_Id(SOPC_WriterGroup* group, uint16_t id)
1025
0
{
1026
0
    SOPC_ASSERT(NULL != group);
1027
0
    group->id = id;
1028
0
}
1029
1030
uint32_t SOPC_WriterGroup_Get_Version(const SOPC_WriterGroup* group)
1031
0
{
1032
0
    SOPC_ASSERT(NULL != group);
1033
0
    return group->messageSettings.version;
1034
0
}
1035
1036
void SOPC_WriterGroup_Set_Version(SOPC_WriterGroup* group, uint32_t version)
1037
0
{
1038
0
    SOPC_ASSERT(NULL != group);
1039
0
    group->messageSettings.version = version;
1040
0
}
1041
1042
double SOPC_WriterGroup_Get_PublishingInterval(const SOPC_WriterGroup* group)
1043
0
{
1044
0
    SOPC_ASSERT(NULL != group);
1045
0
    return group->publishingIntervalMs;
1046
0
}
1047
1048
int32_t SOPC_WriterGroup_Get_PublishingOffset(const SOPC_WriterGroup* group)
1049
0
{
1050
0
    SOPC_ASSERT(NULL != group);
1051
0
    return group->publishingOffsetMs;
1052
0
}
1053
1054
void SOPC_WriterGroup_Set_PublishingInterval(SOPC_WriterGroup* group, double interval_ms)
1055
0
{
1056
0
    SOPC_ASSERT(NULL != group);
1057
0
    group->publishingIntervalMs = interval_ms;
1058
0
}
1059
1060
void SOPC_WriterGroup_Set_PublishingOffset(SOPC_WriterGroup* group, int32_t offset_ms)
1061
0
{
1062
0
    SOPC_ASSERT(NULL != group);
1063
0
    group->publishingOffsetMs = offset_ms;
1064
0
}
1065
1066
SOPC_UadpNetworkMessageContentMask SOPC_WriterGroup_Get_NetworkMessageContentMask(const SOPC_WriterGroup* group)
1067
0
{
1068
0
    SOPC_ASSERT(NULL != group);
1069
0
    return group->messageSettings.contentMask;
1070
0
}
1071
1072
void SOPC_WriterGroup_Set_NetworkMessageContentMask(SOPC_WriterGroup* group,
1073
                                                    SOPC_UadpNetworkMessageContentMask contentMask)
1074
0
{
1075
0
    SOPC_ASSERT(NULL != group);
1076
0
    group->messageSettings.contentMask = contentMask;
1077
0
}
1078
1079
SOPC_SecurityMode_Type SOPC_WriterGroup_Get_SecurityMode(const SOPC_WriterGroup* group)
1080
0
{
1081
0
    SOPC_ASSERT(NULL != group);
1082
0
    return group->securityMode;
1083
0
}
1084
1085
void SOPC_WriterGroup_Set_SecurityMode(SOPC_WriterGroup* group, SOPC_SecurityMode_Type mode)
1086
0
{
1087
0
    SOPC_ASSERT(NULL != group);
1088
0
    group->securityMode = mode;
1089
0
}
1090
1091
const char* SOPC_WriterGroup_Get_SecurityGroupId(const SOPC_WriterGroup* group)
1092
0
{
1093
0
    SOPC_ASSERT(NULL != group);
1094
0
    return group->securityGroupId;
1095
0
}
1096
1097
void SOPC_WriterGroup_Set_SecurityGroupId(SOPC_WriterGroup* group, const char* securityGroupId)
1098
0
{
1099
0
    SOPC_ASSERT(NULL != group);
1100
0
    if (NULL == securityGroupId)
1101
0
    {
1102
0
        group->securityGroupId = NULL;
1103
0
    }
1104
0
    else
1105
0
    {
1106
0
        group->securityGroupId = SOPC_PubSub_String_Copy(securityGroupId);
1107
0
        SOPC_ASSERT(NULL != group->securityGroupId);
1108
0
    }
1109
0
}
1110
1111
bool SOPC_WriterGroup_Allocate_SecurityKeyServices_Array(SOPC_WriterGroup* group, uint32_t nb)
1112
0
{
1113
0
    SOPC_ASSERT(NULL != group);
1114
    // free in SOPC_WriterGroup_Clear
1115
0
    group->securityKeyServices = SOPC_Calloc(nb, sizeof(SOPC_SecurityKeyServices));
1116
0
    if (NULL == group->securityKeyServices)
1117
0
    {
1118
0
        return false;
1119
0
    }
1120
0
    group->securityKeyServices_length = nb;
1121
0
    return true;
1122
0
}
1123
1124
uint32_t SOPC_WriterGroup_Nb_SecurityKeyServices(const SOPC_WriterGroup* group)
1125
0
{
1126
0
    SOPC_ASSERT(NULL != group);
1127
0
    return group->securityKeyServices_length;
1128
0
}
1129
1130
SOPC_SecurityKeyServices* SOPC_WriterGroup_Get_SecurityKeyServices_At(const SOPC_WriterGroup* group, uint32_t index)
1131
0
{
1132
0
    SOPC_ASSERT(NULL != group);
1133
0
    SOPC_ASSERT(index < group->securityKeyServices_length);
1134
0
    SOPC_ASSERT(NULL != group->securityKeyServices);
1135
0
    return &group->securityKeyServices[index];
1136
0
}
1137
1138
/** SecurityKeyServices **/
1139
1140
const char* SOPC_SecurityKeyServices_Get_EndpointUrl(const SOPC_SecurityKeyServices* sks)
1141
0
{
1142
0
    SOPC_ASSERT(NULL != sks);
1143
0
    return sks->endpointUrl;
1144
0
}
1145
1146
bool SOPC_SecurityKeyServices_Set_EndpointUrl(SOPC_SecurityKeyServices* sks, const char* uri)
1147
0
{
1148
0
    SOPC_ASSERT(NULL != sks);
1149
0
    sks->endpointUrl = SOPC_PubSub_String_Copy(uri);
1150
0
    return (NULL != sks->endpointUrl);
1151
0
}
1152
1153
SOPC_SerializedCertificate* SOPC_SecurityKeyServices_Get_ServerCertificate(const SOPC_SecurityKeyServices* sks)
1154
0
{
1155
0
    SOPC_ASSERT(NULL != sks);
1156
0
    return sks->serverCertificate;
1157
0
}
1158
1159
bool SOPC_SecurityKeyServices_Set_ServerCertificate(SOPC_SecurityKeyServices* sks,
1160
                                                    SOPC_SerializedCertificate* serverCertificate)
1161
0
{
1162
0
    SOPC_ASSERT(NULL != sks);
1163
0
    sks->serverCertificate = serverCertificate;
1164
0
    return (NULL != sks->serverCertificate);
1165
0
}
1166
1167
bool SOPC_WriterGroup_Allocate_DataSetWriter_Array(SOPC_WriterGroup* group, uint8_t nb)
1168
0
{
1169
0
    SOPC_ASSERT(NULL != group);
1170
    // free in SOPC_WriterGroup_Clear
1171
0
    group->dataSetWriters = SOPC_Calloc(nb, sizeof(SOPC_DataSetWriter));
1172
0
    if (NULL == group->dataSetWriters)
1173
0
    {
1174
0
        return false;
1175
0
    }
1176
0
    group->dataSetWriters_length = nb;
1177
0
    return true;
1178
0
}
1179
1180
uint8_t SOPC_WriterGroup_Nb_DataSetWriter(const SOPC_WriterGroup* group)
1181
0
{
1182
0
    SOPC_ASSERT(NULL != group);
1183
0
    return group->dataSetWriters_length;
1184
0
}
1185
1186
SOPC_DataSetWriter* SOPC_WriterGroup_Get_DataSetWriter_At(const SOPC_WriterGroup* group, uint8_t index)
1187
0
{
1188
0
    SOPC_ASSERT(NULL != group && index < group->dataSetWriters_length);
1189
0
    return &group->dataSetWriters[index];
1190
0
}
1191
1192
const char* SOPC_WriterGroup_Get_MqttTopic(const SOPC_WriterGroup* writer)
1193
0
{
1194
0
    SOPC_ASSERT(NULL != writer);
1195
0
    return writer->mqttTopic;
1196
0
}
1197
1198
void SOPC_WriterGroup_Set_MqttTopic(SOPC_WriterGroup* writer, const char* topic)
1199
0
{
1200
0
    SOPC_ASSERT(NULL != writer);
1201
0
    if (NULL != writer->mqttTopic)
1202
0
    {
1203
0
        SOPC_Free(writer->mqttTopic);
1204
0
    }
1205
0
    if (NULL == topic)
1206
0
    {
1207
0
        writer->mqttTopic = NULL;
1208
0
    }
1209
0
    else
1210
0
    {
1211
0
        writer->mqttTopic = SOPC_PubSub_String_Copy(topic);
1212
0
        SOPC_ASSERT(NULL != writer->mqttTopic);
1213
0
    }
1214
0
}
1215
1216
/* Expected only for acyclic publisher */
1217
double SOPC_WriterGroup_Get_KeepAlive(const SOPC_WriterGroup* group)
1218
0
{
1219
0
    SOPC_ASSERT(NULL != group);
1220
0
    return group->keepAliveTimeMs;
1221
0
}
1222
void SOPC_WriterGroup_Set_KeepAlive(SOPC_WriterGroup* group, double keepAlive_ms)
1223
0
{
1224
0
    SOPC_ASSERT(NULL != group);
1225
0
    group->keepAliveTimeMs = keepAlive_ms;
1226
0
}
1227
1228
SOPC_Pubsub_MessageEncodingType SOPC_WriterGroup_Get_Encoding(const SOPC_WriterGroup* group)
1229
0
{
1230
0
    SOPC_ASSERT(NULL != group);
1231
0
    return group->messageEncoding;
1232
0
}
1233
1234
void SOPC_WriterGroup_Set_Encoding(SOPC_WriterGroup* group, SOPC_Pubsub_MessageEncodingType messageEncoding)
1235
0
{
1236
0
    SOPC_ASSERT(NULL != group);
1237
0
    group->messageEncoding = messageEncoding;
1238
0
}
1239
1240
/** DataSetWriter **/
1241
uint16_t SOPC_DataSetWriter_Get_Id(const SOPC_DataSetWriter* writer)
1242
0
{
1243
0
    SOPC_ASSERT(NULL != writer);
1244
0
    return writer->id;
1245
0
}
1246
1247
void SOPC_DataSetWriter_Set_Id(SOPC_DataSetWriter* writer, uint16_t id)
1248
0
{
1249
0
    SOPC_ASSERT(NULL != writer);
1250
0
    writer->id = id;
1251
0
}
1252
1253
const SOPC_DataSetWriter_Options* SOPC_DataSetWriter_Get_Options(const SOPC_DataSetWriter* writer)
1254
0
{
1255
0
    SOPC_ASSERT(NULL != writer);
1256
0
    return &writer->options;
1257
0
}
1258
1259
void SOPC_DataSetWriter_Set_Options(SOPC_DataSetWriter* writer, const SOPC_DataSetWriter_Options* options)
1260
0
{
1261
0
    SOPC_ASSERT(NULL != writer && NULL != options);
1262
0
    writer->options = *options;
1263
0
}
1264
1265
void SOPC_DataSetWriter_Set_DataSet(SOPC_DataSetWriter* writer, SOPC_PublishedDataSet* dataset)
1266
0
{
1267
0
    SOPC_ASSERT(NULL != writer);
1268
0
    writer->dataSet = dataset;
1269
0
}
1270
1271
const SOPC_PublishedDataSet* SOPC_DataSetWriter_Get_DataSet(const SOPC_DataSetWriter* writer)
1272
0
{
1273
0
    SOPC_ASSERT(NULL != writer && NULL != writer->dataSet);
1274
0
    return writer->dataSet;
1275
0
}
1276
1277
/* SOPC_FieldMetaData */
1278
1279
SOPC_FieldTarget* SOPC_FieldMetaData_Get_TargetVariable(const SOPC_FieldMetaData* fieldMetaData)
1280
205
{
1281
205
    SOPC_ASSERT(NULL != fieldMetaData);
1282
205
    return fieldMetaData->targetVariable;
1283
205
}
1284
1285
SOPC_PublishedVariable* SOPC_FieldMetaData_Get_PublishedVariable(const SOPC_FieldMetaData* fieldMetaData)
1286
0
{
1287
0
    SOPC_ASSERT(NULL != fieldMetaData);
1288
0
    return fieldMetaData->publishedVariable;
1289
0
}
1290
1291
int32_t SOPC_FieldMetaData_Get_ValueRank(const SOPC_FieldMetaData* metadata)
1292
14
{
1293
14
    SOPC_ASSERT(NULL != metadata);
1294
14
    return metadata->arrDimension.valueRank;
1295
14
}
1296
1297
SOPC_BuiltinId SOPC_FieldMetaData_Get_BuiltinType(const SOPC_FieldMetaData* metadata)
1298
466
{
1299
466
    SOPC_ASSERT(NULL != metadata);
1300
466
    return metadata->builtinType;
1301
466
}
1302
1303
void SOPC_FieldMetaData_Set_BuiltinType(SOPC_FieldMetaData* metadata, SOPC_BuiltinId builtinType)
1304
18
{
1305
18
    SOPC_ASSERT(NULL != metadata);
1306
18
    metadata->builtinType = builtinType;
1307
18
}
1308
1309
const SOPC_PubSub_ArrayDimension* SOPC_FieldMetaData_Get_ArrayDimension(const SOPC_FieldMetaData* metadata)
1310
11
{
1311
11
    SOPC_ASSERT(NULL != metadata);
1312
11
    return &metadata->arrDimension;
1313
11
}
1314
1315
bool SOPC_FieldMetaDeta_SetCopy_ArrayDimension(SOPC_FieldMetaData* metadata,
1316
                                               const SOPC_PubSub_ArrayDimension* arrayDimensions)
1317
0
{
1318
0
    SOPC_ASSERT(NULL != metadata);
1319
0
    SOPC_ASSERT(NULL != arrayDimensions);
1320
0
    bool res = true;
1321
0
    if (NULL != metadata->arrDimension.arrayDimensions)
1322
0
    {
1323
0
        SOPC_Free(metadata->arrDimension.arrayDimensions);
1324
0
    }
1325
0
    metadata->arrDimension.arrayDimensions = NULL;
1326
0
    if (arrayDimensions->valueRank > 0)
1327
0
    {
1328
0
        metadata->arrDimension.arrayDimensions = SOPC_Calloc((size_t) arrayDimensions->valueRank, sizeof(uint32_t));
1329
0
        if (NULL != metadata->arrDimension.arrayDimensions)
1330
0
        {
1331
0
            memcpy(metadata->arrDimension.arrayDimensions, arrayDimensions->arrayDimensions,
1332
0
                   sizeof(*metadata->arrDimension.arrayDimensions) * (size_t) arrayDimensions->valueRank);
1333
0
        }
1334
0
        else
1335
0
        {
1336
0
            res = false;
1337
0
        }
1338
0
    }
1339
0
    if (res)
1340
0
    {
1341
0
        metadata->arrDimension.valueRank = arrayDimensions->valueRank;
1342
0
    }
1343
0
    return res;
1344
0
}
1345
1346
void SOPC_FieldMetaData_ArrayDimension_Move(SOPC_FieldMetaData* metadata, SOPC_PubSub_ArrayDimension* arrayDimension)
1347
18
{
1348
18
    SOPC_ASSERT(NULL != metadata);
1349
18
    metadata->arrDimension = *arrayDimension;
1350
18
}
1351
1352
/* SOPC_PublishedDataSet */
1353
1354
bool SOPC_PublishedDataSet_Init(SOPC_PublishedDataSet* dataset, SOPC_PublishedDataSetSourceType type, uint16_t nbFields)
1355
0
{
1356
0
    SOPC_ASSERT(NULL != dataset);
1357
0
    dataset->dataSetSourceType = type;
1358
    // free in SOPC_DataSetMetaData_Clear
1359
0
    dataset->dataSetMetaData.fields = SOPC_Calloc(nbFields, sizeof(SOPC_FieldMetaData));
1360
0
    if (NULL == dataset->dataSetMetaData.fields)
1361
0
    {
1362
0
        return false;
1363
0
    }
1364
0
    dataset->dataSetMetaData.fields_length = nbFields;
1365
0
    for (int i = 0; i < nbFields; i++)
1366
0
    {
1367
        // free in SOPC_DataSetMetaData_Clear
1368
0
        SOPC_PublishedVariable* variable = SOPC_Calloc(1, sizeof(SOPC_PublishedVariable));
1369
0
        if (NULL == variable)
1370
0
        {
1371
0
            SOPC_DataSetMetaData_Clear(&(dataset->dataSetMetaData));
1372
0
            return false;
1373
0
        }
1374
0
        dataset->dataSetMetaData.fields[i].publishedVariable = variable;
1375
0
    }
1376
0
    return true;
1377
1378
    ////dataset->dataSetSource.type = type;
1379
    // dataset->dataSetSource.source.dataItems.length = nbFields;
1380
    // dataset->dataSetSource.source.dataItems.publishedData = SOPC_Calloc(nbFields, sizeof(SOPC_PublishedVariable));
1381
0
}
1382
1383
static void SOPC_PublishedDataSet_Clear(SOPC_PublishedDataSet* dataset)
1384
0
{
1385
0
    if (NULL == dataset)
1386
0
    {
1387
0
        return;
1388
0
    }
1389
1390
0
    SOPC_DataSetMetaData_Clear(&(dataset->dataSetMetaData));
1391
    // SOPC_Free(dataset->dataSetSource.source.dataItems.publishedData);
1392
0
}
1393
1394
uint16_t SOPC_PublishedDataSet_Nb_FieldMetaData(const SOPC_PublishedDataSet* dataset)
1395
0
{
1396
0
    SOPC_ASSERT(NULL != dataset);
1397
0
    return dataset->dataSetMetaData.fields_length;
1398
0
}
1399
1400
SOPC_FieldMetaData* SOPC_PublishedDataSet_Get_FieldMetaData_At(const SOPC_PublishedDataSet* dataset, uint16_t index)
1401
0
{
1402
0
    SOPC_ASSERT(NULL != dataset);
1403
0
    SOPC_ASSERT(index < dataset->dataSetMetaData.fields_length);
1404
0
    return &(dataset->dataSetMetaData.fields[index]);
1405
0
}
1406
1407
SOPC_PublishedDataSetSourceType SOPC_PublishedDataSet_Get_DataSet_SourceType(const SOPC_PublishedDataSet* dataset)
1408
0
{
1409
0
    SOPC_ASSERT(NULL != dataset);
1410
0
    return dataset->dataSetSourceType;
1411
0
}
1412
1413
/** SOPC_PublishedVariable **/
1414
1415
const SOPC_NodeId* SOPC_PublishedVariable_Get_NodeId(const SOPC_PublishedVariable* variable)
1416
0
{
1417
0
    SOPC_ASSERT(NULL != variable);
1418
0
    return variable->nodeId;
1419
0
}
1420
1421
void SOPC_PublishedVariable_Set_NodeId(SOPC_PublishedVariable* variable, SOPC_NodeId* nodeId)
1422
0
{
1423
0
    SOPC_ASSERT(NULL != variable && NULL != nodeId);
1424
    // free in SOPC_PublishedVariable_Clear
1425
0
    variable->nodeId = nodeId;
1426
0
}
1427
1428
uint32_t SOPC_PublishedVariable_Get_AttributeId(const SOPC_PublishedVariable* variable)
1429
0
{
1430
0
    SOPC_ASSERT(NULL != variable);
1431
0
    return variable->attributeId;
1432
0
}
1433
1434
void SOPC_PublishedVariable_Set_AttributeId(SOPC_PublishedVariable* variable, uint32_t attributeId)
1435
0
{
1436
0
    SOPC_ASSERT(NULL != variable);
1437
0
    variable->attributeId = attributeId;
1438
0
}
1439
1440
const char* SOPC_PublishedVariable_Get_IndexRange(const SOPC_PublishedVariable* variable)
1441
0
{
1442
0
    return variable->indexRange;
1443
0
}
1444
1445
bool SOPC_PublishedVariable_Set_IndexRange(SOPC_PublishedVariable* variable, const char* indexRange)
1446
0
{
1447
0
    SOPC_ASSERT(NULL != variable && NULL != indexRange);
1448
    // free in SOPC_FieldTarget_Clear
1449
0
    variable->indexRange = SOPC_PubSub_String_Copy(indexRange);
1450
0
    return (NULL != variable->indexRange);
1451
0
}
1452
1453
/* Private */
1454
1455
static char* SOPC_PubSub_String_Copy(const char* src)
1456
0
{
1457
0
    SOPC_ASSERT(NULL != src);
1458
0
    char* dst = SOPC_Malloc((strlen(src) + 1) * sizeof(char));
1459
0
    if (NULL != dst)
1460
0
    {
1461
0
        strcpy(dst, src);
1462
0
    }
1463
0
    return dst;
1464
0
}
1465
1466
static void SOPC_WriterGroup_Clear(SOPC_WriterGroup* group)
1467
0
{
1468
0
    if (NULL != group)
1469
0
    {
1470
0
        SOPC_Free(group->securityGroupId);
1471
        // securityKeyServices_length /= 0 => securityKeyServices /= NULL
1472
0
        SOPC_ASSERT(0 == group->securityKeyServices_length || NULL != group->securityKeyServices);
1473
0
        for (uint32_t i = 0; i < group->securityKeyServices_length; i++)
1474
0
        {
1475
0
            SOPC_SecurityKeyServices_Clear(&group->securityKeyServices[i]);
1476
0
        }
1477
0
        SOPC_Free(group->securityKeyServices);
1478
0
        group->securityKeyServices = NULL;
1479
0
        group->securityKeyServices_length = 0;
1480
0
        group->dataSetWriters_length = 0;
1481
        /* IMPORTANT NOTE: No memory management to do in dataSetWriter(s), publishedDataSet managed in config struct
1482
         * => no need to iterate on array */
1483
0
        SOPC_Free(group->dataSetWriters);
1484
0
        SOPC_Free(group->mqttTopic);
1485
0
        group->dataSetWriters = NULL;
1486
0
        group->mqttTopic = NULL;
1487
0
    }
1488
0
}
1489
1490
static void SOPC_SecurityKeyServices_Clear(SOPC_SecurityKeyServices* sks)
1491
0
{
1492
0
    if (NULL == sks)
1493
0
    {
1494
0
        return;
1495
0
    }
1496
1497
0
    SOPC_Free(sks->endpointUrl);
1498
0
    sks->endpointUrl = NULL;
1499
0
    SOPC_KeyManager_SerializedCertificate_Delete(sks->serverCertificate);
1500
0
    sks->serverCertificate = NULL;
1501
0
}
1502
1503
static void SOPC_ReaderGroup_Clear(SOPC_ReaderGroup* group)
1504
0
{
1505
0
    if (NULL != group)
1506
0
    {
1507
0
        SOPC_Free(group->securityGroupId);
1508
1509
        // securityKeyServices_length /= 0 => securityKeyServices /= NULL
1510
0
        SOPC_ASSERT(0 == group->securityKeyServices_length || NULL != group->securityKeyServices);
1511
0
        for (uint32_t i = 0; i < group->securityKeyServices_length; i++)
1512
0
        {
1513
0
            SOPC_SecurityKeyServices_Clear(&group->securityKeyServices[i]);
1514
0
        }
1515
0
        SOPC_Free(group->securityKeyServices);
1516
0
        group->securityKeyServices = NULL;
1517
0
        group->securityKeyServices_length = 0;
1518
1519
0
        for (int i = 0; i < group->dataSetReaders_length; i++)
1520
0
        {
1521
0
            SOPC_DataSetMetaData_Clear(&(group->dataSetReaders[i].metaData));
1522
0
        }
1523
0
        group->dataSetReaders_length = 0;
1524
0
        SOPC_Free(group->dataSetReaders);
1525
0
        SOPC_Free(group->mqttTopic);
1526
0
        SOPC_String_Clear(&group->publisherId.data.string);
1527
0
    }
1528
0
}
1529
1530
static void SOPC_FieldTarget_Clear(SOPC_FieldTarget* target)
1531
0
{
1532
0
    if (NULL != target)
1533
0
    {
1534
0
        SOPC_Free(target->receiverIndexRange);
1535
0
        SOPC_NodeId_Clear(target->nodeId);
1536
0
        SOPC_Free(target->nodeId);
1537
0
        SOPC_Free(target->writeIndexRange);
1538
0
    }
1539
0
}
1540
1541
static void SOPC_PublishedVariable_Clear(SOPC_PublishedVariable* variable)
1542
0
{
1543
0
    if (NULL != variable)
1544
0
    {
1545
0
        SOPC_NodeId_Clear(variable->nodeId);
1546
0
        SOPC_Free(variable->nodeId);
1547
0
    }
1548
0
}
1549
1550
/* Helper Functions*/
1551
1552
bool SOPC_EndpointDescription_Create_From_URL(char* url, OpcUa_EndpointDescription** endpoint_out)
1553
0
{
1554
0
    SOPC_ASSERT(NULL != endpoint_out);
1555
0
    *endpoint_out = NULL;
1556
1557
0
    bool allocSuccess = true;
1558
0
    OpcUa_EndpointDescription* endpoint;
1559
0
    if (NULL == url)
1560
0
    {
1561
0
        return true;
1562
0
    }
1563
0
    endpoint = SOPC_Calloc(1, sizeof(OpcUa_EndpointDescription));
1564
0
    if (NULL == endpoint)
1565
0
    {
1566
0
        return false;
1567
0
    }
1568
1569
0
    OpcUa_EndpointDescription_Initialize(endpoint);
1570
0
    SOPC_String_Initialize(&endpoint->EndpointUrl);
1571
0
    SOPC_ReturnStatus status = SOPC_String_CopyFromCString(&endpoint->EndpointUrl, url);
1572
0
    if (SOPC_STATUS_OK == status)
1573
0
    {
1574
0
        *endpoint_out = endpoint;
1575
0
    }
1576
0
    else
1577
0
    {
1578
0
        allocSuccess = false;
1579
0
        SOPC_Free(endpoint);
1580
0
    }
1581
0
    return allocSuccess;
1582
0
}