diff --git a/lib/fluiver.dart b/lib/fluiver.dart index ebac62b..5b5b195 100644 --- a/lib/fluiver.dart +++ b/lib/fluiver.dart @@ -5,7 +5,7 @@ library; import 'dart:async'; import 'dart:collection'; -import 'dart:io' show InternetAddress, Socket, SocketException; +import 'dart:io' show InternetAddress, SecureSocket, SocketException; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/lib/src/helpers/network_probe.dart b/lib/src/helpers/network_probe.dart index 22435b0..ee7290c 100644 --- a/lib/src/helpers/network_probe.dart +++ b/lib/src/helpers/network_probe.dart @@ -2,8 +2,8 @@ part of '../../fluiver.dart'; /// Lightweight reachability probes. abstract final class NetworkProbe { - /// Returns `true` if a TCP socket to `host:port` — Cloudflare DNS - /// (`1.0.0.1:53`) by default — opens within [timeout]. + /// Returns `true` if a secure connection to `host:port` — Cloudflare DNS + /// over TLS (`1.0.0.1:853`) by default — opens within [timeout]. /// /// Skips DNS resolution by connecting to a literal IP — faster and more /// reliable than HTTP probes. [host] must be a literal IPv4/IPv6 address; @@ -20,14 +20,14 @@ abstract final class NetworkProbe { /// in the browser, and a running web app is by definition online. static Future checkConnection({ String host = '1.0.0.1', - int port = 53, + int port = 853, Duration timeout = const Duration(seconds: 3), }) async { if (kIsWeb) { return true; } try { - final socket = await Socket.connect( + final socket = await SecureSocket.connect( InternetAddress(host), port, timeout: timeout, diff --git a/test/network_probe_test.dart b/test/network_probe_test.dart index 56c5f9c..46d7305 100644 --- a/test/network_probe_test.dart +++ b/test/network_probe_test.dart @@ -5,29 +5,20 @@ import 'package:fluiver/fluiver.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - // The TimeoutException path is not covered: a deterministic connect - // timeout needs an endpoint that black-holes SYNs, and no loopback setup - // does that — closed ports refuse (SocketException) instead. group('checkConnection', () { test('returns true when the endpoint accepts', () async { - final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0); - addTearDown(server.close); - + // Connect to Google DNS over TLS as an integration test. + // This avoids mocking a local secure server without valid certificates. final result = await NetworkProbe.checkConnection( - host: server.address.address, - port: server.port, + host: '8.8.8.8', ); check(result).isTrue(); }); test('returns false on connection refused', () async { - final server = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0); - final port = server.port; - await server.close(); - final result = await NetworkProbe.checkConnection( host: InternetAddress.loopbackIPv4.address, - port: port, + port: 55555, ); check(result).isFalse(); });