Nailathalang source
I-download ang source ZIP
CH-J SM Mobile
I-browse ang mga direktoryo at file ng isang partikular na release ng application.
CH-J / SM Mobile
175 file
sm-mobile-20261016T185235Z-8e93ecc1b59a
Idinagdag: · Binuo:
1
import 'dart:async';2
import 'dart:io';3
import 'measure.dart';5
/// Settings of a TCP connect measurement. [count] 0 means continuous until6
/// stopped.7
class TcpPingSettings {8
final int port, count;9
final Duration interval, timeout;10
const TcpPingSettings({11
required this.port,12
this.count = 4,13
this.interval = const Duration(seconds: 1),14
this.timeout = const Duration(seconds: 2),15
});16
Map<String, Object?> toJson() => {17
'port': port,18
'count': count == 0 ? 'continuous' : count,19
'intervalMs': interval.inMilliseconds,20
'timeoutMs': timeout.inMilliseconds,21
};22
}24
/// A running measurement; [cancel] stops it at once, also aborting a25
/// connection attempt in progress.26
class PingRun {27
final Stream<Sample> samples;28
final Future<void> Function() cancel;29
PingRun(this.samples, this.cancel);30
}32
/// errno values for a refused connection and for "no route" (Darwin,33
/// Linux/Android).34
const _refused = {61, 111};35
const _timedOut = {60, 110};36
const _unreachable = {51, 65, 101, 113};38
/// Classifies a failed connect. A connection refused (TCP reset from the39
/// target) is never reported as a timeout.40
(Outcome, String?) classifyConnectError(Object e, {required bool timedOut}) {41
if (e is SocketException) {42
final code = e.osError?.errorCode;43
if (code != null) {44
if (_refused.contains(code)) return (Outcome.refused, 'errno $code');45
if (_timedOut.contains(code)) return (Outcome.timeout, 'errno $code');46
if (_unreachable.contains(code)) {47
return (Outcome.unreachable, 'errno $code');48
}49
return (Outcome.error, '${e.osError!.message} (errno $code)');50
}51
if (timedOut || e.message.toLowerCase().contains('timed out')) {52
return (Outcome.timeout, null);53
}54
return (Outcome.error, e.message);55
}56
if (e is TimeoutException) return (Outcome.timeout, null);57
return (Outcome.error, e.toString());58
}60
typedef Connector =61
Future<ConnectionTask<Socket>> Function(InternetAddress, int);63
Future<ConnectionTask<Socket>> _connect(InternetAddress a, int port) =>64
Socket.startConnect(a, port);66
/// Measures how long the TCP three-way handshake to [address]:[port] takes.67
/// This is TCP connect timing, not an ICMP echo: a closed port answers with68
/// a reset (refused), a filtered one often not at all (timeout).69
PingRun tcpPing(70
InternetAddress address,71
TcpPingSettings settings, {72
Connector connect = _connect,73
}) {74
final out = StreamController<Sample>();75
var stopped = false;76
ConnectionTask<Socket>? pending;77
Timer? wait;78
Completer<void>? sleeping;79
final family = Family.of(address);81
Future<void> loop() async {82
var seq = 0;83
final clock = Stopwatch()..start();84
var nextStart = Duration.zero;85
while (!stopped && (settings.count == 0 || seq < settings.count)) {86
final delay = nextStart - clock.elapsed;87
if (delay > Duration.zero) {88
final done = sleeping = Completer<void>();89
wait = Timer(delay, () {90
if (!done.isCompleted) done.complete();91
});92
await done.future;93
if (stopped) break;94
}95
seq++;96
final started = clock.elapsed;97
nextStart = started + settings.interval;98
final time = DateTime.now();99
final watch = Stopwatch()..start();100
Sample sample;101
try {102
final task = pending = await connect(address, settings.port);103
Socket socket;104
try {105
socket = await task.socket.timeout(settings.timeout);106
} on TimeoutException {107
task.cancel();108
rethrow;109
}110
final ms = watch.elapsedMicroseconds / 1000;111
socket.destroy();112
sample = Sample(113
seq: seq,114
time: time,115
family: family,116
address: address.address,117
port: settings.port,118
rttMs: ms,119
outcome: Outcome.ok,120
);121
} catch (e) {122
if (stopped) break;123
final (outcome, detail) = classifyConnectError(124
e,125
timedOut: watch.elapsed >= settings.timeout,126
);127
sample = Sample(128
seq: seq,129
time: time,130
family: family,131
address: address.address,132
port: settings.port,133
outcome: outcome,134
// A refusal still measures a full round trip to the target.135
rttMs: outcome == Outcome.refused136
? watch.elapsedMicroseconds / 1000137
: null,138
detail: detail,139
);140
} finally {141
pending = null;142
}143
if (stopped) break;144
out.add(sample);145
}146
await out.close();147
}149
Future<void> cancel() async {150
if (stopped) return;151
stopped = true;152
pending?.cancel();153
wait?.cancel();154
if (sleeping != null && !sleeping!.isCompleted) sleeping!.complete();155
if (!out.isClosed) unawaited(out.close());156
}158
out.onListen = () => unawaited(loop());159
out.onCancel = cancel;160
return PingRun(out.stream, cancel);161
}SHA-256
13d640eca917d25c6852130f4f306b8e39b06643f3a691a5cba7b95e2ccc0370CH-J Proprietary Software License 1.14 · Ibinibigay ang source sa ilalim ng CH-J Proprietary Software License 1.14. Hindi binabago ng pagiging available nito ang mga tuntunin ng lisensya at hindi ito nagbibigay ng karagdagang karapatan.
SHA-256 ng archive
46e427a43e87af091004f36145590bda8fe90086dfb0f631afeb5029fb0b5655