feat: sync httpdns sdk/platform updates without large binaries
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/io.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http/io_client.dart';
|
||||
import 'package:TrustAPP_httpdns/TrustAPP_httpdns.dart';
|
||||
|
||||
/* *
|
||||
* 构建<E69E84><E5BBBA>?HTTPDNS 能力<E883BD><E58A9B>?IOHttpClientAdapter
|
||||
*
|
||||
* 本方案由EMAS团队设计实现,参考请注明出处<E587BA><E5A484>?
|
||||
*/
|
||||
|
||||
IOHttpClientAdapter buildHttpdnsHttpClientAdapter() {
|
||||
final HttpClient client = HttpClient();
|
||||
_configureHttpClient(client);
|
||||
|
||||
_configureConnectionFactory(client);
|
||||
|
||||
final IOHttpClientAdapter adapter = IOHttpClientAdapter(
|
||||
createHttpClient: () => client,
|
||||
)..validateCertificate = (cert, host, port) => true;
|
||||
return adapter;
|
||||
}
|
||||
|
||||
HttpClient buildHttpdnsNativeHttpClient() {
|
||||
final HttpClient client = HttpClient();
|
||||
_configureHttpClient(client);
|
||||
_configureConnectionFactory(client);
|
||||
return client;
|
||||
}
|
||||
|
||||
http.Client buildHttpdnsHttpPackageClient() {
|
||||
final HttpClient httpClient = buildHttpdnsNativeHttpClient();
|
||||
return IOClient(httpClient);
|
||||
}
|
||||
|
||||
// HttpClient 基础配置
|
||||
void _configureHttpClient(HttpClient client) {
|
||||
client.findProxy = (Uri _) => 'DIRECT';
|
||||
client.idleTimeout = const Duration(seconds: 90);
|
||||
client.maxConnectionsPerHost = 8;
|
||||
}
|
||||
|
||||
// 配置基于 HTTPDNS 的连接工<E68EA5><E5B7A5>?
|
||||
void _configureConnectionFactory(HttpClient client) {
|
||||
client
|
||||
.connectionFactory = (Uri uri, String? proxyHost, int? proxyPort) async {
|
||||
final String domain = uri.host;
|
||||
final bool https = uri.scheme.toLowerCase() == 'https';
|
||||
final int port = uri.port == 0 ? (https ? 443 : 80) : uri.port;
|
||||
|
||||
final List<InternetAddress> targets = await _resolveTargets(domain);
|
||||
final Object target = targets.isNotEmpty ? targets.first : domain;
|
||||
|
||||
if (!https) {
|
||||
return Socket.startConnect(target, port);
|
||||
}
|
||||
|
||||
// HTTPS:先 TCP,再 TLS(SNI=域名),并保持可取消
|
||||
bool cancelled = false;
|
||||
final Future<ConnectionTask<Socket>> rawStart = Socket.startConnect(
|
||||
target,
|
||||
port,
|
||||
);
|
||||
final Future<Socket> upgraded = rawStart.then((task) async {
|
||||
final Socket raw = await task.socket;
|
||||
if (cancelled) {
|
||||
raw.destroy();
|
||||
throw const SocketException('Connection cancelled');
|
||||
}
|
||||
final SecureSocket secure = await SecureSocket.secure(raw, host: domain);
|
||||
if (cancelled) {
|
||||
secure.destroy();
|
||||
throw const SocketException('Connection cancelled');
|
||||
}
|
||||
return secure;
|
||||
});
|
||||
return ConnectionTask.fromSocket(upgraded, () {
|
||||
cancelled = true;
|
||||
try {
|
||||
rawStart.then((t) => t.cancel());
|
||||
} catch (_) {}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// 通过 HTTPDNS 解析目标 IP 列表;IPv4 优先;失败则返回空列表(上层回退系统 DNS<4E><53>?
|
||||
Future<List<InternetAddress>> _resolveTargets(String domain) async {
|
||||
try {
|
||||
final res = await TrustAPPHttpdns.resolveHostSyncNonBlocking(
|
||||
domain,
|
||||
ipType: 'both',
|
||||
);
|
||||
final List<String> ipv4 =
|
||||
(res['ipv4'] as List?)?.cast<String>() ?? const <String>[];
|
||||
final List<String> ipv6 =
|
||||
(res['ipv6'] as List?)?.cast<String>() ?? const <String>[];
|
||||
final List<InternetAddress> targets = [
|
||||
...ipv4.map(InternetAddress.tryParse).whereType<InternetAddress>(),
|
||||
...ipv6.map(InternetAddress.tryParse).whereType<InternetAddress>(),
|
||||
];
|
||||
if (targets.isEmpty) {
|
||||
debugPrint('[HTTPDNS] no result for $domain, fallback to system DNS');
|
||||
} else {
|
||||
debugPrint('[HTTPDNS] resolved $domain -> ${targets.first.address}');
|
||||
}
|
||||
return targets;
|
||||
} catch (e) {
|
||||
debugPrint('[HTTPDNS] resolve failed: $e, fallback to system DNS');
|
||||
return const <InternetAddress>[];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user