Crate gntp

Crate gntp 

Source
Expand description

§GNTP - Growl Notification Transport Protocol Client

A robust, production-ready Rust implementation of the Growl Notification Transport Protocol (GNTP) for sending desktop notifications to Growl-compatible clients across multiple platforms.

§Features

  • Full GNTP 1.0 protocol implementation
  • Multiple icon delivery modes (Binary, File URL, Data URL/Base64)
  • Windows Growl compatibility with automatic workarounds
  • Cross-platform support (Windows, macOS, Linux)
  • Binary resource deduplication to prevent protocol errors
  • Comprehensive error handling with detailed error types
  • Production-ready with extensive testing
  • No external dependencies (except uuid for unique identifiers)

§Platform Compatibility

PlatformBinary ModeFile URLData URLRecommended
Windows (Growl for Windows)⚠️ Buggy✅ WorksBestDataUrl
macOS (Growl)✅ Works✅ Works✅ WorksBinary
Linux (Growl-compatible)✅ Works✅ Works✅ WorksBinary

§Quick Start

use gntp::{GntpClient, NotificationType, Resource, IconMode};

// Create client with DataUrl mode (safest, most compatible)
let mut client = GntpClient::new("My App")
    .with_icon_mode(IconMode::DataUrl);

// Load icon from file
let icon = Resource::from_file("icon.png")?;

// Define notification type with icon
let notification = NotificationType::new("alert")
    .with_display_name("Alert Notification")
    .with_icon(icon);

// Register (must be called first!)
client.register(vec![notification])?;

// Send notification
client.notify("alert", "Hello", "This is a test notification")?;

§Icon Delivery Modes

§Binary Mode (GNTP Spec Compliant)

let client = GntpClient::new("App")
    .with_icon_mode(IconMode::Binary);

Sends icons as binary resources according to GNTP specification. Note: May not work correctly with Growl for Windows due to implementation bugs.

§File URL Mode

let client = GntpClient::new("App")
    .with_icon_mode(IconMode::FileUrl);

References icons via file:// URLs. Requires icon files to exist on disk.

let client = GntpClient::new("App")
    .with_icon_mode(IconMode::DataUrl); // Default

Embeds icons as base64-encoded data URLs. Most compatible across all platforms. No external files required.

§Advanced Usage

§Creating Resources from Memory

let image_data: Vec<u8> = vec![/* your image bytes */];
let icon = Resource::from_bytes(image_data, "image/png");

§Sending Notifications with Options

let options = NotifyOptions::new()
    .with_sticky(true)
    .with_priority(2)
    .with_icon(icon);

client.notify_with_options(
    "alert",
    "Important",
    "This stays on screen",
    options
)?;

§Multiple Notification Types

let info = NotificationType::new("info")
    .with_display_name("Information");
let warning = NotificationType::new("warning")
    .with_display_name("Warning");
let error = NotificationType::new("error")
    .with_display_name("Error");

client.register(vec![info, warning, error])?;

client.notify("info", "Info", "Something happened")?;
client.notify("warning", "Warning", "Be careful!")?;
client.notify("error", "Error", "Something went wrong!")?;

§Remote Notifications

let client = GntpClient::new("Remote App")
    .with_host("192.168.1.100")
    .with_port(23053);

§Debug Mode

let client = GntpClient::new("Debug App")
    .with_debug(true); // Prints detailed packet information

§Protocol Specification

GNTP requires two separate steps:

  1. REGISTER - Register your application and notification types (once per connection)
  2. NOTIFY - Send notifications (multiple times)

You must call register() before calling notify(), otherwise you’ll receive a ProtocolError.

§Error Handling

All operations return Result<T, GntpError> with detailed error information:

match client.register(vec![]) {
    Ok(_) => println!("Registered successfully"),
    Err(GntpError::ConnectionError(msg)) => {
        eprintln!("Connection failed: {}", msg);
    }
    Err(GntpError::IoError(msg)) => {
        eprintln!("I/O error: {}", msg);
    }
    Err(GntpError::ProtocolError(msg)) => {
        eprintln!("Protocol error: {}", msg);
    }
}

§Windows Compatibility Notes

Growl for Windows has a known bug where it doesn’t properly handle binary resources according to the GNTP specification. When the server receives binary data, it may not respond, causing timeout errors (10060).

Solution: Use IconMode::DataUrl (default) which embeds icons as base64 strings. This bypasses the binary resource issue entirely.

§Performance Considerations

  • Binary Mode: Smallest packet size, fastest transmission
  • File URL Mode: No data in packet, but requires disk access
  • Data URL Mode: Larger packets (~33% increase due to base64), but most reliable

For typical notification icons (< 100KB), the performance difference is negligible.

§Examples

See the examples directory for:

  • Basic notifications
  • Notifications with icons
  • Multiple notification types
  • Remote notifications
  • Error handling patterns

§License

MIT License - See LICENSE file for details

§Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

§Credits

Author: Hadi Cahyadi cumulus13@gmail.com

Structs§

GntpClient
GNTP client for sending notifications to Growl
NotificationType
Notification type definition
NotifyOptions
Options for sending notifications
Resource
Binary resource (icon) with multiple delivery options

Enums§

GntpError
GNTP client errors
IconMode
Icon delivery mode for notifications