# 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. Each call to `tools/generate_certificate.sh` creates a self-signed RSA-2048 certificate (`_cert.der`) and private key (`_key.der`) in the given directory: ```sh tools/generate_certificate.sh certs ServerLDS tools/generate_certificate.sh certs ServerRegister tools/generate_certificate.sh certs ServerRegisterClient tools/generate_certificate.sh certs Client ``` | Identity | Used by | Purpose | |----------|---------|---------| | `ServerLDS` | ServerLDS | Server certificate for the LDS | | `ServerRegister` | ServerRegister | Server certificate for the registering server | | `ServerRegisterClient` | ServerRegister | Client certificate used when connecting to the LDS | | `Client` | Client | Client certificate for all client operations | ### Populate the trust stores OPC UA applications only accept connections from peers whose certificate is in their trust store. Create the trust store directories and symlink each peer's certificate: ```sh mkdir -p certs/trust/{server_lds,server_register,server_register_client,client} ln -s ../../ServerRegisterClient_cert.der ../../Client_cert.der \ certs/trust/server_lds/ ln -s ../../ServerLDS_cert.der ../../Client_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 four combinations of security and authentication: | Test | Security | Auth | |------|----------|------| | `unsecure_anonymous` | None / None | anonymous | | `secure_anonymous` | SignAndEncrypt / Basic256Sha256 | anonymous | | `secure_user` | SignAndEncrypt / Basic256Sha256 | user/password | | `secure_cert` | SignAndEncrypt / Basic256Sha256 | X509 certificate | Run all tests: ```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/`. Three authentication modes are supported via the `authMode` key: - **anonymous** — no user identity - **user** — username and password (requires `username` and `password` keys) - **cert** — X509 certificate identity token (reuses the application certificate; requires encryption to be configured)