Skip to content
cheebinhohPublic

About

Distributed Messaging Network

Resources

Stars

1 star

Watchers

1 watching

Forks

Repository files navigation

# Dmn: Distributed Messaging & Synchronization

Dmn is a C++ library for distributed messaging and data synchronization. It
provides building blocks for networking, message exchange, concurrency control,
and conflict resolution, with an emphasis on delegation and integration into
existing applications.

## Documentation

Generated documentation: <https://cheebinhoh.github.io/Dmn/>

## Build and test on Linux

The project uses CMake and fetches its third-party dependencies during
configuration when they are not available locally. ICU development files are
required. On Ubuntu, install the native build prerequisites with:

```bash
sudo apt-get update
sudo apt-get install build-essential cmake git libicu-dev
```

Then configure, build, and run the regular unit tests:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j2
ctest --test-dir build -L dmn --output-on-failure
```

### Valgrind tests

Install Valgrind (on Ubuntu, `sudo apt-get install valgrind`) and enable its
test variants at configure time:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_VALGRIND=ON
cmake --build build -j2
ctest --test-dir build -L 'dmn|valgrind' --output-on-failure
```

This runs the regular tests plus their Valgrind variants. The `valgrind`
variants are only registered when `ENABLE_VALGRIND=ON`.

### Kafka integration tests

Kafka tests are optional and require a broker available at
`localhost:9092`. Either start a broker and create the `timer_counter` topic
yourself, or enable `BUILD_KAFKA_TEST=ON` and use the staged project helper.
For example, with Kafka's command-line tools:

```bash
kafka-topics.sh --create --topic timer_counter --bootstrap-server localhost:9092
```

Then configure, build, and run the Kafka tests:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DBUILD_KAFKA_TEST=ON
cmake --build build -j2
./build/scripts/run-bookstrap-dmn.sh
ctest --test-dir build -L kafka --output-on-failure
./build/scripts/run-bookstrap-dmn.sh stop
```

The helper downloads and verifies the pinned Kafka distribution when needed;
it requires Java and network access on first use. The Docker entrypoint starts
Kafka and creates this topic automatically.

### D-Bus extension

The optional D-Bus extension provides byte-oriented input/output adapters
that send and receive D-Bus signals, plus a typed generic client for method
calls, properties, and signal subscriptions. The signal adapters can carry
serialized DMesg messages through `Dmn_DMesgNet` or other application
payloads using a configured signal routing tuple. The extension is intended
for inter-process communication on one host and does not provide cross-host
transport. The core `dmn` library does not depend on D-Bus; the extension is
built separately as `dmn-dbus` and is disabled by default. `Dmn_DMesgDbus` is
the DMesg-specific composition facade for applications that do not need to
construct the underlying D-Bus endpoints directly; advanced callers can
continue to inject `Dmn_DbusInput` and `Dmn_DbusOutput` into `Dmn_DMesgNet`.
When an application links `dmn-dbus`, the target defines `DMN_ENABLE_DBUS`,
so `dmn.hpp` also includes the D-Bus configuration, endpoint, and facade
headers. Generic clients include `dmn-dbus-client.hpp` and
`dmn-dbus-value.hpp` directly; BlueZ clients include
`dmn-bluez-client.hpp`. Without the optional target and its compile
definitions, the umbrella header does not include the optional D-Bus API. The
`dmn-fault-injection.hpp` header is included by `dmn.hpp` only when
`ENABLE_FAULT_INJECTION=ON` defines `FIU_ENABLE`; its CMake target-source
registration is gated by the same option.

On Ubuntu, install the libdbus development files, pkg-config, and daemon used
by the private-bus unit test:

```bash
sudo apt-get install libdbus-1-dev pkg-config dbus-daemon
```

Enable the extension and run its test (registered under the regular `dmn`
CTest label):

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_DBUS=ON
cmake --build build -j2
ctest --test-dir build -R '^dmn-test-dbus-io$' --output-on-failure
ctest --test-dir build -R '^dmn-test-dbus-facade$' --output-on-failure
```

### BlueZ discovery CLI

On Linux, the optional `dmn-bluez-cli` program prints BlueZ's known
adapter/device inventory and can explicitly start a scan on one powered
adapter. It depends on the Dmn D-Bus extension, but not on GATT or ANCS.
Install the D-Bus development package and daemon as above, then configure and
build both optional Bluetooth CLIs:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
  -DENABLE_APP_BLUEZ_DISCOVERY=ON -DENABLE_APP_BLUETOOTH=ON
cmake --build build --target dmn-bluez-cli dmn-bluetooth-cli -j2
```

Install the built libraries, CLIs, headers, and their manual pages (use `sudo` if
installing to a system prefix):

```bash
cmake --install build --prefix "$HOME/.local"
export PATH="$HOME/.local/bin:$PATH"
man -M "$HOME/.local/share/man" dmn-bluez-cli
man -M "$HOME/.local/share/man" dmn-bluetooth-cli
```

Print the current known-device inventory as CSV without starting discovery:

```bash
./build/src/app/dmn-bluez-cli
```

The CSV includes the adapter address and path needed to select a scan target.
Start an explicit scan with either selector; if exactly one powered adapter
exists, `--adapter` may be omitted:

```bash
./build/src/app/dmn-bluez-cli --discovery \
  --adapter 'B8:F7:75:BF:F3:C3'
```

The CLI prints initial known devices, then live add/change/remove rows until
Ctrl-C or SIGTERM. It stops only the discovery session it started. It does
not pair, connect, change trust, or power an adapter. Scanning requires a
working BlueZ system service and local system-bus policy that permits the
discovery calls; the CLI does not fall back to the session bus. For argument
syntax, run `./build/src/app/dmn-bluez-cli --help`. The private-bus
integration coverage can be run with:

```bash
ctest --test-dir build -R '^dmn-test-bluez-device-list$' \
  --output-on-failure
```

### Bluetooth ANCS monitor CLI

The optional `dmn-bluetooth-cli` command pairs/connects one selected device as
needed and monitors its ANCS notifications:

```bash
./build/src/app/dmn-bluetooth-cli monitor "iPhone Genghis"
```

See `man dmn-bluetooth-cli` for its options, output, failure handling, and
recovery guidance. This CLI requires a working BlueZ system service and does
not provide a graphical interface.

### GTK Bluetooth application

On Linux desktops, the optional `dmn-bluetooth-gtk` app provides a graphical
interface for browsing BlueZ devices, saving a device selection, connecting
and disconnecting, and explicitly starting or stopping ANCS monitoring. The
GTK application and CLI are separate frontends to the same BlueZ/ANCS
functionality; enabling the GTK build does not build or replace the CLI.

The app never connects automatically. **Start monitoring** is an explicit
choice saved per device, so the app can restore that intent on later launches.
It starts the monitor only after the device is saved, paired, and BlueZ
confirms it is connected; if disconnected, it waits for you to connect it.
**Stop monitoring** clears the saved intent. Disconnecting or exiting stops
the live monitor but preserves the intent, so monitoring can resume after
reconnection or relaunch. The newest-first event feed contains only
notifications received while the app process is running; it is not a
persistent notification archive or a desktop notification-history reader.
Search and device, event-kind, and category filters compose; activating a row
shows available details. The feed is capped at 1,000 in-memory events, with
older-event eviction reported in the interface. Hovering over notification
text shows its full value wrapped to the available feed width.
The GTK app requires a running BlueZ system service and a graphical desktop
session.

Install the additional development dependencies on Ubuntu:

```bash
sudo apt-get install libgtk-4-dev libadwaita-1-dev
```

GTK 4 4.14 or newer and libadwaita 1.5 or newer are required. Configure and
build the app without enabling the CLI:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
  -DENABLE_APP_BLUETOOTH_GTK=ON
cmake --build build --target dmn-bluetooth-gtk -j2
./build/src/app/dmn-bluetooth-gtk
```

The GTK option enables the required ANCS, BlueZ, and D-Bus libraries but
remains off in default/headless builds. To install the application, desktop
launcher, AppStream metadata, icons, and settings schema into a user prefix:

```bash
cmake --install build --prefix "$HOME/.local"
```

For the implemented UI, remaining features, and current design details, see
the [GTK application specification](docs/specs/dmn-bluetooth-gtk-app-spec.md)
and its [UI storyboard](docs/specs/dmn-bluetooth-gtk-ui-storyboard.md).

## Fault-injection tests

Fault-injection support is optional and disabled by default. Enabling it links
libfiu into the fault-injection build. CMake uses an installed libfiu package
found through pkg-config when available; otherwise it fetches and builds
libfiu 1.2 and its `fiu-run` launcher.

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_FAULT_INJECTION=ON
cmake --build build --target fault-injection-tests -j2
ctest --test-dir build -L fault-injection --output-on-failure
```

Fault-injection tests are GoogleTest executables invoked by CTest through
`fiu-run`. They use the separate `fault-injection` label and are not included
in the regular `dmn` test group. To run one test by name:

```bash
ctest --test-dir build -R '^dmn-test-fi-timer-thread-start-failure$' \
  --output-on-failure
```

The recurring-reschedule failure test can be run individually with:

```bash
ctest --test-dir build -R '^dmn-test-fi-timer-reschedule-failure$' \
  --output-on-failure
```

## Docker

From the repository root, build the image:

```bash
docker build -t dmn .
```

Start it interactively with its normal entrypoint:

```bash
docker run -it --rm dmn
```

The image enables its non-hardware CMake options (the GTK desktop app is not
included). On startup, the entrypoint
bootstraps the Kafka topic and runs the `dmn`, `kafka`, `valgrind`, and
`fault-injection` CTest groups. If they pass, it opens a Bash prompt in the
container; if they fail, the entrypoint exits without opening the prompt. The
run command removes the container when you exit because it uses `--rm`.

To enter a shell immediately without starting Kafka or running tests, bypass
the entrypoint:

```bash
docker run -it --rm --entrypoint /bin/bash dmn
```

The image is built with `BUILD_NDEBUG=ON`, which disables assertions. Use a
native build with `BUILD_NDEBUG=OFF` when assertions are needed. To build with
Docker Buildx and load the image into the local Docker engine:

```bash
docker buildx build -t dmn:latest --load .
```

Remove the image when it is no longer needed:

```bash
docker rmi dmn
```

## CMake options

| Option | Default | Purpose |
| --- | --- | --- |
| `BUILD_NDEBUG` | `OFF` | Define `NDEBUG` for the build. |
| `BUILD_KAFKA_TEST` | `OFF` | Build the additional Kafka integration tests. |
| `ENABLE_DBUS` | `OFF` | Build the optional D-Bus signal I/O extension and generic D-Bus client. Requires libdbus development files and pkg-config; private-bus tests require `dbus-daemon`. |
| `ENABLE_BLUEZ` | `OFF` | Build the Linux BlueZ library; automatically enables its `ENABLE_DBUS` dependency. |
| `ENABLE_ANCS` | `OFF` | Build the backend-neutral ANCS protocol library. |
| `ENABLE_APP_BLUEZ_DISCOVERY` | `OFF` | Build and install `dmn-bluez-cli`; automatically enables `ENABLE_BLUEZ` and `ENABLE_DBUS`. |
| `ENABLE_APP_BLUETOOTH` | `OFF` | Build and install `dmn-bluetooth-cli`; automatically enables `ENABLE_ANCS`, `ENABLE_BLUEZ`, and `ENABLE_DBUS`. |
| `ENABLE_APP_BLUETOOTH_GTK` | `OFF` | Build and install the Linux GTK 4/libadwaita `dmn-bluetooth-gtk` desktop app; automatically enables `ENABLE_ANCS`, `ENABLE_BLUEZ`, and `ENABLE_DBUS`. Requires GTK 4 4.14+, libadwaita 1.5+, and GLib schema tools. |
| `ENABLE_ANCS_HARDWARE_TESTS` | `OFF` | Register the opt-in physical-iPhone test; requires `ENABLE_APP_BLUETOOTH=ON`. |
| `ENABLE_VALGRIND` | `OFF` | Register Valgrind test variants; requires Valgrind. |
| `ENABLE_FAULT_INJECTION` | `OFF` | Build libfiu support and register tests run through `fiu-run`. |

The options are cached in the build directory. Reconfigure that directory
with the desired options before building. The `dmn` CTest label selects the
regular unit tests; `kafka`, `fault-injection`, and `valgrind` select their
respective optional test groups.

On Linux, to enable the non-hardware CMake options used in the example below,
including Kafka, D-Bus, BlueZ, ANCS, both Bluetooth CLI programs, Valgrind,
and fault injection, configure and build as shown. The optional GTK app has
separate GTK/libadwaita dependencies described above. BlueZ tests use a private
bus and do not require a physical adapter; the physical-iPhone test remains
opt-in:

```bash
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_NDEBUG=ON \
  -DBUILD_KAFKA_TEST=ON \
  -DENABLE_DBUS=ON \
  -DENABLE_BLUEZ=ON \
  -DENABLE_ANCS=ON \
  -DENABLE_APP_BLUEZ_DISCOVERY=ON \
  -DENABLE_APP_BLUETOOTH=ON \
  -DENABLE_VALGRIND=ON \
  -DENABLE_FAULT_INJECTION=ON
cmake --build build -j2
```

This configuration requires libdbus development files, pkg-config,
`dbus-daemon`, Valgrind, and Java plus network access to bootstrap Kafka on
first use. Run the Kafka helper before its tests, then run every registered
test group with:

```bash
./build/scripts/run-bookstrap-dmn.sh
ctest --test-dir build -L 'dmn|kafka|valgrind|fault-injection' \
  --output-on-failure
./build/scripts/run-bookstrap-dmn.sh stop
```

`BUILD_NDEBUG=ON` disables assertions, so use `OFF` if you want assertions
enabled while running the full test groups.

About

Distributed Messaging Network

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages