1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# OPC UA Discovery
A small C project that demonstrates OPC UA server discovery using the
[open62541](https://www.open62541.org/) library. Three programs work together:
- **ServerLDS** — Local Discovery Server that other servers register with
- **ServerRegister** — a server that periodically registers itself with the LDS
- **Client** — queries the LDS for servers, lists endpoints, or reads the current time from a server
## Prerequisites
- CMake 4.0+
- A C11 compiler (GCC or Clang)
- OpenSSL development libraries (`libssl-dev` / `openssl-devel`)
- `openssl` CLI (for generating certificates)
## Getting started
Clone the repository with its submodule:
```sh
git clone --recursive https://git.tvcloud.fr/opcua_c
cd opcua_c
```
### Generate certificates
The programs use TLS certificates for mutual authentication. ServerLDS and
ServerRegister can also run without certificates (SecurityPolicy#None only) by
omitting the `certificate`, `privateKey`, and `trustStore` keys from their
config files. For encrypted operation, four identities are needed — run these
from the project root:
```sh
tools/generate_certificate.sh certs ServerLDS
tools/generate_certificate.sh certs ServerRegister
tools/generate_certificate.sh certs ServerRegisterClient
tools/generate_certificate.sh certs ClientFindServers
```
### Populate the trust stores
Each program trusts a specific set of peers. Create symlinks to the
certificates in the trust store directories so they can find each other:
```sh
mkdir -p certs/trust/{server_lds,server_register,server_register_client,client}
ln -s ../../ServerRegisterClient_cert.der ../../ClientFindServers_cert.der \
certs/trust/server_lds/
ln -s ../../ServerLDS_cert.der ../../ClientFindServers_cert.der \
certs/trust/server_register/
ln -s ../../ServerLDS_cert.der \
certs/trust/server_register_client/
ln -s ../../ServerLDS_cert.der ../../ServerRegister_cert.der \
certs/trust/client/
```
### Build
```sh
cmake -B build
cmake --build build --parallel
```
open62541 is fetched from the submodule and built automatically — the first
build takes a bit longer.
## Running
Start the programs in order, each in its own terminal, from the project root:
```sh
# 1. Local Discovery Server
build/ServerLDS config/server_lds.conf
# 2. Register Server (connects to the LDS on port 4840)
build/ServerRegister config/server_register.conf \
config/server_register_client.conf opc.tcp://localhost:4840
# 3. Find registered servers via the LDS
build/Client config/client.conf find-servers opc.tcp://localhost:4840
# 4. List endpoints on the registered server
build/Client config/client.conf get-endpoints opc.tcp://localhost:4841
# 5. Read the current time from the registered server
build/Client config/client.conf read-time opc.tcp://localhost:4841
```
All three programs accept an optional log level as the last argument
(`trace`, `debug`, `info`, `warning`, `error`, `fatal`). The default is `info`.
## Tests
Integration tests exercise five combinations of security and authentication:
| Test | Security | Auth |
|------|----------|------|
| `nosec_anon` | LDS + ServerRegister unsecured / None | anonymous |
| `none_user` | None | user/password |
| `basic256sha256_anon` | SignAndEncrypt / Basic256Sha256 | anonymous |
| `aes256_anon` | SignAndEncrypt / Aes256_Sha256_RsaPss | anonymous |
| `aes128_user` | SignAndEncrypt / Aes128_Sha256_RsaOaep | user/password |
Run them:
```sh
ctest --test-dir build --output-on-failure
```
### Memory leak check
Rebuild with AddressSanitizer, run the tests, then switch back:
```sh
# ASan build
cmake -B build \
-DCMAKE_C_FLAGS="-fsanitize=address -fno-omit-frame-pointer" \
-DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address"
cmake --build build --parallel
ASAN_OPTIONS="detect_leaks=1" ctest --test-dir build --output-on-failure
# Restore normal build
cmake -B build -DCMAKE_C_FLAGS="" -DCMAKE_EXE_LINKER_FLAGS=""
cmake --build build --parallel
```
## Configuration
Programs are configured through plain text files (`key = value`, one per line).
Example configs are in `config/`.
|