network_reachability 0.0.1
network_reachability: ^0.0.1 copied to clipboard
An advanced network monitoring and resilience library for Flutter, powered by a high-performance Rust core.
Network-Reachability
An advanced network monitoring and resilience library for Flutter, powered by a high-performance Rust core.
Go beyond simple connectivity checks. Understand the quality, stability, and security of your user's network.
Why? • Key Features • How It Works • Installation • Basic Usage • Advanced Usage • Contributing
🤔 Why Choose Network-Reachability? #
Most network libraries tell you if you're connected or disconnected. In the real world, this is not enough. A user might be "connected" but on a network so slow that your app is unusable, or on an insecure public WiFi that exposes them to risk.
Network-Reachability answers the questions that truly matter for building robust applications:
- Is the connection good enough? Instead of a simple boolean, you get a detailed
ConnectionQualityreport (Excellent,Great,Good,Moderate,Poor,Unstable,CaptivePortal,Offline), including concrete metrics like latency, jitter, and packet loss. This allows you to tailor the user experience—for example, by disabling video streaming on aPoorconnection. - Is the backend reachable and stable? This library doesn't just check for a generic internet connection. It probes your actual server endpoints (
NetworkTarget). If your backend is down, the app will know. - Is the network secure? For sensitive applications (banking, enterprise), knowing the network environment is critical. This library actively detects security risks like VPNs, DNS hijacking, and proxies, allowing you to block operations on untrusted networks.
- How should my app behave during network issues? With a built-in Circuit Breaker, the library can automatically stop your app from hammering a failing backend service, preventing cascading failures and providing a better user experience until the service recovers.
This library gives you the deep network intelligence needed to build resilient, secure, and user-friendly applications that adapt gracefully to real-world network conditions.
✨ Key Features #
-
Deep Quality Analysis: Get a multi-faceted view of the network quality, including average latency, jitter (latency variation), and packet loss percentage. The final
ConnectionQualityenum gives you an instant, actionable summary. -
guard()Protected Actions: The library's crown jewel. Wrap any network-dependent function (like an API call) in aguard(). It will only execute if the network meets your predefined quality and security rules, throwing specific, catchable exceptions otherwise. -
Built-in Circuit Breaker: Automatically detects when essential backend services are failing. The circuit breaker will "open" and temporarily block further requests, preventing your app from causing server overloads and providing immediate feedback to the user.
-
Advanced Security Probes: Go beyond application-level security. Detect and react to environmental threats:
- VPN & Proxy Detection: Block or flag connections from anonymized networks.
- DNS Hijack Detection: Protect against man-in-the-middle attacks by comparing system DNS against a trusted resolver.
- Captive Portal Detection: Identify when the user is stuck on a public WiFi login page.
-
Granular Configuration: Take full control. Customize the
NetworkConfigurationto:- Define multiple
NetworkTargetendpoints (TCP/UDP) with priorities. - Set your own
QualityThresholdsfor what constitutes an "excellent" or "poor" connection. - Fine-tune the
ResilienceConfiglike the circuit breaker sensitivity and jitter tolerance.
- Define multiple
-
High-Performance Rust Core: All heavy lifting and network probing is executed in a native Rust engine, ensuring that these complex checks are fast, efficient, and don't block the Flutter UI thread.
🔧 How It Works #
Understanding the lifecycle of the library's core functions is key to using it effectively.
The Anatomy of check() #
When you call NetworkReachability.instance.check(), a multi-stage process is initiated:
- Rust Engine Execution: The call is delegated to the high-performance Rust core, which performs the following:
- Parallel Probing: It sends probes to all
NetworkTargetendpoints defined in your configuration. - Data Collection: It gathers multiple latency samples to calculate statistics like min/max/avg latency, jitter (standard deviation), and packet loss.
- Security Analysis: It inspects network interfaces to detect the
ConnectionType(e.g., WiFi, Cellular) and security flags (e.g.,isVpnDetected). - Quality Evaluation: The final metrics are compared against your
QualityThresholdsto determine an overallConnectionQualityscore.
- Parallel Probing: It sends probes to all
- Report Generation: The Rust engine compiles all this data into a comprehensive
NetworkReport. - Circuit Breaker Update: Back in the Dart layer, the
check()method inspects theNetworkReport. If anyisEssentialtarget failed, it increments a failure counter. If the counter exceeds thecircuitBreakerThresholdfrom your configuration, the circuit is "opened". A successful check on an essential target resets the counter and closes the circuit.
The Lifecycle of guard() #
The guard() method is an intelligent sequence of validations that wrap your action:
- Circuit Breaker Check: The very first step. Is the circuit currently open? If yes, the method fails immediately by throwing a
CircuitBreakerOpenException. This prevents any network activity if the backend is known to be unstable. - Live Network Check: It calls the full
check()method described above to get a fresh, up-to-the-momentNetworkReport. - Security Validation: It compares the
report.securityFlagsagainst yourSecurityConfig.- Is
blockVpntrue and a VPN is detected? ThrowSecurityException. - Is
detectDnsHijacktrue and DNS spoofing is found? ThrowSecurityException. - Are
allowedInterfacesdefined and the current interface isn't one of them? ThrowSecurityException.
- Is
- Quality Validation: It compares the
report.status.qualityagainst theminQualityparameter you provided toguard(). If the current quality is worse than the minimum required (e.g., you requiregoodbut the connection ispoor), it throws aPoorConnectionException. - Execute Action: Only if all the above checks pass does the
actionfunction you provided get executed. The return value of your function is then passed back as the result ofguard().
This robust, multi-step validation process is what makes guard() so powerful.
Installation #
first, you need to install Rust Programming Language on your system.
Next, add network_reachability to your pubspec.yaml file:
dependencies:
network_reachability: ^0.0.1 # Replace with the latest version
Then, run flutter pub get to fetch the package.
🚀 Basic Usage #
1. Initialization #
Initialize the library in your main() function. This sets up the Rust engine and the Dart singleton.
import 'package:flutter/material.dart';
import 'package:network_reachability/network_reachability.dart';
import 'package:network_reachability/core/rust/frb_generated.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize the Rust library bindings.
await RustLib.init();
// Initialize Network-Reachability with a default or custom configuration.
// this uses a default configuration.
await NetworkReachability.init();
runApp(const MyApp());
}
2. Protecting Network Calls with guard() #
This is the primary and most recommended way to use the library. guard() ensures your critical functions only run when the network is in a known good state.
Future<void> fetchSensitiveData() async {
try {
// Wrap your API call with the guard.
final data = await NetworkReachability.instance.guard(
// The action to perform ONLY if checks pass.
action: () => myApi.fetchImportantData(),
// Optional: Require a minimum quality for this specific action.
minQuality: ConnectionQuality.good,
);
print('Data fetched successfully: $data');
} on PoorConnectionException catch (e) {
// Thrown if quality is below 'good'.
print('Could not fetch data: The connection is too slow or unstable. Details: ${e.message}');
} on SecurityException catch (e) {
// Thrown if a security policy is violated (e.g., VPN detected).
print('Action blocked due to a security risk: ${e.message}');
} on CircuitBreakerOpenException catch (e) {
// Thrown if the backend is known to be unstable.
print('Our servers are temporarily unavailable. Please try again later. Details: ${e.message}');
}
}
3. Monitoring Status Changes #
You can listen to a stream of network status updates for background monitoring or to update your UI in real-time.
void listenToNetworkChanges() {
final subscription = NetworkReachability.instance.onStatusChange.listen((status) {
// Note: The stream provides a lightweight `NetworkStatus` object.
// For a full report, you would call `check()` inside the listener.
print('Network status updated: ${status.isConnected ? 'Connected' : 'Disconnected'} - Quality: ${status.quality.name}');
print('Latency: ${status.latencyStats.latencyMs}ms');
print('Jitter: ${status.latencyStats.jitterMs}ms');
print('Packet Loss: ${status.latencyStats.packetLossPercent}%');
print('Stability Score: ${status.latencyStats.stabilityScore}/100');
// Update your UI based on the new status
});
// Don't forget to cancel the subscription in your widget's dispose() method.
}
🔬 Advanced Usage #
Custom Configuration #
Tailor the engine's behavior by providing a NetworkConfiguration during initialization.
import 'package:network_reachability/network_reachability.dart';
Future<void> initializeWithCustomConfig() async {
final config = await NetworkConfiguration.default_(); // Get the default config
final customConfig = NetworkConfiguration(
targets: [
NetworkTarget(
label: 'my-backend-primary',
host: 'api.mydomain.com',
port: 443,
protocol: TargetProtocol.tcp,
timeoutMs: BigInt.from(2000),
isEssential: true, // This target affects the circuit breaker if it fails the app goes offline
priority: 1,
),
],
checkIntervalMs: BigInt.from(15000), // 15 seconds
cacheValidityMs: BigInt.from(2000), // 2 seconds cache
// Defines the latency thresholds (in milliseconds) used to determine [ConnectionQuality].
qualityThreshold: QualityThresholds(
excellent: BigInt.from(50),
great: BigInt.from(100),
good: BigInt.from(150),
moderate: BigInt.from(250),
poor: BigInt.from(500),
),
// Configuration for security-related checks.
security: SecurityConfig(
blockVpn: true,
detectDnsHijack: true,
),
// Configuration for the circuit breaker and resilience
resilience: ResilienceConfig(
// first to respond wins
strategy: CheckStrategy.race,
// The number of consecutive failures of essential targets before the circuit breaker opens.
circuitBreakerThreshold: 3,
// Cooldown period before the circuit breaker transitions to Half-Open.
circuitBreakerCooldownMs: BigInt.from(60000), // 1 minute
// Number of samples to take for jitter and stability analysis.
numJitterSamples: 5,
// The percentage of mean latency that the standard deviation must exceed to be considered high jitter.
jitterThresholdPercent: 0.2,
// If the calculated stability score is less than this value, the quality considered 'Unstable'.
stabilityThershold: 80,
// The packet loss percentage above which the connection is marked as 'Unstable'.
criticalPacketLossPrecent: 5.0,
),
);
await NetworkReachability.init(config: customConfig);
}
Direct Probe Access #
For specific, one-off checks, you can call the individual probe functions directly without running a full check().
// Check if the user is behind a WiFi login page
final captiveStatus = await NetworkReachability.instance.checkForCaptivePortal(
timeoutMs: BigInt.from(5000),
);
if (captiveStatus.isCaptivePortal) {
print('User may need to log in to the network at ${captiveStatus.redirectUrl}');
}
// Check for DNS tampering
final isHijacked = await NetworkReachability.instance.detectDnsHijacking(
domain: 'my-api.com',
);
if (isHijacked) {
print('Warning: Potential DNS hijacking detected!');
}
🤝 Contributing #
Contributions are welcome! Here’s how to get started:
- Fork the repository.
- Create a new branch:
git checkout -b feature/YourFeature - Commit your changes:
git commit -m "Add amazing feature" - Push to your branch:
git push origin feature/YourFeature - Open a pull request.
💡 Please read our Contributing Guidelines and open an issue first for major feature ideas or changes.
📜 License #
This project is licensed under the GPL-3.0 License. See the LICENSE file for full details.
Made with ❤️ by MostafaSensei106