From 6d3db4b6c7c179b3bd934206f7b4e34f365e3baf Mon Sep 17 00:00:00 2001 From: Akrm Al-Hakimi Date: Mon, 2 Feb 2026 21:55:32 -0500 Subject: [PATCH] docs: introduce mdbook --- .github/workflows/docs.yml | 57 ++++ Cargo.lock | 8 +- README.md | 9 +- docs/.gitignore | 2 + docs/README.md | 45 +++ docs/add-page.sh | 49 +++ docs/book.toml | 53 +++ docs/src/SUMMARY.md | 74 +++++ docs/src/advanced/async-runtimes.md | 3 + docs/src/advanced/connection-options.md | 3 + docs/src/advanced/dbus.md | 3 + docs/src/advanced/logging.md | 3 + docs/src/advanced/timeouts.md | 3 + docs/src/api/builders.md | 5 + docs/src/api/errors.md | 5 + docs/src/api/models.md | 5 + docs/src/api/network-manager.md | 5 + docs/src/api/types.md | 5 + docs/src/appendix/changelog.md | 3 + docs/src/appendix/faq.md | 3 + docs/src/appendix/license.md | 3 + docs/src/appendix/troubleshooting.md | 3 + docs/src/development/architecture.md | 3 + docs/src/development/contributing.md | 134 ++++++++ docs/src/development/releases.md | 3 + docs/src/development/testing.md | 3 + docs/src/examples/connection-manager.md | 3 + docs/src/examples/enterprise-wifi.md | 3 + docs/src/examples/network-monitor.md | 3 + docs/src/examples/wifi-auto-connect.md | 3 + docs/src/examples/wifi-scanner.md | 260 +++++++++++++++ docs/src/examples/wireguard-client.md | 3 + docs/src/getting-started/installation.md | 145 ++++++++ docs/src/getting-started/quick-start.md | 310 +++++++++++++++++ docs/src/getting-started/requirements.md | 275 +++++++++++++++ docs/src/gui/configuration.md | 3 + docs/src/gui/installation.md | 3 + docs/src/gui/overview.md | 3 + docs/src/gui/themes.md | 3 + docs/src/gui/waybar.md | 3 + docs/src/guide/bluetooth.md | 3 + docs/src/guide/devices.md | 3 + docs/src/guide/error-handling.md | 3 + docs/src/guide/ethernet.md | 3 + docs/src/guide/monitoring.md | 3 + docs/src/guide/profiles.md | 3 + docs/src/guide/vpn-management.md | 3 + docs/src/guide/vpn-wireguard.md | 3 + docs/src/guide/vpn.md | 406 +++++++++++++++++++++++ docs/src/guide/wifi-connecting.md | 3 + docs/src/guide/wifi-enterprise.md | 3 + docs/src/guide/wifi-hidden.md | 3 + docs/src/guide/wifi-scanning.md | 3 + docs/src/guide/wifi-wpa-psk.md | 3 + docs/src/guide/wifi.md | 319 ++++++++++++++++++ docs/src/introduction.md | 82 +++++ docs/theme/custom.css | 72 ++++ 57 files changed, 2425 insertions(+), 5 deletions(-) create mode 100644 .github/workflows/docs.yml create mode 100644 docs/.gitignore create mode 100644 docs/README.md create mode 100755 docs/add-page.sh create mode 100644 docs/book.toml create mode 100644 docs/src/SUMMARY.md create mode 100644 docs/src/advanced/async-runtimes.md create mode 100644 docs/src/advanced/connection-options.md create mode 100644 docs/src/advanced/dbus.md create mode 100644 docs/src/advanced/logging.md create mode 100644 docs/src/advanced/timeouts.md create mode 100644 docs/src/api/builders.md create mode 100644 docs/src/api/errors.md create mode 100644 docs/src/api/models.md create mode 100644 docs/src/api/network-manager.md create mode 100644 docs/src/api/types.md create mode 100644 docs/src/appendix/changelog.md create mode 100644 docs/src/appendix/faq.md create mode 100644 docs/src/appendix/license.md create mode 100644 docs/src/appendix/troubleshooting.md create mode 100644 docs/src/development/architecture.md create mode 100644 docs/src/development/contributing.md create mode 100644 docs/src/development/releases.md create mode 100644 docs/src/development/testing.md create mode 100644 docs/src/examples/connection-manager.md create mode 100644 docs/src/examples/enterprise-wifi.md create mode 100644 docs/src/examples/network-monitor.md create mode 100644 docs/src/examples/wifi-auto-connect.md create mode 100644 docs/src/examples/wifi-scanner.md create mode 100644 docs/src/examples/wireguard-client.md create mode 100644 docs/src/getting-started/installation.md create mode 100644 docs/src/getting-started/quick-start.md create mode 100644 docs/src/getting-started/requirements.md create mode 100644 docs/src/gui/configuration.md create mode 100644 docs/src/gui/installation.md create mode 100644 docs/src/gui/overview.md create mode 100644 docs/src/gui/themes.md create mode 100644 docs/src/gui/waybar.md create mode 100644 docs/src/guide/bluetooth.md create mode 100644 docs/src/guide/devices.md create mode 100644 docs/src/guide/error-handling.md create mode 100644 docs/src/guide/ethernet.md create mode 100644 docs/src/guide/monitoring.md create mode 100644 docs/src/guide/profiles.md create mode 100644 docs/src/guide/vpn-management.md create mode 100644 docs/src/guide/vpn-wireguard.md create mode 100644 docs/src/guide/vpn.md create mode 100644 docs/src/guide/wifi-connecting.md create mode 100644 docs/src/guide/wifi-enterprise.md create mode 100644 docs/src/guide/wifi-hidden.md create mode 100644 docs/src/guide/wifi-scanning.md create mode 100644 docs/src/guide/wifi-wpa-psk.md create mode 100644 docs/src/guide/wifi.md create mode 100644 docs/src/introduction.md create mode 100644 docs/theme/custom.css diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..a4734a01 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,57 @@ +name: Deploy Docs + +on: + push: + branches: + - master + paths: + - 'docs/**' + - '.github/workflows/docs.yml' + pull_request: + paths: + - 'docs/**' + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install mdBook + run: | + mkdir -p ~/bin + curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.40/mdbook-v0.4.40-x86_64-unknown-linux-gnu.tar.gz | tar -xz -C ~/bin + echo "$HOME/bin" >> $GITHUB_PATH + + - name: Build book + run: | + cd docs + mdbook build + + - name: Upload artifact + if: github.event_name != 'pull_request' + uses: actions/upload-pages-artifact@v3 + with: + path: docs/book + + deploy: + if: github.event_name != 'pull_request' + needs: build + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/Cargo.lock b/Cargo.lock index add38e7f..3b42a05b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,9 +279,9 @@ checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" [[package]] name = "clap" -version = "4.5.55" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e34525d5bbbd55da2bb745d34b36121baac88d07619a9a09cfcf4a6c0832785" +checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" dependencies = [ "clap_builder", "clap_derive", @@ -289,9 +289,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.55" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a20016a20a3da95bef50ec7238dbd09baeef4311dcdd38ec15aba69812fb61" +checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", diff --git a/README.md b/README.md index b0812642..d01c62a0 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Crates.io](https://img.shields.io/crates/v/nmrs)](https://crates.io/crates/nmrs) [![Discord](https://img.shields.io/badge/chat-on%20discord-7289da?logo=discord&logoColor=white)](https://discord.gg/Sk3VfrHrN4) [![Documentation](https://docs.rs/nmrs/badge.svg)](https://docs.rs/nmrs) +[![User Guide](https://img.shields.io/badge/docs-mdBook-blue)](https://cachebag.github.io/nmrs/) [![CI](https://github.com/cachebag/nmrs/actions/workflows/ci.yml/badge.svg)](https://github.com/cachebag/nmrs/actions/workflows/ci.yml) [![License](https://img.shields.io/crates/l/nmrs)](LICENSE) @@ -15,11 +16,17 @@ The project is divided into the following crates: [Jump to the GUI section of this repo](#installation) +## Documentation + +- **[User Guide](https://cachebag.github.io/nmrs/)** - Comprehensive guide with tutorials and examples +- **[API Documentation](https://docs.rs/nmrs)** - Complete API reference on docs.rs +- **[Discord](https://discord.gg/Sk3VfrHrN4)** - Join our community for help and discussion + ## Getting Started _Please consider joining the [**Discord**](https://discord.gg/Sk3VfrHrN4). It's a welcoming community to both developers who want to contribute and/or learn about and discuss nmrs as well as users that would like to be engaged with the development process._ -The best way to get started with `nmrs` is the [API documentation](https://docs.rs/nmrs), which includes examples for common operations like scanning networks, connecting to Wi-Fi, and managing connection profiles. +The best way to get started with `nmrs` is the [User Guide](https://cachebag.github.io/nmrs/), which includes comprehensive tutorials and examples. For detailed API information, see the [API documentation](https://docs.rs/nmrs). ## Sample usage We'll create a simple example that scans for available networks and connects to one. Note that these examples require NetworkManager to be running on your Linux system with D-Bus access, obviously. diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..95672826 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +# mdBook output +book/ diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 00000000..38072467 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,45 @@ +# nmrs Documentation + +This directory contains the mdBook-based user guide for nmrs. + +## Building Locally + +Install mdBook: + +```bash +cargo install mdbook +``` + +Build the book: + +```bash +cd docs +mdbook build +``` + +Serve with live reload: + +```bash +mdbook serve --open +``` + +The documentation will be available at http://localhost:3000 + +## Structure + +- `src/` - Markdown source files +- `book.toml` - mdBook configuration +- `theme/` - Custom CSS and styling +- `book/` - Generated output (gitignored) + +## Contributing + +When adding new pages: + +1. Create the markdown file in the appropriate `src/` subdirectory +2. Add it to `src/SUMMARY.md` to include it in the table of contents +3. Build and preview locally to ensure it looks correct + +## Deployment + +The documentation is automatically built and deployed to GitHub Pages via the `.github/workflows/docs.yml` workflow on every push to `master`. diff --git a/docs/add-page.sh b/docs/add-page.sh new file mode 100755 index 00000000..eaadcec9 --- /dev/null +++ b/docs/add-page.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Helper script to add new pages to the documentation + +if [ $# -lt 2 ]; then + echo "Usage: $0
" + echo "Example: $0 guide wifi-configuration" + echo "" + echo "Available sections:" + echo " - getting-started" + echo " - guide" + echo " - advanced" + echo " - examples" + echo " - gui" + echo " - api" + echo " - development" + echo " - appendix" + exit 1 +fi + +SECTION=$1 +PAGE=$2 +TITLE=$(echo "${PAGE//-/ }" | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) tolower(substr($i,2))}1') + +# Create the file +cat > "src/${SECTION}/${PAGE}.md" << EOF +# ${TITLE} + +[Content to be added] + +## Overview + +... + +## Examples + +... + +## See Also + +- [Related page](../guide/other.md) +EOF + +echo "✓ Created src/${SECTION}/${PAGE}.md" +echo "" +echo "Next steps:" +echo "1. Add content to src/${SECTION}/${PAGE}.md" +echo "2. Add to src/SUMMARY.md in the appropriate section:" +echo " - [${TITLE}](./${SECTION}/${PAGE}.md)" +echo "3. Build and preview: mdbook serve" diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 00000000..2391d774 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,53 @@ +[book] +title = "nmrs Documentation" +description = "Comprehensive guide to using nmrs - A Rust API for NetworkManager" +authors = ["Akrm Al-Hakimi"] +language = "en" +src = "src" + +[rust] +edition = "2021" + +[build] +build-dir = "book" +create-missing = true +use-default-preprocessors = true + +[preprocessor.links] + +[output.html] +default-theme = "navy" +preferred-dark-theme = "navy" +git-repository-url = "https://github.com/cachebag/nmrs" +edit-url-template = "https://github.com/cachebag/nmrs/edit/master/docs/{path}" +site-url = "/nmrs/" +cname = "" +additional-css = ["theme/custom.css"] +additional-js = [] + +[output.html.fold] +enable = true +level = 1 + +[output.html.playground] +editable = true +copyable = true +copy-js = true +line-numbers = true +runnable = true + +[output.html.search] +enable = true +limit-results = 30 +teaser-word-count = 30 +use-boolean-and = true +boost-title = 2 +boost-hierarchy = 1 +boost-paragraph = 1 +expand = true +heading-split-level = 3 + +[output.html.print] +enable = true + +[output.html.redirect] diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md new file mode 100644 index 00000000..2e44f7df --- /dev/null +++ b/docs/src/SUMMARY.md @@ -0,0 +1,74 @@ +# Summary + +[Introduction](./introduction.md) + +# Getting Started + +- [Installation](./getting-started/installation.md) +- [Quick Start](./getting-started/quick-start.md) +- [Requirements](./getting-started/requirements.md) + +# User Guide + +- [WiFi Management](./guide/wifi.md) + - [Scanning Networks](./guide/wifi-scanning.md) + - [Connecting to Networks](./guide/wifi-connecting.md) + - [WPA-PSK Networks](./guide/wifi-wpa-psk.md) + - [WPA-EAP (Enterprise)](./guide/wifi-enterprise.md) + - [Hidden Networks](./guide/wifi-hidden.md) +- [VPN Connections](./guide/vpn.md) + - [WireGuard Setup](./guide/vpn-wireguard.md) + - [VPN Management](./guide/vpn-management.md) +- [Ethernet Management](./guide/ethernet.md) +- [Bluetooth](./guide/bluetooth.md) +- [Device Management](./guide/devices.md) +- [Connection Profiles](./guide/profiles.md) +- [Real-Time Monitoring](./guide/monitoring.md) +- [Error Handling](./guide/error-handling.md) + +# Advanced Topics + +- [Async Runtime Support](./advanced/async-runtimes.md) +- [Custom Timeouts](./advanced/timeouts.md) +- [Connection Options](./advanced/connection-options.md) +- [D-Bus Architecture](./advanced/dbus.md) +- [Logging and Debugging](./advanced/logging.md) + +# Examples + +- [Basic WiFi Scanner](./examples/wifi-scanner.md) +- [WiFi Auto-Connect](./examples/wifi-auto-connect.md) +- [Enterprise WiFi](./examples/enterprise-wifi.md) +- [WireGuard VPN Client](./examples/wireguard-client.md) +- [Network Monitor Dashboard](./examples/network-monitor.md) +- [Connection Manager](./examples/connection-manager.md) + +# nmrs-gui + +- [GUI Overview](./gui/overview.md) +- [Installation](./gui/installation.md) +- [Configuration](./gui/configuration.md) +- [Themes](./gui/themes.md) +- [Waybar Integration](./gui/waybar.md) + +# API Reference + +- [Core Types](./api/types.md) +- [NetworkManager](./api/network-manager.md) +- [Models Module](./api/models.md) +- [Builders Module](./api/builders.md) +- [Error Types](./api/errors.md) + +# Development + +- [Contributing](./development/contributing.md) +- [Architecture](./development/architecture.md) +- [Testing](./development/testing.md) +- [Release Process](./development/releases.md) + +# Appendix + +- [Troubleshooting](./appendix/troubleshooting.md) +- [FAQ](./appendix/faq.md) +- [Changelog](./appendix/changelog.md) +- [License](./appendix/license.md) diff --git a/docs/src/advanced/async-runtimes.md b/docs/src/advanced/async-runtimes.md new file mode 100644 index 00000000..89785c56 --- /dev/null +++ b/docs/src/advanced/async-runtimes.md @@ -0,0 +1,3 @@ +# Async Runtimes + +Documentation coming soon. diff --git a/docs/src/advanced/connection-options.md b/docs/src/advanced/connection-options.md new file mode 100644 index 00000000..1b0982a1 --- /dev/null +++ b/docs/src/advanced/connection-options.md @@ -0,0 +1,3 @@ +# Connection Options + +Documentation coming soon. diff --git a/docs/src/advanced/dbus.md b/docs/src/advanced/dbus.md new file mode 100644 index 00000000..bee1643f --- /dev/null +++ b/docs/src/advanced/dbus.md @@ -0,0 +1,3 @@ +# Dbus + +Documentation coming soon. diff --git a/docs/src/advanced/logging.md b/docs/src/advanced/logging.md new file mode 100644 index 00000000..4e3859b9 --- /dev/null +++ b/docs/src/advanced/logging.md @@ -0,0 +1,3 @@ +# Logging + +Documentation coming soon. diff --git a/docs/src/advanced/timeouts.md b/docs/src/advanced/timeouts.md new file mode 100644 index 00000000..79381cd2 --- /dev/null +++ b/docs/src/advanced/timeouts.md @@ -0,0 +1,3 @@ +# Timeouts + +Documentation coming soon. diff --git a/docs/src/api/builders.md b/docs/src/api/builders.md new file mode 100644 index 00000000..c7b85420 --- /dev/null +++ b/docs/src/api/builders.md @@ -0,0 +1,5 @@ +# Builders + +Documentation coming soon. + +See the [API documentation](https://docs.rs/nmrs) for complete details. diff --git a/docs/src/api/errors.md b/docs/src/api/errors.md new file mode 100644 index 00000000..634c3b7f --- /dev/null +++ b/docs/src/api/errors.md @@ -0,0 +1,5 @@ +# Errors + +Documentation coming soon. + +See the [API documentation](https://docs.rs/nmrs) for complete details. diff --git a/docs/src/api/models.md b/docs/src/api/models.md new file mode 100644 index 00000000..707dea90 --- /dev/null +++ b/docs/src/api/models.md @@ -0,0 +1,5 @@ +# Models + +Documentation coming soon. + +See the [API documentation](https://docs.rs/nmrs) for complete details. diff --git a/docs/src/api/network-manager.md b/docs/src/api/network-manager.md new file mode 100644 index 00000000..c02aa022 --- /dev/null +++ b/docs/src/api/network-manager.md @@ -0,0 +1,5 @@ +# Network Manager + +Documentation coming soon. + +See the [API documentation](https://docs.rs/nmrs) for complete details. diff --git a/docs/src/api/types.md b/docs/src/api/types.md new file mode 100644 index 00000000..48628833 --- /dev/null +++ b/docs/src/api/types.md @@ -0,0 +1,5 @@ +# Types + +Documentation coming soon. + +See the [API documentation](https://docs.rs/nmrs) for complete details. diff --git a/docs/src/appendix/changelog.md b/docs/src/appendix/changelog.md new file mode 100644 index 00000000..045783db --- /dev/null +++ b/docs/src/appendix/changelog.md @@ -0,0 +1,3 @@ +# Changelog + +Documentation coming soon. diff --git a/docs/src/appendix/faq.md b/docs/src/appendix/faq.md new file mode 100644 index 00000000..cddd5912 --- /dev/null +++ b/docs/src/appendix/faq.md @@ -0,0 +1,3 @@ +# Faq + +Documentation coming soon. diff --git a/docs/src/appendix/license.md b/docs/src/appendix/license.md new file mode 100644 index 00000000..104d11df --- /dev/null +++ b/docs/src/appendix/license.md @@ -0,0 +1,3 @@ +# License + +Documentation coming soon. diff --git a/docs/src/appendix/troubleshooting.md b/docs/src/appendix/troubleshooting.md new file mode 100644 index 00000000..bb285c96 --- /dev/null +++ b/docs/src/appendix/troubleshooting.md @@ -0,0 +1,3 @@ +# Troubleshooting + +Documentation coming soon. diff --git a/docs/src/development/architecture.md b/docs/src/development/architecture.md new file mode 100644 index 00000000..a7cd5b2d --- /dev/null +++ b/docs/src/development/architecture.md @@ -0,0 +1,3 @@ +# Architecture + +Documentation coming soon. diff --git a/docs/src/development/contributing.md b/docs/src/development/contributing.md new file mode 100644 index 00000000..b09aa54c --- /dev/null +++ b/docs/src/development/contributing.md @@ -0,0 +1,134 @@ +# Contributing + +Thank you for wanting to contribute to `nmrs`! + +## Guidelines + +I'm fairly accepting to all PRs, only with a couple caveats: +- Do not submit low-effort or autogenerated code. If you absolutely must, please disclose _how_ you used AI otherwise I will close the PR. +- Please try to (when possible) contribute to an [issue](https://github.com/cachebag/nmrs/issues). This is not a hard ask, I'll still consider your contribution if it makes sense. + +## Requirements + +### To run or develop nmrs you need: +- Rust (stable) via `rustup` +- A running `NetworkManager` instance + +I also provide a `Dockerfile` you can build if you don't use Linux and use MacOS instead. + +### To run tests: +```bash +docker compose run test +``` + +### To run an interactive shell: +```bash +docker compose run shell +``` + +It goes without saying that this image only works with nmrs. nmrs-gui requires GTK deps which in that case, you are better off just running a VM or learning how to use Linux on a machine instead. + +If you decide to run the shell, ensure you run all commands from within the nmrs directory, not root. +```bash +cargo test -p nmrs # run library tests +cargo build -p nmrs # build the library +cargo check # you get the point... +``` + +### To develop nmrs-gui, you'll need: +- GTK4 and libadwaita development libraries +- A Wayland compositor + +## When your branch falls behind `master` + +If the respective branch for a PR goes out of sync, I prefer you _rebase_. +I've exposed this setting for you to automatically do so as a contributor on any PR you open. + +## Issues and Commit Message Hygiene + +When you've made changes and are ready to commit, I prefer that you follow the standards explained at [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). + +I additionally request that you format your commits as such: +`type((some issue number)): changes made` + +For example: +``` +fix(#24): fixed bug where something was happening +``` + +Obviously, if there is no issue number to attach, no need to add anything there. + +Lastly, please ensure you make [atomic commits](https://en.wikipedia.org/wiki/Atomic_commit). + +All issues are acceptable. If a situation arises where a request or concern is not valid, I will respond directly to the issue. + +## Tests + +All tests must pass before a merge takes place. + +### Ensure NetworkManager is running +```bash +sudo systemctl start NetworkManager +``` + +### Test everything (unit + integration) +```bash +cargo test --all-features +``` + +### Integration tests + +These require WiFi hardware. Please make sure you run this locally before your PR to ensure everything works. + +```bash +cargo test --test integration_test --all-features +``` + +If you do not have access to WiFi hardware (for whatever odd reason that is), you can do something like this: + +```bash +sudo modprobe mac80211_hwsim radios=2 +cargo test --test integration_test --all-features +sudo modprobe -r mac80211_hwsim +``` + +> **Note**: This method only works on Linux + +## Documentation + +When adding new features or changing existing APIs: + +1. Update rustdoc comments in the source code +2. Add or update examples in the `examples/` directory +3. Update this mdBook documentation if user-facing changes are made +4. Update the CHANGELOG.md + +To build the documentation locally: + +```bash +# API documentation +cargo doc --open --no-deps + +# User guide (this book) +cd docs +mdbook build +mdbook serve --open +``` + +## Code Style + +- Follow standard Rust formatting: `cargo fmt` +- Pass clippy checks: `cargo clippy -- -D warnings` +- No unsafe code (enforced by workspace lints) +- Add doc comments for public APIs +- Write tests for new functionality + +## License + +All contributions fall under the dual MIT/Apache-2.0 license. + +## Getting Help + +- Join our [Discord server](https://discord.gg/Sk3VfrHrN4) +- Open an issue for questions or bugs +- Check existing issues and PRs for similar work diff --git a/docs/src/development/releases.md b/docs/src/development/releases.md new file mode 100644 index 00000000..b2138f10 --- /dev/null +++ b/docs/src/development/releases.md @@ -0,0 +1,3 @@ +# Releases + +Documentation coming soon. diff --git a/docs/src/development/testing.md b/docs/src/development/testing.md new file mode 100644 index 00000000..0b1c46a8 --- /dev/null +++ b/docs/src/development/testing.md @@ -0,0 +1,3 @@ +# Testing + +Documentation coming soon. diff --git a/docs/src/examples/connection-manager.md b/docs/src/examples/connection-manager.md new file mode 100644 index 00000000..60efaded --- /dev/null +++ b/docs/src/examples/connection-manager.md @@ -0,0 +1,3 @@ +# Connection Manager + +Documentation coming soon. diff --git a/docs/src/examples/enterprise-wifi.md b/docs/src/examples/enterprise-wifi.md new file mode 100644 index 00000000..489dadb1 --- /dev/null +++ b/docs/src/examples/enterprise-wifi.md @@ -0,0 +1,3 @@ +# Enterprise Wifi + +Documentation coming soon. diff --git a/docs/src/examples/network-monitor.md b/docs/src/examples/network-monitor.md new file mode 100644 index 00000000..01e5964e --- /dev/null +++ b/docs/src/examples/network-monitor.md @@ -0,0 +1,3 @@ +# Network Monitor + +Documentation coming soon. diff --git a/docs/src/examples/wifi-auto-connect.md b/docs/src/examples/wifi-auto-connect.md new file mode 100644 index 00000000..d3b48ceb --- /dev/null +++ b/docs/src/examples/wifi-auto-connect.md @@ -0,0 +1,3 @@ +# Wifi Auto Connect + +Documentation coming soon. diff --git a/docs/src/examples/wifi-scanner.md b/docs/src/examples/wifi-scanner.md new file mode 100644 index 00000000..f95d7a68 --- /dev/null +++ b/docs/src/examples/wifi-scanner.md @@ -0,0 +1,260 @@ +# Basic WiFi Scanner + +This example demonstrates building a simple but complete WiFi network scanner using nmrs. + +## Features + +- Lists all available WiFi networks +- Shows signal strength with visual indicators +- Displays security types +- Filters by signal strength +- Auto-refreshes every few seconds + +## Complete Code + +```rust +use nmrs::{NetworkManager, models::Network}; +use std::time::Duration; +use tokio::time::sleep; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + // Initialize NetworkManager + let nm = NetworkManager::new().await?; + + println!("WiFi Network Scanner"); + println!("===================\n"); + + // Scan loop + loop { + // Clear screen (Unix/Linux) + print!("\x1B[2J\x1B[1;1H"); + + // Get networks + let mut networks = nm.list_networks().await?; + + // Sort by signal strength (strongest first) + networks.sort_by(|a, b| { + b.strength.unwrap_or(0).cmp(&a.strength.unwrap_or(0)) + }); + + // Display header + println!("WiFi Network Scanner - {} networks found\n", networks.len()); + println!("{:<30} {:>10} {:>8} {:<20}", + "SSID", "Signal", "Band", "Security"); + println!("{}", "-".repeat(70)); + + // Display each network + for net in networks { + print_network(&net); + } + + println!("\n{}", "-".repeat(70)); + println!("Press Ctrl+C to exit"); + + // Wait before next scan + sleep(Duration::from_secs(5)).await; + } +} + +fn print_network(net: &Network) { + let signal = net.strength.unwrap_or(0); + let signal_bar = signal_strength_bar(signal); + + let band = match net.frequency { + Some(freq) if freq > 5000 => "5GHz", + Some(_) => "2.4GHz", + None => "Unknown", + }; + + let security = match &net.security { + nmrs::WifiSecurity::Open => "Open", + nmrs::WifiSecurity::WpaPsk { .. } => "WPA-PSK", + nmrs::WifiSecurity::WpaEap { .. } => "WPA-EAP", + }; + + println!("{:<30} {:>3}% {} {:>8} {:<20}", + truncate_ssid(&net.ssid, 30), + signal, + signal_bar, + band, + security + ); +} + +fn signal_strength_bar(strength: u8) -> String { + let bars = match strength { + 80..=100 => "▂▄▆█", + 60..=79 => "▂▄▆▁", + 40..=59 => "▂▄▁▁", + 20..=39 => "▂▁▁▁", + _ => "▁▁▁▁", + }; + + let color = match strength { + 70..=100 => "\x1b[32m", // Green + 40..=69 => "\x1b[33m", // Yellow + _ => "\x1b[31m", // Red + }; + + format!("{}{}\x1b[0m", color, bars) +} + +fn truncate_ssid(ssid: &str, max_len: usize) -> String { + if ssid.len() <= max_len { + ssid.to_string() + } else { + format!("{}...", &ssid[..max_len - 3]) + } +} +``` + +## Running the Example + +Add to your `Cargo.toml`: + +```toml +[dependencies] +nmrs = "2.0.0" +tokio = { version = "1", features = ["full"] } +``` + +Run with: + +```bash +cargo run +``` + +## Sample Output + +``` +WiFi Network Scanner - 8 networks found + +SSID Signal Band Security +---------------------------------------------------------------------- +MyHomeNetwork 92% ▂▄▆█ 5GHz WPA-PSK +CoffeeShop_Guest 78% ▂▄▆▁ 2.4GHz Open +Neighbor-5G 65% ▂▄▆▁ 5GHz WPA-PSK +Corporate_WiFi 58% ▂▄▁▁ 5GHz WPA-EAP +Guest_Network 45% ▂▄▁▁ 2.4GHz Open +FarAwayNetwork 22% ▂▁▁▁ 2.4GHz WPA-PSK + +---------------------------------------------------------------------- +Press Ctrl+C to exit +``` + +## Enhancements + +### Filter by Signal Strength + +```rust +// Only show networks with signal > 30% +let networks: Vec<_> = networks + .into_iter() + .filter(|n| n.strength.unwrap_or(0) > 30) + .collect(); +``` + +### Group by Frequency Band + +```rust +let mut networks_2_4ghz = Vec::new(); +let mut networks_5ghz = Vec::new(); + +for net in networks { + match net.frequency { + Some(freq) if freq > 5000 => networks_5ghz.push(net), + Some(_) => networks_2_4ghz.push(net), + None => {} + } +} + +println!("\n5GHz Networks:"); +for net in networks_5ghz { + print_network(&net); +} + +println!("\n2.4GHz Networks:"); +for net in networks_2_4ghz { + print_network(&net); +} +``` + +### Add Connection Capability + +```rust +use std::io::{self, Write}; + +// After displaying networks +print!("\nEnter number to connect (or 0 to skip): "); +io::stdout().flush()?; + +let mut input = String::new(); +io::stdin().read_line(&mut input)?; + +if let Ok(choice) = input.trim().parse::() { + if choice > 0 && choice <= networks.len() { + let selected = &networks[choice - 1]; + + // Get password if needed + match &selected.security { + nmrs::WifiSecurity::Open => { + nm.connect(&selected.ssid, nmrs::WifiSecurity::Open).await?; + println!("Connected to {}", selected.ssid); + } + _ => { + print!("Enter password: "); + io::stdout().flush()?; + let mut password = String::new(); + io::stdin().read_line(&mut password)?; + + nm.connect(&selected.ssid, nmrs::WifiSecurity::WpaPsk { + psk: password.trim().to_string() + }).await?; + println!("Connected to {}", selected.ssid); + } + } + } +} +``` + +### Export to JSON + +```rust +use serde::{Serialize, Deserialize}; + +#[derive(Serialize)] +struct NetworkExport { + ssid: String, + signal: u8, + frequency: Option, + security: String, +} + +// Convert networks to exportable format +let exports: Vec = networks.iter().map(|n| { + NetworkExport { + ssid: n.ssid.clone(), + signal: n.strength.unwrap_or(0), + frequency: n.frequency, + security: format!("{:?}", n.security), + } +}).collect(); + +// Write to file +let json = serde_json::to_string_pretty(&exports)?; +std::fs::write("networks.json", json)?; +println!("Exported to networks.json"); +``` + +## Related Examples + +- [WiFi Auto-Connect](./wifi-auto-connect.md) +- [Network Monitor Dashboard](./network-monitor.md) +- [Connection Manager](./connection-manager.md) + +## See Also + +- [WiFi Management Guide](../guide/wifi.md) +- [Scanning Networks](../guide/wifi-scanning.md) +- [API Reference](../api/network-manager.md) diff --git a/docs/src/examples/wireguard-client.md b/docs/src/examples/wireguard-client.md new file mode 100644 index 00000000..8a24f443 --- /dev/null +++ b/docs/src/examples/wireguard-client.md @@ -0,0 +1,3 @@ +# Wireguard Client + +Documentation coming soon. diff --git a/docs/src/getting-started/installation.md b/docs/src/getting-started/installation.md new file mode 100644 index 00000000..5309b0b4 --- /dev/null +++ b/docs/src/getting-started/installation.md @@ -0,0 +1,145 @@ +# Installation + +This guide covers installation for both the **nmrs library** (for developers) and **nmrs-gui** (for end users). + +## nmrs Library + +### Using Cargo + +The easiest way to add nmrs to your project: + +```bash +cargo add nmrs +``` + +Or manually add to your `Cargo.toml`: + +```toml +[dependencies] +nmrs = "2.0.0" +``` + +### From Source + +Clone and build from source: + +```bash +git clone https://github.com/cachebag/nmrs.git +cd nmrs/nmrs +cargo build --release +``` + +### Verify Installation + +Create a simple test to verify nmrs is working: + +```rust +use nmrs::NetworkManager; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + println!("nmrs is working!"); + Ok(()) +} +``` + +## nmrs-gui Application + +### Arch Linux (AUR) + +For Arch Linux users, install from the AUR: + +```bash +yay -S nmrs +# or +paru -S nmrs +``` + +### Nix/NixOS + +Install via Nix: + +```bash +nix-shell -p nmrs +``` + +Or add to your NixOS configuration: + +```nix +environment.systemPackages = with pkgs; [ + nmrs +]; +``` + +### From Source (GUI) + +Requirements: +- Rust 1.85.1 or later +- GTK4 development libraries +- libadwaita + +```bash +# Install dependencies (Arch Linux) +sudo pacman -S gtk4 libadwaita + +# Install dependencies (Ubuntu/Debian) +sudo apt install libgtk-4-dev libadwaita-1-dev + +# Install dependencies (Fedora) +sudo dnf install gtk4-devel libadwaita-devel + +# Build and install +git clone https://github.com/cachebag/nmrs.git +cd nmrs +cargo build --release -p nmrs-gui +sudo cp target/release/nmrs-gui /usr/local/bin/nmrs +``` + +## System Requirements + +### For the Library (nmrs) +- **Operating System**: Linux (any modern distribution) +- **Rust**: 1.78.0 or later +- **NetworkManager**: Version 1.0 or later, running and accessible via D-Bus +- **D-Bus**: System bus must be available + +### For the GUI (nmrs-gui) +All of the above, plus: +- **Rust**: 1.85.1 or later +- **GTK4**: Version 4.0 or later +- **libadwaita**: For modern GNOME styling +- **Wayland** or **X11**: Display server + +## Permissions + +nmrs requires permission to manage network connections. On most systems, this is handled by PolicyKit. Ensure your user is in the appropriate groups: + +```bash +# Check if you're in the network group +groups + +# Add yourself to the network group if needed (requires logout/login) +sudo usermod -aG network $USER +``` + +## Verify NetworkManager + +Ensure NetworkManager is running: + +```bash +systemctl status NetworkManager +``` + +If it's not running: + +```bash +sudo systemctl start NetworkManager +sudo systemctl enable NetworkManager # Start on boot +``` + +## Next Steps + +- **Library Users**: Continue to the [Quick Start](./quick-start.md) guide +- **GUI Users**: See the [GUI Configuration](../gui/configuration.md) guide +- **Having Issues?**: Check [Troubleshooting](../appendix/troubleshooting.md) diff --git a/docs/src/getting-started/quick-start.md b/docs/src/getting-started/quick-start.md new file mode 100644 index 00000000..42ad4188 --- /dev/null +++ b/docs/src/getting-started/quick-start.md @@ -0,0 +1,310 @@ +# Quick Start + +This guide will get you up and running with nmrs in minutes. + +## Prerequisites + +Make sure you have: +- Rust installed (1.78.0+) +- NetworkManager running on your Linux system +- Basic familiarity with async Rust + +## Create a New Project + +```bash +cargo new nmrs-demo +cd nmrs-demo +cargo add nmrs tokio --features tokio/full +``` + +## Your First nmrs Program + +Let's create a simple program that lists available WiFi networks: + +```rust +use nmrs::NetworkManager; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + // Initialize NetworkManager connection + let nm = NetworkManager::new().await?; + + // List all available networks + let networks = nm.list_networks().await?; + + // Print network information + for network in networks { + println!( + "SSID: {:<20} Signal: {:>3}% Security: {:?}", + network.ssid, + network.strength.unwrap_or(0), + network.security + ); + } + + Ok(()) +} +``` + +Run it: + +```bash +cargo run +``` + +You should see output like: + +``` +SSID: MyHomeNetwork Signal: 85% Security: WpaPsk +SSID: CoffeeShopWiFi Signal: 62% Security: Open +SSID: Neighbor5G Signal: 45% Security: WpaEap +``` + +## Connecting to a Network + +Now let's connect to a WiFi network: + +```rust +use nmrs::{NetworkManager, WifiSecurity}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + // Connect to a WPA-PSK protected network + nm.connect("MyHomeNetwork", WifiSecurity::WpaPsk { + psk: "your_password_here".into() + }).await?; + + println!("Connected successfully!"); + + // Verify the connection + if let Some(ssid) = nm.current_ssid().await { + println!("Current network: {}", ssid); + } + + Ok(()) +} +``` + +## Error Handling + +nmrs provides detailed error types for better error handling: + +```rust +use nmrs::{NetworkManager, WifiSecurity, ConnectionError}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + match nm.connect("MyNetwork", WifiSecurity::WpaPsk { + psk: "password123".into() + }).await { + Ok(_) => println!("✓ Connected successfully"), + Err(ConnectionError::AuthFailed) => { + eprintln!("✗ Authentication failed - wrong password?"); + } + Err(ConnectionError::NotFound) => { + eprintln!("✗ Network not found or out of range"); + } + Err(ConnectionError::Timeout) => { + eprintln!("✗ Connection timed out"); + } + Err(ConnectionError::DhcpFailed) => { + eprintln!("✗ Failed to obtain IP address"); + } + Err(e) => eprintln!("✗ Error: {}", e), + } + + Ok(()) +} +``` + +## Device Management + +List all network devices: + +```rust +use nmrs::NetworkManager; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + let devices = nm.list_devices().await?; + + for device in devices { + println!( + "Interface: {:<10} Type: {:<10} State: {:?}", + device.interface, + device.device_type, + device.state + ); + } + + Ok(()) +} +``` + +## Working with Connection Profiles + +List saved connection profiles: + +```rust +use nmrs::NetworkManager; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + let profiles = nm.list_connections().await?; + + println!("Saved connections:"); + for profile in profiles { + println!(" - {}", profile); + } + + Ok(()) +} +``` + +## Real-Time Monitoring + +Monitor network changes: + +```rust +use nmrs::NetworkManager; +use std::sync::Arc; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = Arc::new(NetworkManager::new().await?); + let nm_clone = nm.clone(); + + // Monitor network changes + nm.monitor_network_changes(move || { + println!("Networks changed! Scanning..."); + // In a real app, you'd update your UI here + }).await?; + + // Keep the program running + tokio::signal::ctrl_c().await.ok(); + Ok(()) +} +``` + +## Complete Example: Network Scanner + +Here's a complete example that puts it all together: + +```rust +use nmrs::{NetworkManager, WifiSecurity}; +use std::io::{self, Write}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + println!("Scanning for networks...\n"); + let networks = nm.list_networks().await?; + + // Display networks with numbering + for (i, net) in networks.iter().enumerate() { + println!( + "{:2}. {:<25} Signal: {:>3}% {:?}", + i + 1, + net.ssid, + net.strength.unwrap_or(0), + net.security + ); + } + + // Get user input + print!("\nEnter network number to connect (or 0 to exit): "); + io::stdout().flush().unwrap(); + + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + + let choice: usize = input.trim().parse().unwrap_or(0); + + if choice == 0 || choice > networks.len() { + println!("Exiting..."); + return Ok(()); + } + + let selected = &networks[choice - 1]; + + // Ask for password if needed + let security = match selected.security { + nmrs::models::WifiSecurity::Open => WifiSecurity::Open, + _ => { + print!("Enter password: "); + io::stdout().flush().unwrap(); + let mut password = String::new(); + io::stdin().read_line(&mut password).unwrap(); + WifiSecurity::WpaPsk { + psk: password.trim().to_string() + } + } + }; + + // Connect + println!("Connecting to {}...", selected.ssid); + nm.connect(&selected.ssid, security).await?; + + println!("✓ Connected successfully!"); + + Ok(()) +} +``` + +## Next Steps + +Now that you've got the basics, explore more features: + +- [WiFi Management](../guide/wifi.md) - Advanced WiFi features +- [VPN Connections](../guide/vpn.md) - Set up WireGuard VPNs +- [Device Management](../guide/devices.md) - Control network devices +- [Error Handling](../guide/error-handling.md) - Comprehensive error handling +- [Examples](../examples/wifi-scanner.md) - More complete examples + +## Using Different Async Runtimes + +nmrs works with any async runtime. Here are examples with popular runtimes: + +### async-std + +```toml +[dependencies] +nmrs = "2.0.0" +async-std = { version = "1.12", features = ["attributes"] } +``` + +```rust +#[async_std::main] +async fn main() -> nmrs::Result<()> { + let nm = nmrs::NetworkManager::new().await?; + // ... your code + Ok(()) +} +``` + +### smol + +```toml +[dependencies] +nmrs = "2.0.0" +smol = "2.0" +``` + +```rust +fn main() -> nmrs::Result<()> { + smol::block_on(async { + let nm = nmrs::NetworkManager::new().await?; + // ... your code + Ok(()) + }) +} +``` diff --git a/docs/src/getting-started/requirements.md b/docs/src/getting-started/requirements.md new file mode 100644 index 00000000..685914b5 --- /dev/null +++ b/docs/src/getting-started/requirements.md @@ -0,0 +1,275 @@ +# Requirements + +This page details all the requirements needed to use nmrs effectively. + +## System Requirements + +### Operating System + +nmrs is **Linux-only** and requires: + +- Any modern Linux distribution (kernel 3.10+) +- NetworkManager 1.0 or later +- D-Bus system bus + +Tested on: +- Arch Linux +- Ubuntu 20.04+ +- Fedora 35+ +- Debian 11+ +- NixOS + +### NetworkManager + +NetworkManager must be: +- Installed on your system +- Running and accessible via D-Bus +- Version 1.0 or later (1.46+ recommended for latest features) + +Check your NetworkManager version: + +```bash +NetworkManager --version +``` + +Ensure it's running: + +```bash +systemctl status NetworkManager +``` + +### D-Bus + +The D-Bus system bus must be available and running. This is standard on all modern Linux distributions. + +Verify D-Bus is working: + +```bash +dbus-send --system --print-reply \ + --dest=org.freedesktop.NetworkManager \ + /org/freedesktop/NetworkManager \ + org.freedesktop.DBus.Properties.Get \ + string:'org.freedesktop.NetworkManager' \ + string:'Version' +``` + +## Rust Requirements + +### For nmrs Library + +- **Rust**: 1.78.0 or later +- **Edition**: 2021 + +The library uses stable Rust features only. + +### For nmrs-gui + +- **Rust**: 1.85.1 or later +- **Edition**: 2021 + +The GUI requires a newer Rust version due to GTK4 bindings. + +## Dependencies + +### nmrs Library Dependencies + +The library depends on: + +- `zbus` 5.x - D-Bus communication +- `tokio` or another async runtime +- `serde` - Serialization +- `thiserror` - Error handling +- `futures` - Async utilities + +All dependencies are automatically handled by Cargo. + +### nmrs-gui Dependencies + +Additional system libraries required: + +**Arch Linux:** +```bash +sudo pacman -S gtk4 libadwaita +``` + +**Ubuntu/Debian:** +```bash +sudo apt install libgtk-4-dev libadwaita-1-dev build-essential +``` + +**Fedora:** +```bash +sudo dnf install gtk4-devel libadwaita-devel +``` + +**NixOS:** +```nix +# Handled automatically by the Nix package +``` + +## Permissions + +### PolicyKit + +nmrs needs permission to manage network connections. This is typically handled by PolicyKit on modern Linux systems. + +### User Groups + +Your user should be in the appropriate groups. On most systems: + +```bash +# Check current groups +groups + +# Add to network group (may vary by distribution) +sudo usermod -aG network $USER +``` + +On some distributions, no special group is needed if PolicyKit is properly configured. + +### Running as Root + +While nmrs can run as root, it's **not recommended** for security reasons. Use PolicyKit instead. + +## Hardware Requirements + +### WiFi + +- A WiFi adapter supported by NetworkManager +- WiFi hardware must be recognized by the Linux kernel + +Check your WiFi adapter: + +```bash +nmcli device status +``` + +### Ethernet + +- Network interface card (NIC) +- Recognized by the Linux kernel + +### Bluetooth + +For Bluetooth network features: +- Bluetooth adapter +- BlueZ stack installed and running + +### VPN + +For WireGuard VPN: +- WireGuard kernel module or userspace implementation +- WireGuard tools (usually bundled with NetworkManager) + +Check WireGuard support: + +```bash +modprobe wireguard +lsmod | grep wireguard +``` + +Or use userspace implementation (automatic with NetworkManager 1.16+). + +## Development Requirements + +Additional requirements for developing nmrs: + +### Testing + +- `docker` and `docker-compose` (for containerized testing) +- WiFi hardware or `mac80211_hwsim` kernel module + +### Building Documentation + +- `mdbook` for this documentation +- `cargo-doc` for API documentation + +### IDE/Editor + +Recommended: +- rust-analyzer +- clippy +- rustfmt + +## Optional Dependencies + +### Logging + +For detailed logging, use any logger that implements the `log` facade: + +```toml +[dependencies] +env_logger = "0.11" +``` + +### TLS/Certificates + +For WPA-EAP with certificate validation: +- CA certificates installed in system certificate store +- OpenSSL or rustls (handled by NetworkManager) + +## Troubleshooting + +### NetworkManager Not Found + +If you get "Failed to connect to D-Bus": + +```bash +# Check if NetworkManager is running +systemctl status NetworkManager + +# Start it if needed +sudo systemctl start NetworkManager + +# Enable it to start on boot +sudo systemctl enable NetworkManager +``` + +### Permission Denied + +If you get permission errors: + +1. Check PolicyKit rules: `/usr/share/polkit-1/actions/org.freedesktop.NetworkManager.policy` +2. Ensure D-Bus is accessible: `ls -l /var/run/dbus/system_bus_socket` +3. Try with PolicyKit agent running + +### Dependency Issues + +For build issues: + +```bash +# Update Rust +rustup update stable + +# Clear Cargo cache +cargo clean + +# Update dependencies +cargo update +``` + +## Version Compatibility + +### nmrs Library + +| nmrs Version | Minimum Rust | NetworkManager | Notable Features | +|--------------|--------------|----------------|------------------| +| 2.0.0 | 1.78.0 | 1.0+ | Full API rewrite | +| 1.x | 1.70.0 | 1.0+ | Initial release | + +### nmrs-gui + +| GUI Version | Minimum Rust | GTK | Notable Features | +|-------------|--------------|-----|------------------| +| 1.1.0 | 1.85.1 | 4.0 | Themes support | +| 1.0.0 | 1.82.0 | 4.0 | Initial release | + +## Next Steps + +Once you have all requirements met: + +1. [Install nmrs](./installation.md) +2. [Follow the Quick Start guide](./quick-start.md) +3. Start building with [WiFi Management](../guide/wifi.md) + +If you encounter issues, see [Troubleshooting](../appendix/troubleshooting.md). diff --git a/docs/src/gui/configuration.md b/docs/src/gui/configuration.md new file mode 100644 index 00000000..c9f372cd --- /dev/null +++ b/docs/src/gui/configuration.md @@ -0,0 +1,3 @@ +# Configuration + +Documentation coming soon. diff --git a/docs/src/gui/installation.md b/docs/src/gui/installation.md new file mode 100644 index 00000000..502a6811 --- /dev/null +++ b/docs/src/gui/installation.md @@ -0,0 +1,3 @@ +# Installation + +Documentation coming soon. diff --git a/docs/src/gui/overview.md b/docs/src/gui/overview.md new file mode 100644 index 00000000..ff9716a2 --- /dev/null +++ b/docs/src/gui/overview.md @@ -0,0 +1,3 @@ +# Overview + +Documentation coming soon. diff --git a/docs/src/gui/themes.md b/docs/src/gui/themes.md new file mode 100644 index 00000000..d0198862 --- /dev/null +++ b/docs/src/gui/themes.md @@ -0,0 +1,3 @@ +# Themes + +Documentation coming soon. diff --git a/docs/src/gui/waybar.md b/docs/src/gui/waybar.md new file mode 100644 index 00000000..0b45deda --- /dev/null +++ b/docs/src/gui/waybar.md @@ -0,0 +1,3 @@ +# Waybar + +Documentation coming soon. diff --git a/docs/src/guide/bluetooth.md b/docs/src/guide/bluetooth.md new file mode 100644 index 00000000..1a15a524 --- /dev/null +++ b/docs/src/guide/bluetooth.md @@ -0,0 +1,3 @@ +# Bluetooth + +Documentation coming soon. diff --git a/docs/src/guide/devices.md b/docs/src/guide/devices.md new file mode 100644 index 00000000..1d381367 --- /dev/null +++ b/docs/src/guide/devices.md @@ -0,0 +1,3 @@ +# Devices + +Documentation coming soon. diff --git a/docs/src/guide/error-handling.md b/docs/src/guide/error-handling.md new file mode 100644 index 00000000..e21eb39b --- /dev/null +++ b/docs/src/guide/error-handling.md @@ -0,0 +1,3 @@ +# Error Handling + +Documentation coming soon. diff --git a/docs/src/guide/ethernet.md b/docs/src/guide/ethernet.md new file mode 100644 index 00000000..f4605b7d --- /dev/null +++ b/docs/src/guide/ethernet.md @@ -0,0 +1,3 @@ +# Ethernet + +Documentation coming soon. diff --git a/docs/src/guide/monitoring.md b/docs/src/guide/monitoring.md new file mode 100644 index 00000000..9d50db4d --- /dev/null +++ b/docs/src/guide/monitoring.md @@ -0,0 +1,3 @@ +# Monitoring + +Documentation coming soon. diff --git a/docs/src/guide/profiles.md b/docs/src/guide/profiles.md new file mode 100644 index 00000000..558cdbd1 --- /dev/null +++ b/docs/src/guide/profiles.md @@ -0,0 +1,3 @@ +# Profiles + +Documentation coming soon. diff --git a/docs/src/guide/vpn-management.md b/docs/src/guide/vpn-management.md new file mode 100644 index 00000000..988d63a7 --- /dev/null +++ b/docs/src/guide/vpn-management.md @@ -0,0 +1,3 @@ +# Vpn Management + +Documentation coming soon. diff --git a/docs/src/guide/vpn-wireguard.md b/docs/src/guide/vpn-wireguard.md new file mode 100644 index 00000000..1431a80c --- /dev/null +++ b/docs/src/guide/vpn-wireguard.md @@ -0,0 +1,3 @@ +# Vpn Wireguard + +Documentation coming soon. diff --git a/docs/src/guide/vpn.md b/docs/src/guide/vpn.md new file mode 100644 index 00000000..1edcedae --- /dev/null +++ b/docs/src/guide/vpn.md @@ -0,0 +1,406 @@ +# VPN Connections + +nmrs provides full support for WireGuard VPN connections through NetworkManager. This guide covers everything you need to know about managing VPNs with nmrs. + +## Overview + +VPN support includes: +- **WireGuard** - Modern, fast, secure VPN protocol +- **Profile Management** - Save and reuse VPN configurations +- **Connection Control** - Connect, disconnect, monitor VPN status +- **Multiple Peers** - Support for multiple WireGuard peers +- **Custom DNS** - Override DNS servers for VPN connections +- **MTU Configuration** - Optimize packet sizes + +## Quick Start + +Basic WireGuard VPN connection: + +```rust +use nmrs::{NetworkManager, VpnCredentials, VpnType, WireGuardPeer}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + // Create a WireGuard peer + let peer = WireGuardPeer::new( + "server_public_key_here", + "vpn.example.com:51820", + vec!["0.0.0.0/0".into()], // Route all traffic through VPN + ).with_persistent_keepalive(25); + + // Create VPN credentials + let creds = VpnCredentials::new( + VpnType::WireGuard, + "MyVPN", + "vpn.example.com:51820", + "your_private_key_here", + "10.0.0.2/24", // Your VPN IP + vec![peer], + ).with_dns(vec!["1.1.1.1".into()]); + + // Connect + nm.connect_vpn(creds).await?; + println!("Connected to VPN!"); + + Ok(()) +} +``` + +## VPN Credentials + +The `VpnCredentials` struct contains all necessary VPN configuration: + +```rust +pub struct VpnCredentials { + pub vpn_type: VpnType, + pub name: String, + pub gateway: String, + pub private_key: String, + pub address: String, + pub peers: Vec, + pub dns: Option>, + pub mtu: Option, + pub uuid: Option, +} +``` + +### Creating Credentials + +```rust +use nmrs::{VpnCredentials, VpnType, WireGuardPeer}; + +let peer = WireGuardPeer::new( + "base64_public_key", + "vpn.example.com:51820", + vec!["0.0.0.0/0".into()], +); + +let creds = VpnCredentials::new( + VpnType::WireGuard, + "WorkVPN", // Connection name + "vpn.example.com:51820", // Gateway + "base64_private_key", // Your private key + "10.0.0.2/24", // Your VPN IP address + vec![peer], // WireGuard peers +); +``` + +### With Custom DNS + +```rust +let creds = VpnCredentials::new( + VpnType::WireGuard, + "MyVPN", + "vpn.example.com:51820", + "private_key", + "10.0.0.2/24", + vec![peer], +).with_dns(vec![ + "1.1.1.1".into(), + "8.8.8.8".into(), +]); +``` + +### With Custom MTU + +```rust +let creds = creds.with_mtu(1420); // Standard WireGuard MTU +``` + +## WireGuard Peers + +Each WireGuard connection can have multiple peers: + +```rust +pub struct WireGuardPeer { + pub public_key: String, + pub gateway: String, + pub allowed_ips: Vec, + pub preshared_key: Option, + pub persistent_keepalive: Option, +} +``` + +### Creating Peers + +```rust +use nmrs::WireGuardPeer; + +// Basic peer +let peer = WireGuardPeer::new( + "peer_public_key", + "vpn.example.com:51820", + vec!["0.0.0.0/0".into()], +); + +// Peer with keepalive +let peer = WireGuardPeer::new( + "peer_public_key", + "vpn.example.com:51820", + vec!["0.0.0.0/0".into()], +).with_persistent_keepalive(25); + +// Peer with preshared key +let peer = peer.with_preshared_key("base64_preshared_key"); +``` + +### Multiple Peers + +```rust +let peer1 = WireGuardPeer::new( + "peer1_public_key", + "vpn1.example.com:51820", + vec!["10.0.0.0/8".into()], +); + +let peer2 = WireGuardPeer::new( + "peer2_public_key", + "vpn2.example.com:51820", + vec!["192.168.0.0/16".into()], +); + +let creds = VpnCredentials::new( + VpnType::WireGuard, + "MultiPeerVPN", + "vpn1.example.com:51820", + "private_key", + "10.0.0.2/24", + vec![peer1, peer2], // Multiple peers +); +``` + +## VPN Operations + +### Connect to VPN + +```rust +nm.connect_vpn(creds).await?; +``` + +### Disconnect from VPN + +```rust +nm.disconnect_vpn("MyVPN").await?; +``` + +### List VPN Connections + +```rust +let vpns = nm.list_vpn_connections().await?; + +for vpn in vpns { + println!("Name: {}", vpn.name); + println!("Type: {:?}", vpn.vpn_type); + println!("State: {:?}", vpn.state); +} +``` + +### Get VPN Information + +```rust +let info = nm.get_vpn_info("MyVPN").await?; + +println!("VPN State: {:?}", info.state); +if let Some(ip) = info.ip4_address { + println!("VPN IP: {}", ip); +} +if let Some(device) = info.device { + println!("Device: {}", device); +} +``` + +### Check if VPN is Active + +```rust +let vpns = nm.list_vpn_connections().await?; +let active = vpns.iter().any(|v| { + matches!(v.state, nmrs::models::ActiveConnectionState::Activated) +}); + +if active { + println!("VPN is active"); +} else { + println!("VPN is not active"); +} +``` + +## Routing Configuration + +### Route All Traffic + +Send all traffic through the VPN: + +```rust +let peer = WireGuardPeer::new( + "public_key", + "vpn.example.com:51820", + vec!["0.0.0.0/0".into()], // All IPv4 +); +``` + +### Split Tunnel + +Route only specific networks through VPN: + +```rust +let peer = WireGuardPeer::new( + "public_key", + "vpn.example.com:51820", + vec![ + "10.0.0.0/8".into(), // Private network + "192.168.0.0/16".into(), // Another private network + ], +); +``` + +### IPv6 Support + +```rust +let peer = WireGuardPeer::new( + "public_key", + "vpn.example.com:51820", + vec![ + "0.0.0.0/0".into(), // All IPv4 + "::/0".into(), // All IPv6 + ], +); +``` + +## Error Handling + +Handle VPN-specific errors: + +```rust +use nmrs::ConnectionError; + +match nm.connect_vpn(creds).await { + Ok(_) => println!("VPN connected"), + + Err(ConnectionError::AuthFailed) => { + eprintln!("VPN authentication failed - check keys"); + } + + Err(ConnectionError::Timeout) => { + eprintln!("VPN connection timed out - check gateway"); + } + + Err(ConnectionError::NotFound) => { + eprintln!("VPN gateway not reachable"); + } + + Err(e) => eprintln!("VPN error: {}", e), +} +``` + +## Complete Example + +Here's a complete VPN client: + +```rust +use nmrs::{NetworkManager, VpnCredentials, VpnType, WireGuardPeer}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + // Check if already connected + let vpns = nm.list_vpn_connections().await?; + if let Some(active_vpn) = vpns.iter().find(|v| { + matches!(v.state, nmrs::models::ActiveConnectionState::Activated) + }) { + println!("Already connected to: {}", active_vpn.name); + return Ok(()); + } + + // Create WireGuard configuration + let peer = WireGuardPeer::new( + std::env::var("WG_PUBLIC_KEY")?, + std::env::var("WG_ENDPOINT")?, + vec!["0.0.0.0/0".into()], + ).with_persistent_keepalive(25); + + let creds = VpnCredentials::new( + VpnType::WireGuard, + "AutoVPN", + std::env::var("WG_ENDPOINT")?, + std::env::var("WG_PRIVATE_KEY")?, + std::env::var("WG_ADDRESS")?, + vec![peer], + ).with_dns(vec!["1.1.1.1".into(), "8.8.8.8".into()]); + + // Connect + println!("Connecting to VPN..."); + nm.connect_vpn(creds).await?; + + // Verify connection + let info = nm.get_vpn_info("AutoVPN").await?; + println!("Connected! VPN IP: {:?}", info.ip4_address); + + // Keep connection alive + println!("Press Ctrl+C to disconnect..."); + tokio::signal::ctrl_c().await?; + + // Disconnect + nm.disconnect_vpn("AutoVPN").await?; + println!("Disconnected from VPN"); + + Ok(()) +} +``` + +## Advanced Topics + +For more advanced VPN usage, see: + +- [WireGuard Setup](./vpn-wireguard.md) - Detailed WireGuard guide +- [VPN Management](./vpn-management.md) - Managing VPN profiles +- [Examples](../examples/wireguard-client.md) - Complete VPN client example + +## Security Best Practices + +1. **Never hardcode keys** - Use environment variables or secure storage +2. **Rotate keys regularly** - Update WireGuard keys periodically +3. **Use preshared keys** - Add extra layer of security with PSK +4. **Verify endpoints** - Ensure gateway addresses are correct +5. **Monitor connection** - Check VPN status regularly + +## Troubleshooting + +### VPN Won't Connect + +```rust +// Check if WireGuard is available +// NetworkManager should handle this automatically + +// Verify your credentials are correct +println!("Gateway: {}", creds.gateway); +println!("Address: {}", creds.address); +// Don't print private keys! +``` + +### Connection Drops + +Use persistent keepalive: + +```rust +let peer = peer.with_persistent_keepalive(25); // Send keepalive every 25s +``` + +### DNS Not Working + +Explicitly set DNS servers: + +```rust +let creds = creds.with_dns(vec![ + "1.1.1.1".into(), + "8.8.8.8".into(), +]); +``` + +## Next Steps + +- [WireGuard Setup Guide](./vpn-wireguard.md) +- [VPN Management](./vpn-management.md) +- [Complete VPN Client Example](../examples/wireguard-client.md) diff --git a/docs/src/guide/wifi-connecting.md b/docs/src/guide/wifi-connecting.md new file mode 100644 index 00000000..08f8853c --- /dev/null +++ b/docs/src/guide/wifi-connecting.md @@ -0,0 +1,3 @@ +# Wifi Connecting + +Documentation coming soon. diff --git a/docs/src/guide/wifi-enterprise.md b/docs/src/guide/wifi-enterprise.md new file mode 100644 index 00000000..41627ef3 --- /dev/null +++ b/docs/src/guide/wifi-enterprise.md @@ -0,0 +1,3 @@ +# Wifi Enterprise + +Documentation coming soon. diff --git a/docs/src/guide/wifi-hidden.md b/docs/src/guide/wifi-hidden.md new file mode 100644 index 00000000..c2b60f07 --- /dev/null +++ b/docs/src/guide/wifi-hidden.md @@ -0,0 +1,3 @@ +# Wifi Hidden + +Documentation coming soon. diff --git a/docs/src/guide/wifi-scanning.md b/docs/src/guide/wifi-scanning.md new file mode 100644 index 00000000..45c07a74 --- /dev/null +++ b/docs/src/guide/wifi-scanning.md @@ -0,0 +1,3 @@ +# Wifi Scanning + +Documentation coming soon. diff --git a/docs/src/guide/wifi-wpa-psk.md b/docs/src/guide/wifi-wpa-psk.md new file mode 100644 index 00000000..fa6a5215 --- /dev/null +++ b/docs/src/guide/wifi-wpa-psk.md @@ -0,0 +1,3 @@ +# Wifi Wpa Psk + +Documentation coming soon. diff --git a/docs/src/guide/wifi.md b/docs/src/guide/wifi.md new file mode 100644 index 00000000..cb1a7b77 --- /dev/null +++ b/docs/src/guide/wifi.md @@ -0,0 +1,319 @@ +# WiFi Management + +nmrs provides comprehensive WiFi management capabilities through the `NetworkManager` API. This chapter covers all WiFi-related operations. + +## Overview + +WiFi management in nmrs includes: + +- **Network Discovery** - Scan for available access points +- **Connection Management** - Connect, disconnect, and monitor connections +- **Security Support** - Open, WPA-PSK, WPA-EAP/Enterprise +- **Signal Monitoring** - Real-time signal strength updates +- **Profile Management** - Save and manage connection profiles +- **Advanced Features** - Hidden networks, custom DNS, static IP + +## Quick Reference + +```rust +use nmrs::{NetworkManager, WifiSecurity}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + // Scan for networks + let networks = nm.list_networks().await?; + + // Connect to WPA-PSK network + nm.connect("MyWiFi", WifiSecurity::WpaPsk { + psk: "password".into() + }).await?; + + // Get current connection + if let Some(ssid) = nm.current_ssid().await { + println!("Connected to: {}", ssid); + } + + // Disconnect + nm.disconnect().await?; + + Ok(()) +} +``` + +## Security Types + +nmrs supports all major WiFi security protocols: + +### Open Networks + +No authentication required: + +```rust +nm.connect("FreeWiFi", WifiSecurity::Open).await?; +``` + +### WPA-PSK (Personal) + +Password-based authentication: + +```rust +nm.connect("HomeWiFi", WifiSecurity::WpaPsk { + psk: "your_password".into() +}).await?; +``` + +### WPA-EAP (Enterprise) + +802.1X authentication with various methods: + +```rust +use nmrs::{WifiSecurity, EapOptions, EapMethod, Phase2}; + +let eap_opts = EapOptions::new("user@company.com", "password") + .with_method(EapMethod::Peap) + .with_phase2(Phase2::Mschapv2) + .with_domain_suffix_match("company.com"); + +nm.connect("CorpWiFi", WifiSecurity::WpaEap { + opts: eap_opts +}).await?; +``` + +## Network Information + +The `Network` struct contains detailed information about discovered networks: + +```rust +pub struct Network { + pub ssid: String, // Network name + pub strength: Option, // Signal strength (0-100) + pub security: WifiSecurity, // Security type + pub frequency: Option, // Frequency in MHz + pub hwaddress: Option, // BSSID/MAC address +} +``` + +Example usage: + +```rust +let networks = nm.list_networks().await?; + +for net in networks { + println!("SSID: {}", net.ssid); + + if let Some(strength) = net.strength { + println!(" Signal: {}%", strength); + + if strength > 70 { + println!(" Quality: Excellent"); + } else if strength > 50 { + println!(" Quality: Good"); + } else { + println!(" Quality: Weak"); + } + } + + if let Some(freq) = net.frequency { + let band = if freq > 5000 { "5GHz" } else { "2.4GHz" }; + println!(" Band: {}", band); + } +} +``` + +## Connection Options + +Customize connection behavior with `ConnectionOptions`: + +```rust +use nmrs::{NetworkManager, WifiSecurity, ConnectionOptions}; + +let opts = ConnectionOptions::new(true) // autoconnect + .with_priority(10) // higher = preferred + .with_ipv4_method("auto") // DHCP + .with_dns(vec!["1.1.1.1".into(), "8.8.8.8".into()]); + +// Note: Advanced connection options require using builders directly +// See the Advanced Topics section for details +``` + +## WiFi Radio Control + +Enable or disable WiFi hardware: + +```rust +// Disable WiFi (airplane mode) +nm.set_wifi_enabled(false).await?; + +// Enable WiFi +nm.set_wifi_enabled(true).await?; + +// Check WiFi status +let enabled = nm.is_wifi_enabled().await?; +println!("WiFi is {}", if enabled { "enabled" } else { "disabled" }); +``` + +## Network Scanning + +Trigger a fresh scan: + +```rust +// Request a scan (may take a few seconds) +nm.request_scan().await?; + +// Wait a moment for scan to complete +tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + +// Get updated results +let networks = nm.list_networks().await?; +``` + +## Detecting Connection State + +Check your current WiFi status: + +```rust +// Get current SSID +if let Some(ssid) = nm.current_ssid().await { + println!("Connected to: {}", ssid); +} else { + println!("Not connected"); +} + +// Get detailed network info +if let Some(info) = nm.current_network_info().await? { + println!("SSID: {}", info.ssid); + println!("IP: {:?}", info.ip4_address); + println!("Gateway: {:?}", info.gateway); + println!("DNS: {:?}", info.dns); +} +``` + +## Error Handling + +WiFi operations can fail for various reasons. Handle them gracefully: + +```rust +use nmrs::ConnectionError; + +match nm.connect("Network", WifiSecurity::WpaPsk { + psk: "pass".into() +}).await { + Ok(_) => println!("Connected!"), + + Err(ConnectionError::AuthFailed) => { + eprintln!("Wrong password"); + } + + Err(ConnectionError::NotFound) => { + eprintln!("Network not found - out of range?"); + } + + Err(ConnectionError::Timeout) => { + eprintln!("Connection timed out"); + } + + Err(ConnectionError::DhcpFailed) => { + eprintln!("Failed to get IP address"); + } + + Err(ConnectionError::NoSecrets) => { + eprintln!("Missing password or credentials"); + } + + Err(e) => eprintln!("Error: {}", e), +} +``` + +## Real-Time Updates + +Monitor WiFi networks in real-time: + +```rust +use std::sync::Arc; + +let nm = Arc::new(NetworkManager::new().await?); +let nm_clone = nm.clone(); + +nm.monitor_network_changes(move || { + println!("Network list changed!"); + // In a GUI app, you'd trigger a UI refresh here +}).await?; + +// Monitor device state (connection/disconnection) +nm.monitor_device_changes(|| { + println!("Device state changed!"); +}).await?; +``` + +## Related Guides + +- [Scanning Networks](./wifi-scanning.md) - Detailed scanning guide +- [Connecting to Networks](./wifi-connecting.md) - Connection details +- [WPA-PSK Networks](./wifi-wpa-psk.md) - Password-protected WiFi +- [WPA-EAP (Enterprise)](./wifi-enterprise.md) - Enterprise WiFi +- [Hidden Networks](./wifi-hidden.md) - Connecting to hidden SSIDs +- [Error Handling](./error-handling.md) - Comprehensive error guide + +## Best Practices + +### 1. Cache the NetworkManager Instance + +```rust +// Good - reuse the same instance +let nm = NetworkManager::new().await?; +nm.list_networks().await?; +nm.connect("WiFi", WifiSecurity::Open).await?; + +// Avoid - creating multiple instances +let nm1 = NetworkManager::new().await?; +nm1.list_networks().await?; +let nm2 = NetworkManager::new().await?; // Unnecessary +nm2.connect("WiFi", WifiSecurity::Open).await?; +``` + +### 2. Handle Signal Strength + +```rust +// Always check for None +if let Some(strength) = network.strength { + println!("Signal: {}%", strength); +} else { + println!("Signal: Unknown"); +} +``` + +### 3. Use Timeouts + +```rust +use tokio::time::{timeout, Duration}; + +// Wrap operations in timeouts +match timeout(Duration::from_secs(30), nm.connect("WiFi", security)).await { + Ok(Ok(_)) => println!("Connected"), + Ok(Err(e)) => eprintln!("Connection failed: {}", e), + Err(_) => eprintln!("Operation timed out"), +} +``` + +### 4. Monitor for Disconnections + +```rust +// Keep monitoring in the background +tokio::spawn(async move { + loop { + if nm.current_ssid().await.is_none() { + eprintln!("Disconnected!"); + // Attempt reconnection logic + } + tokio::time::sleep(Duration::from_secs(5)).await; + } +}); +``` + +## Next Steps + +- Learn about [VPN Connections](./vpn.md) +- Explore [Device Management](./devices.md) +- See complete [Examples](../examples/wifi-scanner.md) diff --git a/docs/src/introduction.md b/docs/src/introduction.md new file mode 100644 index 00000000..a35e43b3 --- /dev/null +++ b/docs/src/introduction.md @@ -0,0 +1,82 @@ +# Introduction + +Welcome to the **nmrs** documentation! This guide will help you understand and use nmrs, a powerful Rust library for managing network connections on Linux via NetworkManager. + +## What is nmrs? + +**nmrs** is a high-level, async Rust API for [NetworkManager](https://networkmanager.dev/) over [D-Bus](https://dbus.freedesktop.org/doc/dbus-specification.html). It provides: + +- **Simple WiFi Management** - Scan, connect, and manage wireless networks +- **VPN Support** - Full WireGuard VPN integration +- **Ethernet Control** - Manage wired network connections +- **Bluetooth** - Connect to Bluetooth network devices +- **Real-Time Monitoring** - Event-driven network state updates +- **Type Safety** - Comprehensive error handling with specific failure reasons +- **Async/Await** - Built on modern async Rust with runtime flexibility + +## Project Structure + +The nmrs project consists of two main components: + +### nmrs (Library) +The core Rust library providing NetworkManager bindings and network management capabilities. This is what you'll use if you're building applications that need to manage network connections programmatically. + +### nmrs-gui (Application) +A beautiful, Wayland-compatible GTK4 graphical interface for NetworkManager. Perfect for desktop users who want a modern network management GUI. + +## Why nmrs? + +### For Developers +- **Safe Abstractions** - No unsafe code, leveraging Rust's type system +- **Async-First** - Built for modern async Rust applications +- **Signal-Based** - Efficient D-Bus signal monitoring instead of polling +- **Well-Documented** - Comprehensive docs with examples for every feature +- **Runtime Agnostic** - Works with Tokio, async-std, smol, and more + +### For Users (nmrs-gui) +- **Modern UI** - Clean GTK4 interface with multiple themes +- **Wayland Native** - First-class Wayland support +- **Lightweight** - Fast and efficient +- **Customizable** - CSS-based theming system +- **DE Integration** - Works great with tiling WMs (Hyprland, Sway, i3) + +## Quick Example + +Here's a taste of what nmrs can do: + +```rust +use nmrs::{NetworkManager, WifiSecurity}; + +#[tokio::main] +async fn main() -> nmrs::Result<()> { + let nm = NetworkManager::new().await?; + + // Scan for networks + let networks = nm.list_networks().await?; + for net in networks { + println!("{} - {}%", net.ssid, net.strength.unwrap_or(0)); + } + + // Connect to a network + nm.connect("MyWiFi", WifiSecurity::WpaPsk { + psk: "password123".into() + }).await?; + + Ok(()) +} +``` + +## Community + +- **Discord**: Join our [Discord server](https://discord.gg/Sk3VfrHrN4) to chat with developers and users +- **GitHub**: Report issues, contribute, or browse the code at [github.com/cachebag/nmrs](https://github.com/cachebag/nmrs) +- **Crates.io**: Install from [crates.io/crates/nmrs](https://crates.io/crates/nmrs) +- **API Docs**: Full API reference at [docs.rs/nmrs](https://docs.rs/nmrs) + +## License + +nmrs is dual-licensed under MIT and Apache 2.0, giving you flexibility in how you use it. + +--- + +Ready to get started? Head to the [Installation](./getting-started/installation.md) guide! diff --git a/docs/theme/custom.css b/docs/theme/custom.css new file mode 100644 index 00000000..0dfed83a --- /dev/null +++ b/docs/theme/custom.css @@ -0,0 +1,72 @@ +:root { + --nmrs-primary: #e67e22; + --nmrs-secondary: #3498db; + --nmrs-success: #2ecc71; + --nmrs-warning: #f39c12; + --nmrs-danger: #e74c3c; +} + +.sidebar .sidebar-scrollbox { + background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%); +} + +.hljs { + border-radius: 6px; +} + +a { + color: var(--nmrs-secondary); +} + +a:hover { + color: var(--nmrs-primary); +} + +.warning { + border-left: 4px solid var(--nmrs-warning); + padding-left: 1em; + margin: 1em 0; +} + +.info { + border-left: 4px solid var(--nmrs-secondary); + padding-left: 1em; + margin: 1em 0; +} + +.success { + border-left: 4px solid var(--nmrs-success); + padding-left: 1em; + margin: 1em 0; +} + +h1 { + border-bottom: 2px solid var(--nmrs-primary); + padding-bottom: 0.3em; +} + +table { + border-collapse: collapse; + width: 100%; + margin: 1.5em 0; +} + +table th { + background-color: var(--table-header-bg); + color: var(--table-header-fg); + font-weight: 600; + padding: 0.75em; + text-align: left; +} + +table td { + padding: 0.75em; + border-bottom: 1px solid var(--table-border-color); +} + +code { + background-color: var(--inline-code-bg); + padding: 0.2em 0.4em; + border-radius: 3px; + font-size: 0.9em; +}