mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
New Ping, use servers to ping
This commit is contained in:
79
lib/data/model/server/ping_result.dart
Normal file
79
lib/data/model/server/ping_result.dart
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
final parseFailed = Exception('Parse failed');
|
||||||
|
final seqReg = RegExp(r'icmp_seq=(.+) ttl=(.+) time=(.+) ms');
|
||||||
|
final packetReg =
|
||||||
|
RegExp(r'(.+) packets transmitted, (.+) received, (.+)% packet loss');
|
||||||
|
final timeReg = RegExp(r'min/avg/max/mdev = (.+)/(.+)/(.+)/(.+) ms');
|
||||||
|
final ipReg = RegExp(r' \((\S+)\) ');
|
||||||
|
|
||||||
|
class PingResult {
|
||||||
|
String serverName;
|
||||||
|
String? ip;
|
||||||
|
List<PingSeqResult>? results;
|
||||||
|
PingStatistics? statistic;
|
||||||
|
|
||||||
|
PingResult.parse(this.serverName, String raw) {
|
||||||
|
final lines = raw.split('\n');
|
||||||
|
lines.removeWhere((element) => element.isEmpty);
|
||||||
|
final statisticIndex =
|
||||||
|
lines.indexWhere((element) => element.startsWith('---'));
|
||||||
|
if (statisticIndex == -1) {
|
||||||
|
throw parseFailed;
|
||||||
|
}
|
||||||
|
final statisticRaw = lines.sublist(statisticIndex + 1);
|
||||||
|
statistic = PingStatistics.parse(statisticRaw);
|
||||||
|
results = lines
|
||||||
|
.sublist(1, statisticIndex)
|
||||||
|
.map((e) => PingSeqResult.parse(e))
|
||||||
|
.toList();
|
||||||
|
ip = ipReg.firstMatch(lines[0])?.group(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PingSeqResult {
|
||||||
|
int? seq;
|
||||||
|
int? ttl;
|
||||||
|
double? time;
|
||||||
|
|
||||||
|
PingSeqResult.parse(String raw) {
|
||||||
|
final seqMatched = seqReg.firstMatch(raw);
|
||||||
|
if (seqMatched == null) {
|
||||||
|
throw parseFailed;
|
||||||
|
}
|
||||||
|
seq = int.tryParse(seqMatched.group(1)!);
|
||||||
|
ttl = int.tryParse(seqMatched.group(2)!);
|
||||||
|
time = double.tryParse(seqMatched.group(3)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'seq: $seq, ttl: $ttl, time: $time';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PingStatistics {
|
||||||
|
int? total;
|
||||||
|
int? received;
|
||||||
|
double? loss;
|
||||||
|
double? min;
|
||||||
|
double? max;
|
||||||
|
double? avg;
|
||||||
|
double? stddev;
|
||||||
|
|
||||||
|
PingStatistics.parse(List<String> lines) {
|
||||||
|
if (lines.isEmpty || lines.length != 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final packetMatched = packetReg.firstMatch(lines[0]);
|
||||||
|
final timeMatched = timeReg.firstMatch(lines[1]);
|
||||||
|
if (packetMatched == null || timeMatched == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
total = int.tryParse(packetMatched.group(1)!);
|
||||||
|
received = int.tryParse(packetMatched.group(2)!);
|
||||||
|
loss = double.tryParse(packetMatched.group(3)!);
|
||||||
|
min = double.tryParse(timeMatched.group(1)!);
|
||||||
|
avg = double.tryParse(timeMatched.group(2)!);
|
||||||
|
max = double.tryParse(timeMatched.group(3)!);
|
||||||
|
stddev = double.tryParse(timeMatched.group(4)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 115;
|
static const int build = 117;
|
||||||
static const String engine =
|
static const String engine =
|
||||||
"Flutter 2.10.4 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision c860cba910 (6 weeks ago) • 2022-03-25 00:23:12 -0500\nEngine • revision 57d3bac3dd\nTools • Dart 2.16.2 • DevTools 2.9.2\n";
|
"Flutter 2.10.4 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision c860cba910 (6 weeks ago) • 2022-03-25 00:23:12 -0500\nEngine • revision 57d3bac3dd\nTools • Dart 2.16.2 • DevTools 2.9.2\n";
|
||||||
static const String buildAt = "2022-05-03 08:33:56.199910";
|
static const String buildAt = "2022-05-03 11:39:22.853075";
|
||||||
static const int modifications = 3;
|
static const int modifications = 6;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,11 @@ class _AptManagePageState extends State<AptManagePage>
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
locator<AptProvider>().init(si.client!, si.status.sysVer.dist, () => scrollController.jumpTo(scrollController.position.maxScrollExtent));
|
locator<AptProvider>().init(
|
||||||
|
si.client!,
|
||||||
|
si.status.sysVer.dist,
|
||||||
|
() =>
|
||||||
|
scrollController.jumpTo(scrollController.position.maxScrollExtent));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:dart_ping/dart_ping.dart';
|
|
||||||
import 'package:dart_ping_ios/dart_ping_ios.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:toolbox/core/extension/uint8list.dart';
|
||||||
import 'package:toolbox/core/utils.dart';
|
import 'package:toolbox/core/utils.dart';
|
||||||
|
import 'package:toolbox/data/model/server/ping_result.dart';
|
||||||
|
import 'package:toolbox/data/provider/server.dart';
|
||||||
import 'package:toolbox/data/res/color.dart';
|
import 'package:toolbox/data/res/color.dart';
|
||||||
|
import 'package:toolbox/locator.dart';
|
||||||
import 'package:toolbox/view/widget/input_field.dart';
|
import 'package:toolbox/view/widget/input_field.dart';
|
||||||
import 'package:toolbox/view/widget/round_rect_card.dart';
|
import 'package:toolbox/view/widget/round_rect_card.dart';
|
||||||
|
|
||||||
@@ -18,16 +18,13 @@ class PingPage extends StatefulWidget {
|
|||||||
class _PingPageState extends State<PingPage>
|
class _PingPageState extends State<PingPage>
|
||||||
with AutomaticKeepAliveClientMixin {
|
with AutomaticKeepAliveClientMixin {
|
||||||
late TextEditingController _textEditingController;
|
late TextEditingController _textEditingController;
|
||||||
Ping? _ping;
|
|
||||||
late MediaQueryData _media;
|
late MediaQueryData _media;
|
||||||
|
final List<PingResult> _results = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_textEditingController = TextEditingController(text: '');
|
_textEditingController = TextEditingController(text: '');
|
||||||
if (Platform.isIOS) {
|
|
||||||
DartPingIOS.register();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -47,25 +44,61 @@ class _PingPageState extends State<PingPage>
|
|||||||
const SizedBox(height: 13),
|
const SizedBox(height: 13),
|
||||||
buildInput(context, _textEditingController, maxLines: 1),
|
buildInput(context, _textEditingController, maxLines: 1),
|
||||||
_buildControl(),
|
_buildControl(),
|
||||||
RoundRectCard(ConstrainedBox(
|
SizedBox(
|
||||||
constraints: BoxConstraints(
|
width: double.infinity,
|
||||||
minWidth: double.infinity,
|
height: _media.size.height * 0.6,
|
||||||
minHeight: _media.size.height * 0.6,
|
child: ListView.builder(
|
||||||
),
|
itemCount: _results.length,
|
||||||
)),
|
itemBuilder: (context, index) {
|
||||||
|
final result = _results[index];
|
||||||
|
return _buildResultItem(result);
|
||||||
|
}),
|
||||||
|
),
|
||||||
])),
|
])),
|
||||||
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void doPing() {
|
Widget _buildResultItem(PingResult result) {
|
||||||
_ping = Ping(_textEditingController.text.trim());
|
return RoundRectCard(ListTile(
|
||||||
_ping!.stream.listen((event) {
|
contentPadding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17),
|
||||||
final resp = event.response.toString();
|
title: Text(result.serverName,
|
||||||
if (resp == 'null') return;
|
style: TextStyle(
|
||||||
|
fontSize: 18, fontWeight: FontWeight.bold, color: primaryColor)),
|
||||||
|
subtitle: Text(_buildPingSummary(result)),
|
||||||
|
trailing: Text(
|
||||||
|
'Avg: ' +
|
||||||
|
(result.statistic?.avg?.toStringAsFixed(2) ?? 'unkown') +
|
||||||
|
' ms',
|
||||||
|
style: TextStyle(fontSize: 14, color: primaryColor)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
String _buildPingSummary(PingResult result) {
|
||||||
|
final ip = result.ip ?? 'unkown';
|
||||||
|
final ttl = result.results?.first.ttl ?? 'unkown';
|
||||||
|
final loss = result.statistic?.loss ?? 'unkown';
|
||||||
|
final min = result.statistic?.min ?? 'unkown';
|
||||||
|
final max = result.statistic?.max ?? 'unkown';
|
||||||
|
return '$ip\nttl: $ttl, loss: $loss%\nmin: $min ms, max: $max ms';
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> doPing() async {
|
||||||
|
_results.clear();
|
||||||
|
final target = _textEditingController.text.trim();
|
||||||
|
if (target.isEmpty) {
|
||||||
|
showSnackBar(context, const Text('Please input a target'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var si in locator<ServerProvider>().servers) {
|
||||||
|
if (si.client == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final result = await si.client!.run('ping -c 3 $target').string;
|
||||||
|
_results.add(PingResult.parse(si.info.name, result));
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildControl() {
|
Widget _buildControl() {
|
||||||
@@ -86,11 +119,11 @@ class _PingPageState extends State<PingPage>
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 7,
|
width: 7,
|
||||||
),
|
),
|
||||||
Text('Stop')
|
Text('Clear')
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_ping != null) _ping!.stop();
|
_results.clear();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
|
|||||||
30
pubspec.lock
30
pubspec.lock
@@ -117,20 +117,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
dart_ping:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: dart_ping
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "6.1.2"
|
|
||||||
dart_ping_ios:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: dart_ping_ios
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.0"
|
|
||||||
dartssh2:
|
dartssh2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -206,13 +192,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.2"
|
version: "1.3.2"
|
||||||
flutter_icmp_ping:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_icmp_ping
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
flutter_lints:
|
flutter_lints:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -356,13 +335,6 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
open_file:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: open_file
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "3.2.1"
|
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -371,7 +343,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0"
|
version: "1.8.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
|||||||
@@ -54,12 +54,8 @@ dependencies:
|
|||||||
r_upgrade: ^0.3.6
|
r_upgrade: ^0.3.6
|
||||||
pull_to_refresh: ^2.0.0
|
pull_to_refresh: ^2.0.0
|
||||||
marquee: ^2.2.0
|
marquee: ^2.2.0
|
||||||
dart_ping: ^6.1.1
|
|
||||||
dart_ping_ios: ^1.0.0
|
|
||||||
dropdown_button2: ^1.1.1
|
dropdown_button2: ^1.1.1
|
||||||
flutter_advanced_drawer: ^1.3.0
|
flutter_advanced_drawer: ^1.3.0
|
||||||
open_file: ^3.2.1
|
|
||||||
path_provider: ^2.0.9
|
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user