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
137
138
|
# 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 <certs_dir> <name>`. This creates `<name>_cert.der` and `<name>_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 \
user user password \
certs/ServerRegisterClient_cert.der certs/ClientFindServers_cert.der
```
Args: `<port> <applicationUri> <cert> <key> <cleanup-timeout-seconds> <auth-mode> [<username> <password>] [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 \
user user password \
user user password \
certs/ServerLDS_cert.der certs/ClientFindServers_cert.der
```
Args: `<port> <applicationUri> <server-cert> <server-key> <client-cert> <client-key> <discovery-endpoint> <register-interval-seconds> <security-mode> <security-policy> <server-auth-mode> [<server-user> <server-pass>] <client-auth-mode> [<client-user> <client-pass>] [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. Server auth mode controls what clients connecting to this server need; client auth mode controls how this server authenticates to the LDS. 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 \
user user password \
certs/ServerLDS_cert.der certs/ServerRegister_cert.der
```
Args: `<discovery-server-endpoint> <applicationUri> <cert> <key> <security-mode> <security-policy> <auth-mode> [<username> <password>] [trustlist...]`
Queries the LDS and prints all registered servers and their endpoints. Auth mode controls how the client authenticates when reading server time. The trustlist should include the certs of all servers whose endpoints will be queried.
**Security and auth options** (for both ServerRegister and ClientFindServers):
| Security modes | Security policies |
|----------------|-------------------|
| `None` | `None` |
| `Sign` | `Basic256Sha256` |
| `SignAndEncrypt` | `Aes256_Sha256_RsaPss` |
| | `Aes128_Sha256_RsaOaep` |
| | `ECC_nistP256` |
| Auth modes | Description |
|------------|-------------|
| `anonymous` | No session credentials |
| `user` | Username/password (requires two extra args) |
## 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 |
|