aboutsummaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
blob: b3ee66f1ce08026beb3eb0859a7f8f9bb024db52 (plain)
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
# 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 \
  certs/ServerRegisterClient_cert.der certs/ClientFindServers_cert.der
```

Args: `<port> <applicationUri> <cert> <key> <cleanup-timeout-seconds> [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: `<port> <applicationUri> <server-cert> <server-key> <client-cert> <client-key> <discovery-endpoint> <register-interval-seconds> <security-mode> <security-policy> [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: `<discovery-server-endpoint> <applicationUri> <cert> <key> <security-mode> <security-policy> [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 |