# How Sniffnet's Favorite System Manages Network Hosts and Services

> Discover how Sniffnet's favorite system uses HashSets for O(1) checks, UI toggles, filtered reports, and real-time alerts on network hosts and services.

- Repository: [Giuliano Bellini/sniffnet](https://github.com/GyulyVGC/sniffnet)
- Tags: deep-dive
- Published: 2026-04-28

---

**Sniffnet maintains a persistent, in-memory collection of favorite network entities using three HashSets stored in the `Favorites` struct, enabling O(1) membership checks, UI star toggles, filtered reporting, and real-time traffic alerts for specific hosts, services, and programs.**

The Sniffnet network monitoring application (GyulyVGC/sniffnet) implements a comprehensive favorite system that persists user preferences across sessions via serialized configuration. This system tracks three distinct entity types—network hosts, services, and application programs—allowing security analysts and network administrators to focus monitoring on critical infrastructure components.

## Core Data Structures

The favorite system centers on [`src/gui/types/favorite.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/favorite.rs), which defines the storage containers and access patterns that enable efficient favorite management.

### The Favorites Struct

At the heart of the system lies the **`Favorites`** struct, which encapsulates three separate `HashSet` instances. Each set stores a different entity type and derives serialization traits for persistent storage in the user's configuration file.

```rust
#[derive(Clone, Default, PartialEq, Debug, Serialize, Deserialize)]
#[serde(default)]
pub struct Favorites {
    #[serde(deserialize_with = "deserialize_or_default")]
    hosts: HashSet<Host>,
    #[serde(deserialize_with = "deserialize_or_default")]
    services: HashSet<Service>,
    #[serde(deserialize_with = "deserialize_or_default")]
    programs: HashSet<Program>,
}

```

This structure ensures that favorites survive application restarts while providing constant-time complexity for membership tests.

### The FavoriteKey Enum

To abstract over the three entity types, Sniffnet uses the **`FavoriteKey`** enum that unifies hosts, services, and programs under a single interface. This pattern enables generic insertion and removal operations without exposing internal storage details.

```rust
pub enum FavoriteKey {
    Host(Host),
    Service(Service),
    Program(Program),
}

```

The `Favorites::insert` and `Favorites::remove` methods pattern-match on this enum to route operations to the appropriate underlying HashSet, as implemented in [`src/gui/types/favorite.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/favorite.rs) lines 54-78.

## Adding and Removing Favorites

### Programmatic API

The `Favorites` implementation provides **`insert`** and **`remove`** methods that accept a `&FavoriteKey` parameter. These methods delegate to the respective HashSet operations after dispatching based on the enum variant.

When working with the system programmatically, you can add entities as follows:

```rust
use sniffnet::gui::types::favorite::{Favorites, FavoriteKey};
use sniffnet::networking::types::host::Host;

// Assume `host` is a Host object you want to favorite
let mut fav = Favorites::default();
fav.insert(&FavoriteKey::Host(host.clone()));
// `fav.hosts()` now contains the host

```

Removal follows an identical pattern, calling `favorites.remove(&key)` to delete entries from the appropriate set.

### UI Interaction and State Management

The GUI implements favorite toggling through star buttons rendered next to network entries in [`src/gui/pages/overview_page.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/pages/overview_page.rs). Each button calls `FavoriteItem::star_button`, which determines the current favorite state by invoking `contains_host`, `contains_service`, or `contains_program` depending on the entity type.

When clicked, the button emits a **`Message::AddOrRemoveFavorite(key, should_add)`** event. The main application state in [`src/gui/sniffer.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/sniffer.rs) handles this message:

```rust
Message::AddOrRemoveFavorite(key, should_add) => {
    if should_add { self.conf.favorites.insert(&key); }
    else { self.conf.favorites.remove(&key); }
}

```

This architecture cleanly separates UI events from data mutations while ensuring the configuration remains synchronized with user actions.

## Querying Favorite Status

Membership testing relies on three specialized helper methods: **`contains_host`**, **`contains_service`**, and **`contains_program`**. Each delegates directly to the underlying `HashSet::contains` implementation, providing O(1) lookup performance.

To check if a service is favorited programmatically:

```rust
use sniffnet::gui::types::favorite::Favorites;
use sniffnet::networking::types::service::Service;

fn is_fav_service(fav: &Favorites, svc: &Service) -> bool {
    fav.contains_service(svc)
}

```

These query methods power both the UI star indicators in [`src/gui/pages/overview_page.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/pages/overview_page.rs) and the filtering logic throughout the application.

## Filtering Traffic and Reports

### Overview Page Implementation

The overview page supports **"Only show favorites"** filtering through boolean flags in the configuration: `host_favorites_filter`, `service_favorites_filter`, and `program_favorites_filter`. When toggled in [`src/gui/sniffer.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/sniffer.rs) (lines 704-713), these flags restrict displayed entries to those present in the corresponding favorite sets.

The `Favorite::get_entries` method coordinates this filtering by calling specialized helpers like `get_host_entries`, `get_service_entries`, and `get_program_entries`. These functions build result vectors containing only favorited items when their respective filter flags are active.

### Report and Inspect Views

For detailed traffic analysis, the search parameters in [`src/report/types/search_parameters.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/report/types/search_parameters.rs) include an **`only_favorites`** boolean flag. When enabled, the report generation logic in [`src/report/get_report_entries.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/report/get_report_entries.rs) validates each captured packet against the favorite sets:

```rust
let is_favorite_host   = favorites.contains_host(&e.1);
let is_favorite_service = favorites.contains_service(&value.service);
let is_favorite_program = favorites.contains_program(&value.program);
let is_favorite = is_favorite_host || is_favorite_service || is_favorite_program;

```

Only entries satisfying this disjunction proceed through `SearchParameters::match_entry`, ensuring reports contain exclusively favorited traffic when the filter is active. The inspect page in [`src/gui/pages/inspect_page.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/pages/inspect_page.rs) provides similar UI controls for "Only show favorites".

## Real-Time Notifications

Sniffnet extends the favorite system into its notification pipeline. The [`src/notifications/notify_and_log.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/notifications/notify_and_log.rs) module monitors traffic for favorited entities through the `favorites_last_interval` function (lines 186-204) and generates **`LoggedNotification::FavoriteTransmitted`** events when new activity occurs for tracked items.

This creates a targeted monitoring system that suppresses noise while highlighting critical network activity, allowing users to receive immediate alerts when monitored hosts or services transmit data.

## Summary

- Sniffnet's favorite system uses three `HashSet` instances within the `Favorites` struct to track **hosts**, **services**, and **programs** with serialization support for persistence via [`src/gui/types/favorite.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/favorite.rs).
- The **`FavoriteKey`** enum abstracts entity types, enabling unified insertion and removal via `insert()` and `remove()` methods that pattern-match on the variant.
- UI star buttons trigger **`Message::AddOrRemoveFavorite`** events handled in [`src/gui/sniffer.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/sniffer.rs) to mutate the persistent configuration state.
- Membership testing occurs in constant time through **`contains_host`**, **`contains_service`**, and **`contains_program`** helpers.
- Filtering applies to both the **overview page** (via filter flags in `Conf`) and **report generation** (via `only_favorites` search parameters), restricting views to favorited entities.
- The notification system generates **`FavoriteTransmitted`** alerts in [`src/notifications/notify_and_log.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/notifications/notify_and_log.rs) when traffic involves favorited network endpoints.

## Frequently Asked Questions

### How does Sniffnet persist favorite hosts between application restarts?

The `Favorites` struct in [`src/gui/types/favorite.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/favorite.rs) implements `Serialize` and `Deserialize` traits, with each HashSet annotated using `#[serde(deserialize_with = "deserialize_or_default")]`. This configuration saves favorites to the user's config file on disk and automatically reloads them when Sniffnet launches, maintaining state across sessions without manual intervention.

### What is the time complexity for checking if a host is a favorite?

All membership checks operate in **O(1)** average time complexity. The `contains_host`, `contains_service`, and `contains_program` methods delegate directly to the underlying `HashSet::contains` implementation, ensuring instantaneous lookup even with thousands of tracked favorites stored in memory.

### Can I filter reports to show only traffic from favorite services?

Yes. Set `conf.report_search_parameters.only_favorites = true` before generating the report. The `get_searched_entries` function in [`src/report/get_report_entries.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/report/get_report_entries.rs) will then verify each entry against the favorite sets using logical OR logic across hosts, services, and programs, returning only traffic involving favorited entities.

### How does the UI know whether to display a filled or empty star icon?

The `FavoriteItem::star_button` method queries the appropriate `contains_*` method (depending on entity type) to determine the boolean `is_favorite` state. It renders the star accordingly and emits `Message::AddOrRemoveFavorite(key, !is_favorite)` on click, immediately toggling the favorite status in the persistent `conf.favorites` collection and updating the display.