# CLAUDE.md — OPC UA Discovery Project ## Project Overview C project exploring OPC UA discovery using the open62541 library (git submodule at `deps/open62541`). CMake build system (C11). Source files live in `src/`, certificates in `certs/`, helper scripts in `tools/`. ## Build ```sh cmake --build build --parallel ``` If the build directory doesn't exist yet or dependencies need reconfiguring: ```sh cmake -B build cmake --build build --parallel ``` open62541 is built automatically via `cmake/BuildDeps.cmake` with `UA_ENABLE_ENCRYPTION=OPENSSL` and `UA_ENABLE_DISCOVERY=ON`, installed to `build/deps/open62541-install`. The open62541 build directory is `build/deps/open62541`. After building, verify that `compile_commands.json` is symlinked from `build/` to the project root. ### Building Documentation To build the open62541 HTML documentation (requires `python3-sphinx`, `python3-sphinx-rtd-theme`, `graphviz`): ```sh cmake -B build -DBUILD_DOC=ON cmake --build build --target doc ``` Output goes to `build/deps/open62541/doc/index.html`. ## Code Style - Follow the `.clang-format` file in the project root (GNU-based style). - Key points: 2-space indent, braces on own line (`BreakBeforeBraces: GNU`), space before parens (`SpaceBeforeParens: Always`), pointer star on the right (`PointerAlignment: Right`), 79-column limit, return type on its own line for definitions. - Do **not** reformat code you didn't change. ## Workflow Preferences - **Ask before committing.** Never commit without explicit confirmation. - **Ask when ambiguous.** If a task or requirement is unclear, ask rather than guess. - **Plan mode:** Ask before entering plan mode — don't assume it's needed. - **Validation:** After making changes, confirm the project compiles with `cmake --build build --parallel`. When asked to run or test, start all three programs (LDS, ServerRegister, ClientFindServers) using the commands in the **Running** section below, then verify the client output. - **Verbosity:** Give detailed explanations of what was done and why. ## Certificates Generate DER certificates with `tools/generate_certificate.sh `. This creates `_cert.der` and `_key.der` in the given directory. Four identities are needed: ```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 ``` Existing certs live in `certs/`. Only regenerate if missing. ## Running All three programs run from the project root. Start them in order in separate terminals: **1. Local Discovery Server (LDS)** ```sh build/ServerLDS 4840 "urn:bobink.ServerLDS" \ certs/ServerLDS_cert.der certs/ServerLDS_key.der \ 60 \ certs/ServerRegisterClient_cert.der certs/ClientFindServers_cert.der ``` Args: ` [trustlist...]` The trustlist must include the client certs that will connect over encrypted channels: `ServerRegisterClient_cert.der` (used by `ServerRegister`) and `ClientFindServers_cert.der` (used by `ClientFindServers`). Cleanup timeout must be > 10. **2. Register Server** ```sh build/ServerRegister 4841 "urn:bobink.ServerRegister" \ certs/ServerRegister_cert.der certs/ServerRegister_key.der \ certs/ServerRegisterClient_cert.der certs/ServerRegisterClient_key.der \ "opc.tcp://localhost:4840" 10 \ SignAndEncrypt Aes128_Sha256_RsaOaep \ certs/ServerLDS_cert.der certs/ClientFindServers_cert.der ``` Args: ` [trustlist...]` Uses separate server/client certificate pairs. The client cert+key are for the secure channel to the LDS. Re-registers periodically at the given interval. Trustlist should include the LDS cert and any client certs that will query this server's endpoints (e.g. `ClientFindServers_cert.der`). **3. Find Servers Client** ```sh build/ClientFindServers "opc.tcp://localhost:4840" \ "urn:bobink.ClientFindServers" \ certs/ClientFindServers_cert.der certs/ClientFindServers_key.der \ SignAndEncrypt Aes128_Sha256_RsaOaep \ certs/ServerLDS_cert.der certs/ServerRegister_cert.der ``` Args: ` [trustlist...]` Queries the LDS and prints all registered servers and their endpoints. The trustlist should include the certs of all servers whose endpoints will be queried. **Security options** (for both ServerRegister and ClientFindServers): | Security modes | Security policies | |----------------|-------------------| | `None` | `None` | | `Sign` | `Basic256Sha256` | | `SignAndEncrypt` | `Aes256_Sha256_RsaPss` | | | `Aes128_Sha256_RsaOaep` | | | `ECC_nistP256` | ## Project Structure | Path | Purpose | |------|---------| | `src/common.h` / `src/common.c` | Shared helpers: `loadFile()`, `createSecureServer()`, `createSecureClientConfig()`, `parseSecurityMode()`, `resolveSecurityPolicyUri()` | | `src/server_lds.c` | Local Discovery Server | | `src/server_register.c` | Server that registers with LDS | | `src/client_find_servers.c` | Client that queries LDS and displays endpoints | | `certs/` | TLS certificates for server, client, and LDS | | `tools/` | Helper scripts | | `cmake/BuildDeps.cmake` | Configures, builds, and installs open62541 | | `deps/open62541` | open62541 git submodule |