From 3e8fae1c3ea0c45a3e63a49011354f970d763e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BC=9A=E5=81=9A=E9=A5=AD=E7=9A=84=E4=BA=8C=E5=93=88?= Date: Mon, 17 Mar 2025 22:55:52 +0800 Subject: [PATCH] 1.0.4 --- lib/config/app_config.dart | 41 +- lib/config/cof.dart | 15 +- lib/config/navigationconfiguration.dart | 12 +- lib/screens/front.dart | 85 +- lib/screens/settings.dart | 215 +- lib/src/rust/api/simple.dart | 2 +- lib/src/rust/frb_generated.dart | 33 +- lib/src/rust/frb_generated.io.dart | 9 + lib/src/rust/frb_generated.web.dart | 9 + lib/utils/kv_state.dart | 47 +- pubspec.lock | 363 +- rust/Cargo.lock | 12 +- rust/easytier/Cargo.lock | 5274 ----------------- rust/easytier/Cargo.toml | 4 +- rust/easytier/src/common/config.rs | 1 - rust/easytier/src/common/constants.rs | 4 +- rust/easytier/src/common/stun.rs | 210 +- rust/easytier/src/connector/direct.rs | 208 +- rust/easytier/src/connector/dns_connector.rs | 74 +- rust/easytier/src/connector/manual.rs | 16 +- .../src/connector/udp_hole_punch/common.rs | 2 +- rust/easytier/src/easytier-cli.rs | 40 +- rust/easytier/src/easytier-core.rs | 11 - rust/easytier/src/instance/listeners.rs | 46 +- .../src/peers/foreign_network_manager.rs | 3 +- rust/easytier/src/peers/peer.rs | 42 +- rust/easytier/src/peers/peer_manager.rs | 81 +- rust/easytier/src/peers/peer_map.rs | 5 + rust/easytier/src/peers/rpc_service.rs | 15 +- rust/easytier/src/peers/tests.rs | 2 +- rust/easytier/src/proto/cli.proto | 4 + rust/easytier/src/proto/cli.rs | 4 + rust/easytier/src/proto/common.proto | 2 +- rust/easytier/src/tunnel/common.rs | 8 +- rust/easytier/src/tunnel/mod.rs | 2 +- rust/easytier/src/tunnel/tcp.rs | 6 +- rust/easytier/src/tunnel/udp.rs | 25 +- rust/src/api/simple.rs | 20 +- rust/src/frb_generated.rs | 24 +- 39 files changed, 1111 insertions(+), 5865 deletions(-) delete mode 100644 rust/easytier/Cargo.lock diff --git a/lib/config/app_config.dart b/lib/config/app_config.dart index 29452b5..167b91a 100644 --- a/lib/config/app_config.dart +++ b/lib/config/app_config.dart @@ -28,8 +28,13 @@ class AppConfig { 'seedColor': Colors.blue.value, }, 'server': { - 'list': ['public.easytier.cn:11010'], - 'current': 'public.easytier.cn:11010', + 'list': [ + { + 'url': 'public.easytier.cn:11010', + 'name': '公共服务器', + 'selected': true, + } + ], }, 'room': { 'name': 'kevin', @@ -79,27 +84,27 @@ class AppConfig { } // 服务器列表设置 - List get serverList { - final List? value = _configManager.get('server.list'); - return value?.cast() ?? ['public.easytier.cn:11010']; + List> get serverList { + final dynamic value = _configManager.get('server.list'); + if (value is List) { + return List>.from( + value.map((item) => Map.from(item as Map)), + ); + } + return [ + { + 'url': 'public.easytier.cn:11010', + 'name': '公共服务器', + 'selected': true, + } + ]; } - Future setServerList(List servers) async { + Future setServerList(List> servers) async { _configManager.set('server.list', servers); await _configManager.save(); } - // 当前选中的服务器设置 - String get currentServer { - return _configManager.get('server.current') ?? - 'public.easytier.cn:11010'; - } - - Future setCurrentServer(String server) async { - _configManager.set('server.current', server); - await _configManager.save(); - } - // 房间名设置 String get roomName { return _configManager.get('room.name') ?? 'kevin'; @@ -159,7 +164,7 @@ class AppConfig { _configManager.set('network.dynamicIP', enabled); await _configManager.save(); } - + // 全局ping开关设置 bool get enablePing { return _configManager.get('system.enablePing') ?? true; diff --git a/lib/config/cof.dart b/lib/config/cof.dart index bf9f461..30f235f 100644 --- a/lib/config/cof.dart +++ b/lib/config/cof.dart @@ -25,7 +25,10 @@ class ConfigManager { final yamlMap = loadYaml(content); _config = _mergeConfigs(_convertYaml(yamlMap)); } catch (e) { - throw Exception('配置文件解析失败: $e'); + // 提供更详细的错误信息并使用默认配置 + print('配置文件解析失败: $e'); + print('将使用默认配置继续运行。请检查配置文件格式是否正确。'); + _config = Map.from(defaultConfig); } } @@ -61,7 +64,15 @@ class ConfigManager { current = current.putIfAbsent(key, () => {}); } - current[keys.last] = value; + // 类型转换确保值类型兼容性 + if (value is Map) { + current[keys.last] = Map.from(value); + } else if (value is List>) { + current[keys.last] = + value.map((e) => Map.from(e)).toList(); + } else { + current[keys.last] = value; + } } /// 合并用户配置与默认配置 diff --git a/lib/config/navigationconfiguration.dart b/lib/config/navigationconfiguration.dart index 51f767c..5128a90 100644 --- a/lib/config/navigationconfiguration.dart +++ b/lib/config/navigationconfiguration.dart @@ -40,12 +40,12 @@ class NavigationConfig { currentThemeMode: currentThemeMode, )), ), - // NavItem( - // label: '房间', - // icon: Icons.room_outlined, - // selectedIcon: Icons.room, - // pageBuilder: () => _getOrCreatePage(1, () => const RoomPage()), - // ), + NavItem( + label: '房间', + icon: Icons.room_outlined, + selectedIcon: Icons.room, + pageBuilder: () => _getOrCreatePage(1, () => const RoomPage()), + ), NavItem( label: '设置', icon: Icons.settings_outlined, diff --git a/lib/screens/front.dart b/lib/screens/front.dart index 971e7cd..a6d0ea2 100644 --- a/lib/screens/front.dart +++ b/lib/screens/front.dart @@ -73,7 +73,7 @@ class _HomePageState extends State { bool _isAutoIP = true; // 只用于控制IP自动/手动模式 - String Serverip = ""; + List Serverip = [""]; int _uploadBytes = 0; int _downloadBytes = 0; int _lastUploadBytes = 0; @@ -115,11 +115,12 @@ class _HomePageState extends State { _roomPasswordControllerFocusNode = FocusNode(); _roomPasswordControllerFocusNode.addListener(_onRoomPasswordFocusChange); - // 修改卡片构建器列表,添加版本信息卡片 + // 修改卡片构建器列表,添加服务器列表卡片 _cardBuilders = [ _buildNetworkStatusCard, _buildUserInfoCard, _buildRoomInfoCard, + _buildServerListCard, _buildVersionInfoCard, ]; } @@ -573,7 +574,60 @@ class _HomePageState extends State { ); } +// 添加服务器列表卡片 + Widget _buildServerListCard(ColorScheme colorScheme) { + final km = Provider.of(context); + // 直接使用 serverIP 列表,而不是尝试访问 serverList + final serverUrls = km.serverIP; + + return FloatingCard( + colorScheme: colorScheme, + maxWidth: 600, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 标题栏 + Row( + children: [ + Icon(Icons.dns, color: colorScheme.primary, size: 22), + const SizedBox(width: 8), + const Text('当前服务器', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + ], + ), + const SizedBox(height: 16), + + // 当前选中的服务器 + Wrap( + spacing: 8, + runSpacing: 8, + children: serverUrls.isEmpty || + (serverUrls.length == 1 && serverUrls[0].isEmpty) + ? [ + Chip( + avatar: Icon(Icons.info_outline, + size: 16, color: colorScheme.error), + label: const Text('未选择服务器'), + backgroundColor: + colorScheme.errorContainer.withOpacity(0.3), + ) + ] + : serverUrls + .map((url) => Chip( + avatar: Icon(Icons.dns, + size: 16, color: colorScheme.primary), + label: Text(url), + backgroundColor: colorScheme.surfaceVariant, + )) + .toList(), + ), + ], + ), + ); + } + // 新增合并后的网络状态卡片(合并了流量统计和IP信息) + // 修改网络状态卡片,去除流量统计部分 Widget _buildNetworkStatusCard(ColorScheme colorScheme) { return FloatingCard( colorScheme: colorScheme, @@ -611,33 +665,6 @@ class _HomePageState extends State { // IP信息部分 _buildIPInfo('虚拟 IP', publicIP, Icons.public, colorScheme), - const SizedBox(height: 12), - - // 流量统计部分 - const Divider(), - const SizedBox(height: 8), - Row( - children: [ - Icon(Icons.data_usage, color: colorScheme.primary, size: 18), - const SizedBox(width: 8), - Text('流量统计', - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: colorScheme.primary, - )), - ], - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - children: [ - _buildTrafficInfo('上传速度', '$uploadSpeed MB/s', Icons.upload, - colorScheme.primary), - _buildTrafficInfo('下载速度', '$downloadSpeed MB/s', Icons.download, - colorScheme.secondary), - ], - ), // 添加运行时间显示 if (_connectionState == ConnectionState.connected) ...[ diff --git a/lib/screens/settings.dart b/lib/screens/settings.dart index e12edae..372a6b0 100644 --- a/lib/screens/settings.dart +++ b/lib/screens/settings.dart @@ -20,8 +20,7 @@ final updateChecker = UpdateChecker( ); class _SettingsPageState extends State { - late List _serverList; - late String _currentServer; + late List> _serverList; final _appConfig = AppConfig(); bool _closeToTray = false; // 添加关闭进入托盘变量 bool _pingEnabled = true; // 添加全局ping开关 @@ -34,21 +33,30 @@ class _SettingsPageState extends State { void initState() { super.initState(); _serverList = _appConfig.serverList; - _currentServer = _appConfig.currentServer; - serverIP = _appConfig.currentServer; + serverIP = _getSelectedServersString(); _closeToTray = _appConfig.closeToTray; // 初始化托盘设置 // 初始化全局ping开关 _pingEnabled = _appConfig.enablePing; // 初始化 ping 状态 for (var server in _serverList) { - pingResults[server] = null; + pingResults[server['url']] = null; } // 开始 ping 所有服务器 _startPingAllServers(); } + // 获取选中的服务器字符串 + String _getSelectedServersString() { + final selected = + _serverList.where((server) => server['selected'] == true).toList(); + if (selected.isEmpty && _serverList.isNotEmpty) { + return _serverList.first['url']; + } + return selected.map((server) => server['url']).join(', '); + } + // 添加一个计时器变量来控制 ping 操作 Timer? _pingTimer; @@ -66,7 +74,7 @@ class _SettingsPageState extends State { if (_pingEnabled) { for (var server in _serverList) { - _pingServerOnce(server); + _pingServerOnce(server['url']); } } }); @@ -99,7 +107,7 @@ class _SettingsPageState extends State { if (!_pingEnabled) { // 如果关闭ping,清空所有结果 for (var server in _serverList) { - pingResults[server] = null; + pingResults[server['url']] = null; } } }); @@ -107,17 +115,32 @@ class _SettingsPageState extends State { // 添加服务器对话框 Future _showAddServerDialog() async { - final controller = TextEditingController(); - final result = await showDialog( + final urlController = TextEditingController(); + final nameController = TextEditingController(); + + final result = await showDialog>( context: context, builder: (context) => AlertDialog( title: const Text('添加服务器'), - content: TextField( - controller: controller, - decoration: const InputDecoration( - labelText: '服务器地址', - hintText: 'example.com:port', - ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: nameController, + decoration: const InputDecoration( + labelText: '服务器名称', + hintText: '自定义名称', + ), + ), + const SizedBox(height: 8), + TextField( + controller: urlController, + decoration: const InputDecoration( + labelText: '服务器地址', + hintText: 'example.com:port', + ), + ), + ], ), actions: [ TextButton( @@ -125,37 +148,67 @@ class _SettingsPageState extends State { child: const Text('取消'), ), TextButton( - onPressed: () => Navigator.pop(context, controller.text), + onPressed: () { + if (urlController.text.isNotEmpty) { + Navigator.pop(context, { + 'url': urlController.text, + 'name': nameController.text.isNotEmpty + ? nameController.text + : urlController.text, + }); + } + }, child: const Text('添加'), ), ], ), ); - if (result != null && result.isNotEmpty) { + if (result != null) { setState(() { - _serverList.add(result); + // 添加新服务器,默认不选中 + _serverList.add({ + 'url': result['url'], + 'name': result['name'], + 'selected': false, + }); _appConfig.setServerList(_serverList); // 初始化新服务器的 ping 状态 - pingResults[result] = null; + pingResults[result['url']] = null; }); } } // 编辑服务器对话框 Future _showEditServerDialog(int index) async { - final controller = TextEditingController(text: _serverList[index]); - final result = await showDialog( + final server = _serverList[index]; + final urlController = TextEditingController(text: server['url']); + final nameController = TextEditingController(text: server['name']); + + final result = await showDialog>( context: context, builder: (context) => AlertDialog( title: const Text('编辑服务器'), - content: TextField( - controller: controller, - decoration: const InputDecoration( - labelText: '服务器地址', - hintText: 'example.com:port', - ), + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextField( + controller: nameController, + decoration: const InputDecoration( + labelText: '服务器名称', + hintText: '自定义名称', + ), + ), + const SizedBox(height: 8), + TextField( + controller: urlController, + decoration: const InputDecoration( + labelText: '服务器地址', + hintText: 'example.com:port', + ), + ), + ], ), actions: [ TextButton( @@ -163,17 +216,42 @@ class _SettingsPageState extends State { child: const Text('取消'), ), TextButton( - onPressed: () => Navigator.pop(context, controller.text), + onPressed: () { + if (urlController.text.isNotEmpty) { + Navigator.pop(context, { + 'url': urlController.text, + 'name': nameController.text.isNotEmpty + ? nameController.text + : urlController.text, + }); + } + }, child: const Text('保存'), ), ], ), ); - if (result != null && result.isNotEmpty) { + if (result != null) { + final oldUrl = server['url']; setState(() { - _serverList[index] = result; + _serverList[index] = { + 'url': result['url'], + 'name': result['name'], + 'selected': server['selected'], + }; _appConfig.setServerList(_serverList); + + // 更新 ping 状态 + if (oldUrl != result['url']) { + pingResults[result['url']] = pingResults[oldUrl]; + pingResults.remove(oldUrl); + } + + // 更新当前选中的服务器显示 + serverIP = _getSelectedServersString(); + // 使用新的 serverList 方法替代直接设置 serverIP + Provider.of(context, listen: false).serverList = _serverList; }); } } @@ -206,19 +284,46 @@ class _SettingsPageState extends State { _appConfig.setServerList(_serverList); // 移除 ping 状态 - pingResults.remove(server); + pingResults.remove(server['url']); - if (_currentServer == server && _serverList.isNotEmpty) { - _currentServer = _serverList[0]; - _appConfig.setCurrentServer(_currentServer); + // 确保至少有一个服务器被选中 + if (_serverList.isNotEmpty && + !_serverList.any((server) => server['selected'] == true)) { + _serverList.first['selected'] = true; } + + // 更新当前选中的服务器显示 + serverIP = _getSelectedServersString(); + // 使用新的 serverList 方法替代直接设置 serverIP + Provider.of(context, listen: false).serverList = _serverList; }); } } + // 切换服务器选中状态 + void _toggleServerSelection(int index) { + setState(() { + _serverList[index]['selected'] = + !(_serverList[index]['selected'] ?? false); + _appConfig.setServerList(_serverList); + + // 更新当前选中的服务器显示 + serverIP = _getSelectedServersString(); + // 使用新的 serverList 方法替代直接设置 serverIP + Provider.of(context, listen: false).serverList = _serverList; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(_serverList[index]['selected'] + ? '已选中服务器: ${_serverList[index]['name']}' + : '已取消选中: ${_serverList[index]['name']}')), + ); + }); + } + // 添加构建 ping 显示组件的方法 - Widget _buildPingWidget(String server) { - final pingResult = pingResults[server]; + Widget _buildPingWidget(String url) { + final pingResult = pingResults[url]; if (!_pingEnabled) { return const Text('Ping已关闭', style: TextStyle(color: Colors.grey)); } else if (pingResult == null) { @@ -238,7 +343,6 @@ class _SettingsPageState extends State { @override Widget build(BuildContext context) { // updateChecker.checkForUpdates(context); - serverIP = Provider.of(context).virtualIP; return ListView( padding: const EdgeInsets.all(16.0), children: [ @@ -247,37 +351,36 @@ class _SettingsPageState extends State { children: [ ListTile( leading: const Icon(Icons.dns), - title: Row( - children: [ - const Text('当前服务器'), - const SizedBox(width: 8), - _buildPingWidget(_currentServer), - ], - ), - subtitle: Text(_currentServer), + title: const Text('已选中的服务器'), + subtitle: Text(serverIP), ), ExpansionTile( leading: const Icon(Icons.list), title: const Text('服务器列表'), children: [ - // 在服务器列表前添加当前服务器的 ping 状态显示 ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _serverList.length, itemBuilder: (context, index) { final server = _serverList[index]; + final isSelected = server['selected'] == true; return ListTile( - leading: const Icon(Icons.computer), + leading: Icon( + isSelected + ? Icons.check_circle + : Icons.circle_outlined, + color: isSelected ? Colors.green : null, + ), title: Row( children: [ - Text('服务器 ${index + 1}'), + Text(server['name']), const SizedBox(width: 8), - _buildPingWidget(server), + _buildPingWidget(server['url']), ], ), - subtitle: Text(server), + subtitle: Text(server['url']), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ @@ -291,17 +394,7 @@ class _SettingsPageState extends State { ), ], ), - onTap: () { - setState(() { - _currentServer = server; - Provider.of(context, listen: false).serverIP = - server; - _appConfig.setCurrentServer(_currentServer); - }); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('已切换到服务器: $server')), - ); - }, + onTap: () => _toggleServerSelection(index), ); }, ), diff --git a/lib/src/rust/api/simple.dart b/lib/src/rust/api/simple.dart index f673ed4..9cb79fd 100644 --- a/lib/src/rust/api/simple.dart +++ b/lib/src/rust/api/simple.dart @@ -37,7 +37,7 @@ Future createServer( required String specifiedIp, required String roomName, required String roomPassword, - required String severurl}) => + required List severurl}) => RustLib.instance.api.crateApiSimpleCreateServer( username: username, enableDhcp: enableDhcp, diff --git a/lib/src/rust/frb_generated.dart b/lib/src/rust/frb_generated.dart index c140062..319753d 100644 --- a/lib/src/rust/frb_generated.dart +++ b/lib/src/rust/frb_generated.dart @@ -85,7 +85,7 @@ abstract class RustLibApi extends BaseApi { required String specifiedIp, required String roomName, required String roomPassword, - required String severurl}); + required List severurl}); Future crateApiSimpleEasytierVersion(); @@ -174,7 +174,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { required String specifiedIp, required String roomName, required String roomPassword, - required String severurl}) { + required List severurl}) { return handler.executeNormal(NormalTask( callFfi: (port_) { final serializer = SseSerializer(generalizedFrbRustBinding); @@ -183,7 +183,7 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { sse_encode_String(specifiedIp, serializer); sse_encode_String(roomName, serializer); sse_encode_String(roomPassword, serializer); - sse_encode_String(severurl, serializer); + sse_encode_list_String(severurl, serializer); pdeCallFfi(generalizedFrbRustBinding, serializer, funcId: 2, port: port_); }, @@ -611,6 +611,12 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { .toList(); } + @protected + List dco_decode_list_String(dynamic raw) { + // Codec=Dco (DartCObject based), see doc to use other codecs + return (raw as List).map(dco_decode_String).toList(); + } + @protected List dco_decode_list_kv_node_connection_stats( dynamic raw) { @@ -874,6 +880,18 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { return ans_; } + @protected + List sse_decode_list_String(SseDeserializer deserializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + + var len_ = sse_decode_i_32(deserializer); + var ans_ = []; + for (var idx_ = 0; idx_ < len_; ++idx_) { + ans_.add(sse_decode_String(deserializer)); + } + return ans_; + } + @protected List sse_decode_list_kv_node_connection_stats( SseDeserializer deserializer) { @@ -1117,6 +1135,15 @@ class RustLibApiImpl extends RustLibApiImplPlatform implements RustLibApi { } } + @protected + void sse_encode_list_String(List self, SseSerializer serializer) { + // Codec=Sse (Serialization based), see doc to use other codecs + sse_encode_i_32(self.length, serializer); + for (final item in self) { + sse_encode_String(item, serializer); + } + } + @protected void sse_encode_list_kv_node_connection_stats( List self, SseSerializer serializer) { diff --git a/lib/src/rust/frb_generated.io.dart b/lib/src/rust/frb_generated.io.dart index 5034fc7..74f9ef2 100644 --- a/lib/src/rust/frb_generated.io.dart +++ b/lib/src/rust/frb_generated.io.dart @@ -110,6 +110,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( dynamic raw); + @protected + List dco_decode_list_String(dynamic raw); + @protected List dco_decode_list_kv_node_connection_stats( dynamic raw); @@ -219,6 +222,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( SseDeserializer deserializer); + @protected + List sse_decode_list_String(SseDeserializer deserializer); + @protected List sse_decode_list_kv_node_connection_stats( SseDeserializer deserializer); @@ -329,6 +335,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( List self, SseSerializer serializer); + @protected + void sse_encode_list_String(List self, SseSerializer serializer); + @protected void sse_encode_list_kv_node_connection_stats( List self, SseSerializer serializer); diff --git a/lib/src/rust/frb_generated.web.dart b/lib/src/rust/frb_generated.web.dart index 72cee18..00dbb1b 100644 --- a/lib/src/rust/frb_generated.web.dart +++ b/lib/src/rust/frb_generated.web.dart @@ -112,6 +112,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { dco_decode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( dynamic raw); + @protected + List dco_decode_list_String(dynamic raw); + @protected List dco_decode_list_kv_node_connection_stats( dynamic raw); @@ -221,6 +224,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_decode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( SseDeserializer deserializer); + @protected + List sse_decode_list_String(SseDeserializer deserializer); + @protected List sse_decode_list_kv_node_connection_stats( SseDeserializer deserializer); @@ -331,6 +337,9 @@ abstract class RustLibApiImplPlatform extends BaseApiImpl { sse_encode_list_Auto_Owned_RustOpaque_flutter_rust_bridgefor_generatedRustAutoOpaqueInnerRoute( List self, SseSerializer serializer); + @protected + void sse_encode_list_String(List self, SseSerializer serializer); + @protected void sse_encode_list_kv_node_connection_stats( List self, SseSerializer serializer); diff --git a/lib/utils/kv_state.dart b/lib/utils/kv_state.dart index f444571..dcbac9f 100644 --- a/lib/utils/kv_state.dart +++ b/lib/utils/kv_state.dart @@ -47,13 +47,52 @@ class KM extends ChangeNotifier { notifyListeners(); } - //当前服务器IP - String get serverIP => _config.currentServer; - set serverIP(String value) { - _config.setCurrentServer(value); +//服务器列表 + List> get serverList => _config.serverList; + set serverList(List> value) { + List> convertedList = value.map((item) { + return Map.from(item); + }).toList(); + _config.setServerList(convertedList); notifyListeners(); } + //获取选中的服务器 + //获取选中的服务器 + List get serverIP { + try { + final selected = + serverList.where((server) => server['selected'] == true).toList(); + + if (selected.isEmpty && serverList.isNotEmpty) { + final firstServer = serverList.first; + if (firstServer['url'] is String) { + return [firstServer['url'] as String]; + } + return []; + } + + return selected + .where((server) => server['url'] is String) + .map((server) => server['url'] as String) + .toList(); + } catch (e) { + debugPrint('获取服务器IP时出错: $e'); + return []; + } + } + + //设置服务器选中状态 + void setServerSelected(String url, bool selected) { + final servers = serverList; + for (var i = 0; i < servers.length; i++) { + if (servers[i]['url'] == url) { + servers[i]['selected'] = selected; + } + } + serverList = servers; + } + // 节点列表 List _nodes = []; List get nodes => _nodes; diff --git a/pubspec.lock b/pubspec.lock index dfde858..5312922 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,29 +5,24 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" - url: "https://pub.dev" + sha256: dc27559385e905ad30838356c5f5d574014ba39872d732111cd07ac0beff4c57 + url: "https://pub.flutter-io.cn" source: hosted - version: "76.0.0" - _macros: - dependency: transitive - description: dart - source: sdk - version: "0.3.3" + version: "80.0.0" analyzer: dependency: transitive description: name: analyzer - sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" - url: "https://pub.dev" + sha256: "192d1c5b944e7e53b24b5586db760db934b177d4147c42fbca8c8c5f1eb8d11e" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.11.0" + version: "7.3.0" args: dependency: transitive description: name: args sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.7.0" async: @@ -35,7 +30,7 @@ packages: description: name: async sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.12.0" boolean_selector: @@ -43,71 +38,71 @@ packages: description: name: boolean_selector sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" build: dependency: transitive description: name: build - sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" - url: "https://pub.dev" + sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 + url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.1" + version: "2.4.2" build_cli_annotations: dependency: transitive description: name: build_cli_annotations sha256: b59d2769769efd6c9ff6d4c4cede0be115a566afc591705c2040b707534b1172 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" build_config: dependency: transitive description: name: build_config - sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 - url: "https://pub.dev" + sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.1.1" + version: "1.1.2" build_daemon: dependency: transitive description: name: build_daemon - sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" - url: "https://pub.dev" + sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.2" + version: "4.0.4" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" - url: "https://pub.dev" + sha256: b9e4fda21d846e192628e7a4f6deda6888c36b5b69ba02ff291a01fd529140f0 + url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.2" + version: "2.4.4" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" - url: "https://pub.dev" + sha256: "058fe9dce1de7d69c4b84fada934df3e0153dd000758c4d65964d0166779aa99" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.13" + version: "2.4.15" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 - url: "https://pub.dev" + sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + url: "https://pub.flutter-io.cn" source: hosted - version: "7.3.2" + version: "8.0.0" built_collection: dependency: transitive description: name: built_collection sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.1.1" built_value: @@ -115,7 +110,7 @@ packages: description: name: built_value sha256: ea90e81dc4a25a043d9bee692d20ed6d1c4a1662a28c03a96417446c093ed6b4 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.9.5" characters: @@ -123,7 +118,7 @@ packages: description: name: characters sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" checked_yaml: @@ -131,7 +126,7 @@ packages: description: name: checked_yaml sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.3" clock: @@ -139,7 +134,7 @@ packages: description: name: clock sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.2" code_builder: @@ -147,7 +142,7 @@ packages: description: name: code_builder sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.10.1" collection: @@ -155,7 +150,7 @@ packages: description: name: collection sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.19.1" convert: @@ -163,7 +158,7 @@ packages: description: name: convert sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.2" crypto: @@ -171,7 +166,7 @@ packages: description: name: crypto sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.6" cupertino_icons: @@ -179,23 +174,23 @@ packages: description: name: cupertino_icons sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.8" dart_style: dependency: transitive description: name: dart_style - sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" - url: "https://pub.dev" + sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.7" + version: "3.0.1" dbus: dependency: transitive description: name: dbus sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.11" equatable: @@ -203,7 +198,7 @@ packages: description: name: equatable sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.7" fake_async: @@ -211,23 +206,23 @@ packages: description: name: fake_async sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.2" ffi: dependency: transitive description: name: ffi - sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" - url: "https://pub.dev" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.1.3" + version: "2.1.4" file: dependency: transitive description: name: file sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "7.0.1" fixnum: @@ -235,7 +230,7 @@ packages: description: name: fixnum sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" fl_chart: @@ -243,7 +238,7 @@ packages: description: name: fl_chart sha256: "5276944c6ffc975ae796569a826c38a62d2abcf264e26b88fa6f482e107f4237" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.70.2" flutter: @@ -256,7 +251,7 @@ packages: description: name: flutter_colorpicker sha256: "969de5f6f9e2a570ac660fb7b501551451ea2a1ab9e2097e89475f60e07816ea" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" flutter_driver: @@ -269,7 +264,7 @@ packages: description: name: flutter_lints sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.0" flutter_local_notifications: @@ -277,7 +272,7 @@ packages: description: name: flutter_local_notifications sha256: d59eeafd6df92174b1d5f68fc9d66634c97ce2e7cfe2293476236547bb19bbbd - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "19.0.0" flutter_local_notifications_linux: @@ -285,7 +280,7 @@ packages: description: name: flutter_local_notifications_linux sha256: e3c277b2daab8e36ac5a6820536668d07e83851aeeb79c446e525a70710770a5 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.0.0" flutter_local_notifications_platform_interface: @@ -293,7 +288,7 @@ packages: description: name: flutter_local_notifications_platform_interface sha256: "2569b973fc9d1f63a37410a9f7c1c552081226c597190cb359ef5d5762d1631c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "9.0.0" flutter_local_notifications_windows: @@ -301,7 +296,7 @@ packages: description: name: flutter_local_notifications_windows sha256: f8fc0652a601f83419d623c85723a3e82ad81f92b33eaa9bcc21ea1b94773e6e - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" flutter_localizations: @@ -314,7 +309,7 @@ packages: description: name: flutter_rust_bridge sha256: "5a5c7a5deeef2cc2ffe6076a33b0429f4a20ceac22a397297aed2b1eb067e611" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.9.0" flutter_staggered_grid_view: @@ -322,7 +317,7 @@ packages: description: name: flutter_staggered_grid_view sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" flutter_test: @@ -340,7 +335,7 @@ packages: description: name: frontend_server_client sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" fuchsia_remote_debug_protocol: @@ -353,7 +348,7 @@ packages: description: name: glob sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.3" graphs: @@ -361,7 +356,7 @@ packages: description: name: graphs sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.2" http: @@ -369,7 +364,7 @@ packages: description: name: http sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" http_multi_server: @@ -377,17 +372,17 @@ packages: description: name: http_multi_server sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.2" http_parser: dependency: transitive description: name: http_parser - sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" - url: "https://pub.dev" + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.flutter-io.cn" source: hosted - version: "4.0.2" + version: "4.1.2" integration_test: dependency: "direct dev" description: flutter @@ -398,7 +393,7 @@ packages: description: name: intl sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.19.0" io: @@ -406,39 +401,39 @@ packages: description: name: io sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.5" js: dependency: transitive description: name: js - sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf - url: "https://pub.dev" + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" + url: "https://pub.flutter-io.cn" source: hosted - version: "0.7.1" + version: "0.7.2" json_annotation: dependency: "direct main" description: name: json_annotation sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "4.9.0" json_serializable: dependency: "direct dev" description: name: json_serializable - sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c - url: "https://pub.dev" + sha256: "81f04dee10969f89f604e1249382d46b97a1ccad53872875369622b5bfc9e58a" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.9.0" + version: "6.9.4" leak_tracker: dependency: transitive description: name: leak_tracker sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "10.0.8" leak_tracker_flutter_testing: @@ -446,7 +441,7 @@ packages: description: name: leak_tracker_flutter_testing sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.9" leak_tracker_testing: @@ -454,39 +449,31 @@ packages: description: name: leak_tracker_testing sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" - url: "https://pub.dev" + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://pub.flutter-io.cn" source: hosted - version: "5.0.0" + version: "5.1.1" logging: dependency: transitive description: name: logging sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" - macros: - dependency: transitive - description: - name: macros - sha256: "1d9e801cd66f7ea3663c45fc708450db1fa57f988142c64289142c9b7ee80656" - url: "https://pub.dev" - source: hosted - version: "0.1.3-main.0" matcher: dependency: transitive description: name: matcher sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.17" material_color_utilities: @@ -494,7 +481,7 @@ packages: description: name: material_color_utilities sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.11.1" menu_base: @@ -502,7 +489,7 @@ packages: description: name: menu_base sha256: "820368014a171bd1241030278e6c2617354f492f5c703d7b7d4570a6b8b84405" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.1" meta: @@ -510,7 +497,7 @@ packages: description: name: meta sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.16.0" mime: @@ -518,7 +505,7 @@ packages: description: name: mime sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" nested: @@ -526,7 +513,7 @@ packages: description: name: nested sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" package_config: @@ -534,7 +521,7 @@ packages: description: name: package_config sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" package_info_plus: @@ -542,7 +529,7 @@ packages: description: name: package_info_plus sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "8.3.0" package_info_plus_platform_interface: @@ -550,7 +537,7 @@ packages: description: name: package_info_plus_platform_interface sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.0" path: @@ -558,7 +545,7 @@ packages: description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.9.1" path_provider_linux: @@ -566,7 +553,7 @@ packages: description: name: path_provider_linux sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.1" path_provider_platform_interface: @@ -574,7 +561,7 @@ packages: description: name: path_provider_platform_interface sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" path_provider_windows: @@ -582,23 +569,23 @@ packages: description: name: path_provider_windows sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.0" petitparser: dependency: transitive description: name: petitparser - sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 - url: "https://pub.dev" + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.0.2" + version: "6.1.0" platform: dependency: transitive description: name: platform sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.6" plugin_platform_interface: @@ -606,7 +593,7 @@ packages: description: name: plugin_platform_interface sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.8" pool: @@ -614,7 +601,7 @@ packages: description: name: pool sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.5.1" process: @@ -622,7 +609,7 @@ packages: description: name: process sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "5.0.3" provider: @@ -630,7 +617,7 @@ packages: description: name: provider sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.1.2" pub_semver: @@ -638,17 +625,17 @@ packages: description: name: pub_semver sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.2.0" pubspec_parse: dependency: transitive description: name: pubspec_parse - sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" - url: "https://pub.dev" + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.0" + version: "1.5.0" rust_lib_fltier: dependency: "direct main" description: @@ -661,7 +648,7 @@ packages: description: name: screen_retriever sha256: "570dbc8e4f70bac451e0efc9c9bb19fa2d6799a11e6ef04f946d7886d2e23d0c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_linux: @@ -669,7 +656,7 @@ packages: description: name: screen_retriever_linux sha256: f7f8120c92ef0784e58491ab664d01efda79a922b025ff286e29aa123ea3dd18 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_macos: @@ -677,7 +664,7 @@ packages: description: name: screen_retriever_macos sha256: "71f956e65c97315dd661d71f828708bd97b6d358e776f1a30d5aa7d22d78a149" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_platform_interface: @@ -685,7 +672,7 @@ packages: description: name: screen_retriever_platform_interface sha256: ee197f4581ff0d5608587819af40490748e1e39e648d7680ecf95c05197240c0 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" screen_retriever_windows: @@ -693,7 +680,7 @@ packages: description: name: screen_retriever_windows sha256: "449ee257f03ca98a57288ee526a301a430a344a161f9202b4fcc38576716fe13" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" shared_preferences: @@ -701,23 +688,23 @@ packages: description: name: shared_preferences sha256: "846849e3e9b68f3ef4b60c60cf4b3e02e9321bc7f4d8c4692cf87ffa82fc8a3a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.2" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - sha256: "9f9f3d372d4304723e6136663bb291c0b93f5e4c8a4a6314347f481a33bda2b1" - url: "https://pub.dev" + sha256: "3ec7210872c4ba945e3244982918e502fa2bfb5230dff6832459ca0e1879b7ad" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.4.7" + version: "2.4.8" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.4" shared_preferences_linux: @@ -725,7 +712,7 @@ packages: description: name: shared_preferences_linux sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" shared_preferences_platform_interface: @@ -733,7 +720,7 @@ packages: description: name: shared_preferences_platform_interface sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" shared_preferences_web: @@ -741,7 +728,7 @@ packages: description: name: shared_preferences_web sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.3" shared_preferences_windows: @@ -749,31 +736,31 @@ packages: description: name: shared_preferences_windows sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.4.1" shelf: dependency: transitive description: name: shelf - sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 - url: "https://pub.dev" + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.flutter-io.cn" source: hosted - version: "1.4.1" + version: "1.4.2" shelf_web_socket: dependency: transitive description: name: shelf_web_socket - sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 - url: "https://pub.dev" + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.1" + version: "3.0.0" shortid: dependency: transitive description: name: shortid sha256: d0b40e3dbb50497dad107e19c54ca7de0d1a274eb9b4404991e443dadb9ebedb - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.2" sky_engine: @@ -785,16 +772,16 @@ packages: dependency: transitive description: name: source_gen - sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" - url: "https://pub.dev" + sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + url: "https://pub.flutter-io.cn" source: hosted - version: "1.5.0" + version: "2.0.0" source_helper: dependency: transitive description: name: source_helper sha256: "86d247119aedce8e63f4751bd9626fc9613255935558447569ad42f9f5b48b3c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.5" source_span: @@ -802,7 +789,7 @@ packages: description: name: source_span sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.1" stack_trace: @@ -810,7 +797,7 @@ packages: description: name: stack_trace sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.12.1" stream_channel: @@ -818,7 +805,7 @@ packages: description: name: stream_channel sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" stream_transform: @@ -826,7 +813,7 @@ packages: description: name: stream_transform sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" string_scanner: @@ -834,7 +821,7 @@ packages: description: name: string_scanner sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" sync_http: @@ -842,7 +829,7 @@ packages: description: name: sync_http sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.1" system_tray: @@ -850,7 +837,7 @@ packages: description: name: system_tray sha256: "40444e5de8ed907822a98694fd031b8accc3cb3c0baa547634ce76189cf3d9cf" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.3" term_glyph: @@ -858,7 +845,7 @@ packages: description: name: term_glyph sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.2" test_api: @@ -866,7 +853,7 @@ packages: description: name: test_api sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.4" timezone: @@ -874,7 +861,7 @@ packages: description: name: timezone sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.10.0" timing: @@ -882,7 +869,7 @@ packages: description: name: timing sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" tray_manager: @@ -890,7 +877,7 @@ packages: description: name: tray_manager sha256: "80be6c508159a6f3c57983de795209ac13453e9832fd574143b06dceee188ed2" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.3.2" typed_data: @@ -898,7 +885,7 @@ packages: description: name: typed_data sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.4.0" url_launcher: @@ -906,23 +893,23 @@ packages: description: name: url_launcher sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.1" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "6fc2f56536ee873eeb867ad176ae15f304ccccc357848b351f6f0d8d4a40d193" - url: "https://pub.dev" + sha256: "1d0eae19bd7606ef60fe69ef3b312a437a16549476c42321d5dc1506c9ca3bf4" + url: "https://pub.flutter-io.cn" source: hosted - version: "6.3.14" + version: "6.3.15" url_launcher_ios: dependency: transitive description: name: url_launcher_ios sha256: "16a513b6c12bb419304e72ea0ae2ab4fed569920d1c7cb850263fe3acc824626" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.3.2" url_launcher_linux: @@ -930,7 +917,7 @@ packages: description: name: url_launcher_linux sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.1" url_launcher_macos: @@ -938,7 +925,7 @@ packages: description: name: url_launcher_macos sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.2.2" url_launcher_platform_interface: @@ -946,23 +933,23 @@ packages: description: name: url_launcher_platform_interface sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.3.2" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" - url: "https://pub.dev" + sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + url: "https://pub.flutter-io.cn" source: hosted - version: "2.3.3" + version: "2.4.0" url_launcher_windows: dependency: transitive description: name: url_launcher_windows sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.4" uuid: @@ -970,7 +957,7 @@ packages: description: name: uuid sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.7" vector_math: @@ -978,7 +965,7 @@ packages: description: name: vector_math sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.4" vm_service: @@ -986,7 +973,7 @@ packages: description: name: vm_service sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "14.3.1" watcher: @@ -994,7 +981,7 @@ packages: description: name: watcher sha256: "69da27e49efa56a15f8afe8f4438c4ec02eff0a117df1b22ea4aad194fe1c104" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" web: @@ -1002,7 +989,7 @@ packages: description: name: web sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.1" web_socket: @@ -1010,7 +997,7 @@ packages: description: name: web_socket sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.1.6" web_socket_channel: @@ -1018,7 +1005,7 @@ packages: description: name: web_socket_channel sha256: "0b8e2457400d8a859b7b2030786835a28a8e80836ef64402abef392ff4f1d0e5" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.2" webdriver: @@ -1026,23 +1013,23 @@ packages: description: name: webdriver sha256: "3d773670966f02a646319410766d3b5e1037efb7f07cc68f844d5e06cd4d61c8" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.4" win32: dependency: transitive description: name: win32 - sha256: daf97c9d80197ed7b619040e86c8ab9a9dad285e7671ee7390f9180cc828a51e - url: "https://pub.dev" + sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f + url: "https://pub.flutter-io.cn" source: hosted - version: "5.10.1" + version: "5.12.0" window_manager: dependency: "direct main" description: name: window_manager sha256: "732896e1416297c63c9e3fb95aea72d0355f61390263982a47fd519169dc5059" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "0.4.3" windows_notification: @@ -1050,7 +1037,7 @@ packages: description: name: windows_notification sha256: be3e650874615f315402c9b9f3656e29af156709c4b5cc272cb4ca0ab7ba94a8 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" xdg_directories: @@ -1058,7 +1045,7 @@ packages: description: name: xdg_directories sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" xml: @@ -1066,7 +1053,7 @@ packages: description: name: xml sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "6.5.0" yaml: @@ -1074,9 +1061,9 @@ packages: description: name: yaml sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce - url: "https://pub.dev" + url: "https://pub.flutter-io.cn" source: hosted version: "3.1.3" sdks: - dart: ">=3.7.0-0 <4.0.0" - flutter: ">=3.24.0" + dart: ">=3.7.0 <4.0.0" + flutter: ">=3.27.0" diff --git a/rust/Cargo.lock b/rust/Cargo.lock index db750bd..2879d09 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -389,6 +389,15 @@ dependencies = [ "x25519-dalek", ] +[[package]] +name = "bounded_join_set" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae18fd8f4a623bcf416b5bc8f1e0905534d9911597ed17cc57ab9b6eed65454d" +dependencies = [ + "tokio", +] + [[package]] name = "bstr" version = "1.8.0" @@ -954,7 +963,7 @@ dependencies = [ [[package]] name = "easytier" -version = "2.2.2" +version = "2.2.3" dependencies = [ "anyhow", "async-compression", @@ -967,6 +976,7 @@ dependencies = [ "base64 0.22.1", "bitflags 2.9.0", "boringtun-easytier", + "bounded_join_set", "bytecodec", "byteorder", "bytes", diff --git a/rust/easytier/Cargo.lock b/rust/easytier/Cargo.lock deleted file mode 100644 index 5a72f3e..0000000 --- a/rust/easytier/Cargo.lock +++ /dev/null @@ -1,5274 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.6.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" -dependencies = [ - "anstyle", - "once_cell", - "windows-sys 0.59.0", -] - -[[package]] -name = "anyhow" -version = "1.0.97" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "async-compression" -version = "0.4.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0cf008e5e1a9e9e22a7d3c9a4992e21a350290069e36d8fb72304ed17e8f2d2" -dependencies = [ - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "zstd 0.13.3", - "zstd-safe 7.2.3", -] - -[[package]] -name = "async-event" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1222afd3d2bce3995035054046a279ae7aa154d70d0766cea050073f3fd7ddf" -dependencies = [ - "loom", - "pin-project-lite", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "async-ringbuf" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3535a88714d7b0d7e5bb26aa474c574b5a7d4bfce5e76a035686c35b1bcd4491" -dependencies = [ - "futures", - "ringbuf", -] - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "atomic-shim" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cd4b51d303cf3501c301e8125df442128d3c6d7c69f71b27833d253de47e77" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "auto_impl" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12882f59de5360c748c4cbf569a042d5fb0eb515f7bea9c1f470b47f6ffbd73" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[package]] -name = "base62" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e52a7bcb1d6beebee21fb5053af9e3cbb7a7ed1a4909e534040e676437ab1f" -dependencies = [ - "rustversion", -] - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64ct" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" - -[[package]] -name = "bindgen" -version = "0.71.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" -dependencies = [ - "bitflags 2.9.0", - "cexpr", - "clang-sys", - "itertools 0.13.0", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.100", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "boringtun-easytier" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f09b4d1ada8affba260cb185bbdf6d5acff42f924dea1a17f938cf3e8fbe475" -dependencies = [ - "aead", - "atomic-shim", - "base64 0.13.1", - "blake2", - "chacha20poly1305", - "hex", - "hmac", - "ip_network", - "ip_network_table", - "libc", - "nix 0.25.1", - "parking_lot", - "rand_core 0.6.4", - "ring", - "tracing", - "untrusted", - "x25519-dalek", -] - -[[package]] -name = "bstr" -version = "1.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[package]] -name = "bytecodec" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adf4c9d0bbf32eea58d7c0f812058138ee8edaf0f2802b6d03561b504729a325" -dependencies = [ - "byteorder", - "trackable 0.2.24", -] - -[[package]] -name = "bytecount" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "c2rust-bitfields" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43c3f07ab0ef604fa6f595aa46ec2f8a22172c975e186f6f5bf9829a3b72c41" -dependencies = [ - "c2rust-bitfields-derive", -] - -[[package]] -name = "c2rust-bitfields-derive" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3cbc102e2597c9744c8bd8c15915d554300601c91a079430d309816b0912545" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "cc" -version = "1.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "chrono" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "cidr" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdf600c45bd958cf2945c445264471cca8b6c8e67bc87b71affd6d7e5682621" -dependencies = [ - "serde", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", - "zeroize", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", - "terminal_size", - "unicase", - "unicode-width 0.2.0", -] - -[[package]] -name = "clap_derive" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "codepage" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48f68d061bc2828ae826206326e61251aca94c1e4a5305cf52d9138639c918b4" -dependencies = [ - "encoding_rs", -] - -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - -[[package]] -name = "data-encoding" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" - -[[package]] -name = "defguard_wireguard_rs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba16f17698d4b389907310af018b0c3a80b025bba9c38d947cbc6dd70921743" -dependencies = [ - "base64 0.21.7", - "libc", - "log", - "netlink-packet-core", - "netlink-packet-generic", - "netlink-packet-route 0.17.1", - "netlink-packet-utils", - "netlink-packet-wireguard", - "netlink-sys", - "nix 0.27.1", - "serde", - "thiserror 1.0.69", -] - -[[package]] -name = "defmt" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6" -dependencies = [ - "defmt-parser", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "defmt-parser" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3" -dependencies = [ - "thiserror 2.0.12", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "diatomic-waker" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28025fb55a9d815acf7b0877555f437254f373036eec6ed265116c7a5c0825e9" -dependencies = [ - "loom", - "waker-fn", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "displaydoc" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "easytier" -version = "2.2.2" -dependencies = [ - "aes-gcm", - "anyhow", - "async-compression", - "async-recursion", - "async-ringbuf", - "async-stream", - "async-trait", - "atomic-shim", - "auto_impl", - "base64 0.22.1", - "bitflags 2.9.0", - "boringtun-easytier", - "bytecodec", - "byteorder", - "bytes", - "chrono", - "cidr", - "clap", - "crossbeam", - "dashmap", - "defguard_wireguard_rs", - "easytier-rpc-build", - "encoding", - "futures", - "futures-util", - "gethostname", - "git-version", - "globwalk", - "hickory-resolver", - "http", - "http_req", - "humansize", - "kcp-sys", - "machine-uid", - "mimalloc-rust", - "netlink-packet-core", - "netlink-packet-route 0.21.0", - "netlink-packet-utils", - "netlink-sys", - "network-interface", - "nix 0.29.0", - "once_cell", - "parking_lot", - "percent-encoding", - "petgraph", - "pin-project-lite", - "pnet", - "prost", - "prost-build", - "prost-reflect", - "prost-reflect-build", - "prost-types", - "quinn", - "rand 0.8.5", - "rcgen", - "regex", - "reqwest", - "ring", - "ringbuf", - "rstest", - "rust-i18n", - "rustls", - "serde", - "serde_json", - "serial_test", - "service-manager", - "smoltcp", - "socket2", - "stun_codec", - "sys-locale", - "tabled", - "tachyonix", - "thiserror 1.0.69", - "time", - "timedmap", - "tokio", - "tokio-rustls", - "tokio-socks", - "tokio-stream", - "tokio-util", - "tokio-websockets", - "toml", - "tonic-build", - "tracing", - "tracing-appender", - "tracing-subscriber", - "tun-easytier", - "url", - "uuid", - "wildmatch", - "windows 0.52.0", - "windows-service", - "winreg 0.52.0", - "zerocopy 0.7.35", - "zip", -] - -[[package]] -name = "easytier-rpc-build" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24829168c28f6a448f57d18116c255dcbd2b8c25e76dbc60f6cd16d68ad2cf07" -dependencies = [ - "heck 0.5.0", - "prost-build", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "encoding" -version = "0.2.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -dependencies = [ - "encoding-index-japanese", - "encoding-index-korean", - "encoding-index-simpchinese", - "encoding-index-singlebyte", - "encoding-index-tradchinese", -] - -[[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -dependencies = [ - "encoding_index_tests", -] - -[[package]] -name = "encoding-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b881ab2524b96a5ce932056c7482ba6152e2226fed3936b3e592adeb95ca6d" -dependencies = [ - "codepage", - "encoding_rs", - "windows-sys 0.52.0", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" - -[[package]] -name = "encoding_rs" -version = "0.8.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enum-as-inner" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flate2" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generator" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "windows 0.48.0", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "gethostname" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc3655aa6818d65bc620d6911f05aa7b6aeb596291e1e9f79e52df85583d1e30" -dependencies = [ - "rustix 0.38.44", - "windows-targets 0.52.6", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.13.3+wasi-0.2.2", - "windows-targets 0.52.6", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "git-version" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" -dependencies = [ - "git-version-macro", -] - -[[package]] -name = "git-version-macro" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "globset" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5" -dependencies = [ - "aho-corasick", - "bstr", - "log", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "globwalk" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" -dependencies = [ - "bitflags 1.3.2", - "ignore", - "walkdir", -] - -[[package]] -name = "h2" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hickory-proto" -version = "0.24.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna", - "ipnet", - "once_cell", - "rand 0.8.5", - "thiserror 1.0.69", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "hickory-resolver" -version = "0.24.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" -dependencies = [ - "cfg-if", - "futures-util", - "hickory-proto", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot", - "rand 0.8.5", - "resolv-conf", - "smallvec", - "thiserror 1.0.69", - "tokio", - "tracing", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest", -] - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "hostname" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" -dependencies = [ - "cfg-if", - "libc", - "windows 0.52.0", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "http_req" -version = "0.13.1" -source = "git+https://github.com/EasyTier/http_req.git#b10aa9fc0db3067cc3d2174683a87250b80a1ea9" -dependencies = [ - "base64 0.22.1", - "rand 0.8.5", - "rustls", - "rustls-pemfile", - "rustls-pki-types", - "unicase", - "webpki", - "webpki-roots", - "zeroize", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "humansize" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" -dependencies = [ - "libm", -] - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "hyper", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "ignore" -version = "0.4.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" -dependencies = [ - "crossbeam-deque", - "globset", - "log", - "memchr", - "regex-automata 0.4.9", - "same-file", - "walkdir", - "winapi-util", -] - -[[package]] -name = "indexmap" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", -] - -[[package]] -name = "inout" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - -[[package]] -name = "ip_network" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2f047c0a98b2f299aa5d6d7088443570faae494e9ae1305e48be000c9e0eb1" - -[[package]] -name = "ip_network_table" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4099b7cfc5c5e2fe8c5edf3f6f7adf7a714c9cc697534f63a5a5da30397cb2c0" -dependencies = [ - "ip_network", - "ip_network_table-deps-treebitmap", -] - -[[package]] -name = "ip_network_table-deps-treebitmap" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e537132deb99c0eb4b752f0346b6a836200eaaa3516dd7e5514b63930a09e5d" - -[[package]] -name = "ipconfig" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" -dependencies = [ - "socket2", - "widestring", - "windows-sys 0.48.0", - "winreg 0.50.0", -] - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "ipnetwork" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" -dependencies = [ - "serde", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" -dependencies = [ - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "kcp-sys" -version = "0.1.0" -source = "git+https://github.com/EasyTier/kcp-sys#0f0a0558391ba391c089806c23f369651f6c9eeb" -dependencies = [ - "anyhow", - "auto_impl", - "bindgen", - "bitflags 2.9.0", - "bytes", - "cc", - "dashmap", - "parking_lot", - "rand 0.8.5", - "thiserror 2.0.12", - "tokio", - "tokio-util", - "tracing", - "tracing-subscriber", - "zerocopy 0.7.35", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.171" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.9.0", - "libc", -] - -[[package]] -name = "libyml" -version = "0.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" -dependencies = [ - "anyhow", - "version_check", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" - -[[package]] -name = "loom" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "machine-uid" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4506fa0abb0a2ea93f5862f55973da0a662d2ad0e98f337a1c5aac657f0892" -dependencies = [ - "libc", - "winreg 0.52.0", -] - -[[package]] -name = "managed" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca88d725a0a943b096803bd34e73a4437208b6077654cc4ecb2947a5f91618d" - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mimalloc-rust" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb726c8298efb4010b2c46d8050e4be36cf807b9d9e98cb112f830914fc9bbe" -dependencies = [ - "cty", - "mimalloc-rust-sys", -] - -[[package]] -name = "mimalloc-rust-sys" -version = "1.7.9-source" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6413e13241a9809f291568133eca6694572cf528c1a6175502d090adce5dd5db" -dependencies = [ - "cc", - "cty", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" -dependencies = [ - "adler2", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "multimap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" - -[[package]] -name = "native-tls" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "netlink-packet-core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" -dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-generic" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7eb8ad331c84c6b8cb7f685b448133e5ad82e1ffd5acafac374af4a5a308b" -dependencies = [ - "anyhow", - "byteorder", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-route" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" -dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", - "libc", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-route" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "483325d4bfef65699214858f097d504eb812c38ce7077d165f301ec406c3066e" -dependencies = [ - "anyhow", - "bitflags 2.9.0", - "byteorder", - "libc", - "log", - "netlink-packet-core", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-packet-utils" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" -dependencies = [ - "anyhow", - "byteorder", - "paste", - "thiserror 1.0.69", -] - -[[package]] -name = "netlink-packet-wireguard" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b25b050ff1f6a1e23c6777b72db22790fe5b6b5ccfd3858672587a79876c8f" -dependencies = [ - "anyhow", - "byteorder", - "libc", - "log", - "netlink-packet-generic", - "netlink-packet-utils", -] - -[[package]] -name = "netlink-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c903aa70590cb93691bf97a767c8d1d6122d2cc9070433deb3bbf36ce8bd23" -dependencies = [ - "bytes", - "libc", - "log", -] - -[[package]] -name = "network-interface" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433419f898328beca4f2c6c73a1b52540658d92b0a99f0269330457e0fd998d5" -dependencies = [ - "cc", - "libc", - "thiserror 1.0.69", - "winapi", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "normpath" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl" -version = "0.10.71" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "papergrid" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7419ad52a7de9b60d33e11085a0fe3df1fbd5926aa3f93d3dd53afbc9e86725" -dependencies = [ - "bytecount", - "fnv", - "unicode-width 0.1.11", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -dependencies = [ - "base64 0.22.1", - "serde", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "petgraph" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "plist" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" -dependencies = [ - "base64 0.22.1", - "indexmap", - "quick-xml", - "serde", - "time", -] - -[[package]] -name = "pnet" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "682396b533413cc2e009fbb48aadf93619a149d3e57defba19ff50ce0201bd0d" -dependencies = [ - "ipnetwork", - "pnet_base", - "pnet_datalink", - "pnet_packet", - "pnet_sys", - "pnet_transport", -] - -[[package]] -name = "pnet_base" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" -dependencies = [ - "no-std-net", - "serde", -] - -[[package]] -name = "pnet_datalink" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" -dependencies = [ - "ipnetwork", - "libc", - "pnet_base", - "pnet_sys", - "serde", - "winapi", -] - -[[package]] -name = "pnet_macros" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13325ac86ee1a80a480b0bc8e3d30c25d133616112bb16e86f712dcf8a71c863" -dependencies = [ - "proc-macro2", - "quote", - "regex", - "syn 2.0.100", -] - -[[package]] -name = "pnet_macros_support" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed67a952585d509dd0003049b1fc56b982ac665c8299b124b90ea2bdb3134ab" -dependencies = [ - "pnet_base", -] - -[[package]] -name = "pnet_packet" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c96ebadfab635fcc23036ba30a7d33a80c39e8461b8bd7dc7bb186acb96560f" -dependencies = [ - "glob", - "pnet_base", - "pnet_macros", - "pnet_macros_support", -] - -[[package]] -name = "pnet_sys" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "pnet_transport" -version = "0.35.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f604d98bc2a6591cf719b58d3203fd882bdd6bf1db696c4ac97978e9f4776bf" -dependencies = [ - "libc", - "pnet_base", - "pnet_packet", - "pnet_sys", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "portable-atomic" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy 0.8.23", -] - -[[package]] -name = "prettyplease" -version = "0.2.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" -dependencies = [ - "proc-macro2", - "syn 2.0.100", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "proc-macro2" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" -dependencies = [ - "heck 0.5.0", - "itertools 0.14.0", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn 2.0.100", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "prost-reflect" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5edd582b62f5cde844716e66d92565d7faf7ab1445c8cebce6e00fba83ddb2" -dependencies = [ - "once_cell", - "prost", - "prost-reflect-derive", - "prost-types", -] - -[[package]] -name = "prost-reflect-build" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e2537231d94dd2778920c2ada37dd9eb1ac0325bb3ee3ee651bd44c1134123" -dependencies = [ - "prost-build", - "prost-reflect", -] - -[[package]] -name = "prost-reflect-derive" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fce6b22f15cc8d8d400a2b98ad29202b33bd56c7d9ddd815bc803a807ecb65" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost", -] - -[[package]] -name = "quick-xml" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" -dependencies = [ - "memchr", -] - -[[package]] -name = "quinn" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" -dependencies = [ - "bytes", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash", - "rustls", - "socket2", - "thiserror 2.0.12", - "tokio", - "tracing", -] - -[[package]] -name = "quinn-proto" -version = "0.11.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" -dependencies = [ - "bytes", - "getrandom 0.2.15", - "rand 0.8.5", - "ring", - "rustc-hash", - "rustls", - "rustls-pki-types", - "rustls-platform-verifier", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", - "zerocopy 0.8.23", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.1", -] - -[[package]] -name = "rcgen" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48406db8ac1f3cbc7dcdb56ec355343817958a356ff430259bb07baf7607e1e1" -dependencies = [ - "pem", - "ring", - "time", - "yasna", -] - -[[package]] -name = "redox_syscall" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom 0.2.15", - "libredox", - "thiserror 1.0.69", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - -[[package]] -name = "reqwest" -version = "0.12.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e327e510263980e231de548a33e63d34962d29ae61b467389a1a09627a254" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-tls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-registry", -] - -[[package]] -name = "resolv-conf" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48375394603e3dd4b2d64371f7148fd8c7baa2680e28741f2cb8d23b59e3d4c4" -dependencies = [ - "hostname", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "ringbuf" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726bb493fe9cac765e8f96a144c3a8396bdf766dedad22e504b70b908dcbceb4" -dependencies = [ - "crossbeam-utils", - "portable-atomic", -] - -[[package]] -name = "rstest" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97eeab2f3c0a199bc4be135c36c924b6590b88c377d416494288c14f2db30199" -dependencies = [ - "futures", - "futures-timer", - "rstest_macros", - "rustc_version", -] - -[[package]] -name = "rstest_macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d428f8247852f894ee1be110b375111b586d4fa431f6c46e64ba5a0dcccbe605" -dependencies = [ - "cfg-if", - "glob", - "proc-macro2", - "quote", - "regex", - "relative-path", - "rustc_version", - "syn 2.0.100", - "unicode-ident", -] - -[[package]] -name = "rust-i18n" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b3a6e1c6565b77c86d868eea3068b0eb39582510f9c78cfbd5c67bd36fda9b" -dependencies = [ - "globwalk", - "once_cell", - "regex", - "rust-i18n-macro", - "rust-i18n-support", - "smallvec", -] - -[[package]] -name = "rust-i18n-macro" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6180d8506af2b485ffc1eab7fc6d15678336a694f2b5efac5f2ca78c52928275" -dependencies = [ - "glob", - "once_cell", - "proc-macro2", - "quote", - "rust-i18n-support", - "serde", - "serde_json", - "serde_yml", - "syn 2.0.100", -] - -[[package]] -name = "rust-i18n-support" -version = "3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938f16094e2b09e893b1f85c9da251739a832d4272a5957217977da3a0713bb6" -dependencies = [ - "arc-swap", - "base62", - "globwalk", - "itertools 0.11.0", - "lazy_static", - "normpath", - "once_cell", - "proc-macro2", - "regex", - "serde", - "serde_json", - "serde_yml", - "siphasher", - "toml", - "triomphe", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.9.3", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.23.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" -dependencies = [ - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" -dependencies = [ - "web-time", -] - -[[package]] -name = "rustls-platform-verifier" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c7dc240fec5517e6c4eab3310438636cfe6391dfc345ba013109909a90d136" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scc" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea091f6cac2595aa38993f04f4ee692ed43757035c36e67c180b6828356385b1" -dependencies = [ - "sdd", -] - -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "sdd" -version = "3.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "584e070911c7017da6cb2eb0788d09f43d789029b5877d3e5ecc8acf86ceee21" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.0", - "core-foundation", - "core-foundation-sys", - "libc", - "num-bigint", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_yml" -version = "0.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" -dependencies = [ - "indexmap", - "itoa", - "libyml", - "memchr", - "ryu", - "serde", - "version_check", -] - -[[package]] -name = "serial_test" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" -dependencies = [ - "futures", - "log", - "once_cell", - "parking_lot", - "scc", - "serial_test_derive", -] - -[[package]] -name = "serial_test_derive" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "service-manager" -version = "0.8.0" -source = "git+https://github.com/chipsenkbeil/service-manager-rs.git?branch=main#0294d3b9769c8ef7db8b4e831fb1c4f14b7d473b" -dependencies = [ - "cfg-if", - "dirs", - "encoding-utils", - "encoding_rs", - "plist", - "which", - "xml-rs", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sha2" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" - -[[package]] -name = "smoltcp" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad095989c1533c1c266d9b1e8d70a1329dd3723c3edac6d03bbd67e7bf6f4bb" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "cfg-if", - "defmt", - "heapless", - "managed", -] - -[[package]] -name = "socket2" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "stun_codec" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feed9dafe0bda84f2b6ca3ce726b0a1f1ac2e8b63c6ecfb89b08b32313247b5b" -dependencies = [ - "bytecodec", - "byteorder", - "crc", - "hmac", - "md5", - "sha1", - "trackable 1.3.0", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "sys-locale" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" -dependencies = [ - "libc", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.9.0", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "tabled" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c9303ee60b9bedf722012ea29ae3711ba13a67c9b9ae28993838b63057cb1b" -dependencies = [ - "papergrid", - "tabled_derive", -] - -[[package]] -name = "tabled_derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf0fb8bfdc709786c154e24a66777493fb63ae97e3036d914c8666774c477069" -dependencies = [ - "heck 0.4.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "tachyonix" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86c3eafa053bbcc63bb4bfc5eb26362a33ea0bc2e589f28bce00287d1c167d45" -dependencies = [ - "async-event", - "crossbeam-utils", - "diatomic-waker", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "tempfile" -version = "3.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600" -dependencies = [ - "fastrand", - "getrandom 0.3.1", - "once_cell", - "rustix 1.0.2", - "windows-sys 0.59.0", -] - -[[package]] -name = "terminal_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" -dependencies = [ - "rustix 1.0.2", - "windows-sys 0.59.0", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "time" -version = "0.3.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" -dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" - -[[package]] -name = "time-macros" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "timedmap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825f6c8a18bc36d56a62f66af7296385b628c9c5543a8663d4c217fc920bfefd" - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.44.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "windows-sys 0.52.0", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-socks" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" -dependencies = [ - "either", - "futures-util", - "thiserror 1.0.69", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-websockets" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842e11addde61da7c37ef205cd625ebcd7b607076ea62e4698f06bfd5fd01a03" -dependencies = [ - "base64 0.22.1", - "bytes", - "fastrand", - "futures-core", - "futures-sink", - "http", - "httparse", - "ring", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tokio-util", - "webpki-roots", -] - -[[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tonic-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "prost-types", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-appender" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" -dependencies = [ - "crossbeam-channel", - "thiserror 1.0.69", - "time", - "tracing-subscriber", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "time", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "trackable" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98abb9e7300b9ac902cc04920945a874c1973e08c310627cc4458c04b70dd32" -dependencies = [ - "trackable 1.3.0", - "trackable_derive", -] - -[[package]] -name = "trackable" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15bd114abb99ef8cee977e517c8f37aee63f184f2d08e3e6ceca092373369ae" -dependencies = [ - "trackable_derive", -] - -[[package]] -name = "trackable_derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebeb235c5847e2f82cfe0f07eb971d1e5f6804b18dac2ae16349cc604380f82f" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "triomphe" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" -dependencies = [ - "arc-swap", - "serde", - "stable_deref_trait", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tun-easytier" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10dff0358b37ef593a74c9d2264a1df126e169d194878732a4f99ff7b01678bd" -dependencies = [ - "bytes", - "cfg-if", - "futures-core", - "ipnet", - "libc", - "libloading", - "log", - "nix 0.29.0", - "thiserror 1.0.69", - "tokio", - "tokio-util", - "windows-sys 0.59.0", - "wintun", -] - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" -dependencies = [ - "getrandom 0.3.1", - "rand 0.9.0", - "serde", - "uuid-macro-internal", -] - -[[package]] -name = "uuid-macro-internal" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dcd78c4f979627a754f5522cea6e6a25e55139056535fe6e69c506cd64a862" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "waker-fn" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" - -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.13.3+wasi-0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-root-certs" -version = "0.26.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09aed61f5e8d2c18344b3faa33a4c837855fe56642757754775548fee21386c4" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "0.26.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - -[[package]] -name = "widestring" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" - -[[package]] -name = "wildmatch" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-link" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" - -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result", - "windows-strings", - "windows-targets 0.53.0", -] - -[[package]] -name = "windows-result" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06374efe858fab7e4f881500e6e86ec8bc28f9462c47e5a9941a0142ad86b189" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-service" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24d6bcc7f734a4091ecf8d7a64c5f7d7066f45585c1861eba06449909609c8a" -dependencies = [ - "bitflags 2.9.0", - "widestring", - "windows-sys 0.52.0", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winnow" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "wintun" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da99be64b5aa3de869c16977994314d0759a698d9a73ab0a5b1d52e2282033ae" -dependencies = [ - "c2rust-bitfields", - "libloading", - "log", - "thiserror 1.0.69", - "windows-sys 0.52.0", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core 0.6.4", - "serde", - "zeroize", -] - -[[package]] -name = "xml-rs" -version = "0.8.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" - -[[package]] -name = "yasna" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" -dependencies = [ - "time", -] - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "byteorder", - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" -dependencies = [ - "zerocopy-derive 0.8.23", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe 7.2.3", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "7.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3051792fbdc2e1e143244dc28c60f73d8470e93f3f9cbd0ead44da5ed802722" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.14+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb060d4926e4ac3a3ad15d864e99ceb5f343c6b34f5bd6d81ae6ed417311be5" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/rust/easytier/Cargo.toml b/rust/easytier/Cargo.toml index 78ba3ab..cff0a5f 100644 --- a/rust/easytier/Cargo.toml +++ b/rust/easytier/Cargo.toml @@ -3,7 +3,7 @@ name = "easytier" description = "A full meshed p2p VPN, connecting all your devices in one network with one command." homepage = "https://github.com/EasyTier/EasyTier" repository = "https://github.com/EasyTier/EasyTier" -version = "2.2.2" +version = "2.2.3" edition = "2021" authors = ["kkrainbow"] keywords = ["vpn", "p2p", "network", "easytier"] @@ -192,6 +192,8 @@ http_req = { git = "https://github.com/EasyTier/http_req.git", default-features # for dns connector hickory-resolver = "0.24.4" +bounded_join_set = "0.3.0" + [target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd"))'.dependencies] machine-uid = "0.5.3" diff --git a/rust/easytier/src/common/config.rs b/rust/easytier/src/common/config.rs index fb89a59..d6a727a 100644 --- a/rust/easytier/src/common/config.rs +++ b/rust/easytier/src/common/config.rs @@ -27,7 +27,6 @@ pub fn gen_default_flags() -> Flags { disable_p2p: false, relay_all_peer_rpc: false, disable_udp_hole_punching: false, - ipv6_listener: "udp://[::]:0".to_string(), multi_thread: true, data_compress_algo: CompressionAlgoPb::None.into(), bind_device: true, diff --git a/rust/easytier/src/common/constants.rs b/rust/easytier/src/common/constants.rs index f8b7f78..7272def 100644 --- a/rust/easytier/src/common/constants.rs +++ b/rust/easytier/src/common/constants.rs @@ -29,7 +29,7 @@ pub const WIN_SERVICE_WORK_DIR_REG_KEY: &str = "SOFTWARE\\EasyTier\\Service\\Wor pub const EASYTIER_VERSION: &str = git_version::git_version!( args = ["--abbrev=8", "--always", "--dirty=~"], - prefix = concat!(env!("CARGO_PKG_VERSION"), "-@astral "), + prefix = concat!(env!("CARGO_PKG_VERSION"), "-"), suffix = "", - fallback = env!("CARGO_PKG_VERSION") + fallback = "astral" ); diff --git a/rust/easytier/src/common/stun.rs b/rust/easytier/src/common/stun.rs index 301efcd..8ec6544 100644 --- a/rust/easytier/src/common/stun.rs +++ b/rust/easytier/src/common/stun.rs @@ -1,5 +1,5 @@ use std::collections::BTreeSet; -use std::net::{IpAddr, SocketAddr}; +use std::net::{IpAddr, Ipv6Addr, SocketAddr}; use std::sync::atomic::AtomicBool; use std::sync::{Arc, RwLock}; use std::time::{Duration, Instant}; @@ -8,6 +8,8 @@ use crate::proto::common::{NatType, StunInfo}; use anyhow::Context; use chrono::Local; use crossbeam::atomic::AtomicCell; +use hickory_resolver::config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts}; +use hickory_resolver::TokioAsyncResolver; use rand::seq::IteratorRandom; use tokio::net::{lookup_host, UdpSocket}; use tokio::sync::{broadcast, Mutex}; @@ -22,21 +24,68 @@ use crate::common::error::Error; use super::stun_codec_ext::*; +pub fn get_default_resolver_config() -> ResolverConfig { + let mut default_resolve_config = ResolverConfig::new(); + default_resolve_config.add_name_server(NameServerConfig::new( + "223.5.5.5:53".parse().unwrap(), + Protocol::Udp, + )); + default_resolve_config.add_name_server(NameServerConfig::new( + "180.184.1.1:53".parse().unwrap(), + Protocol::Udp, + )); + default_resolve_config +} + +pub async fn resolve_txt_record( + domain_name: &str, + resolver: &TokioAsyncResolver, +) -> Result { + let response = resolver.txt_lookup(domain_name).await.with_context(|| { + format!( + "txt_lookup failed, domain_name: {}", + domain_name.to_string() + ) + })?; + + let txt_record = response.iter().next().with_context(|| { + format!( + "no txt record found, domain_name: {}", + domain_name.to_string() + ) + })?; + + let txt_data = String::from_utf8_lossy(&txt_record.txt_data()[0]); + tracing::info!(?txt_data, ?domain_name, "get txt record"); + + Ok(txt_data.to_string()) +} + struct HostResolverIter { hostnames: Vec, ips: Vec, max_ip_per_domain: u32, + use_ipv6: bool, } impl HostResolverIter { - fn new(hostnames: Vec, max_ip_per_domain: u32) -> Self { + fn new(hostnames: Vec, max_ip_per_domain: u32, use_ipv6: bool) -> Self { Self { hostnames, ips: vec![], max_ip_per_domain, + use_ipv6, } } + async fn get_txt_record(domain_name: &str) -> Result, Error> { + let resolver = TokioAsyncResolver::tokio_from_system_conf().unwrap_or( + TokioAsyncResolver::tokio(get_default_resolver_config(), ResolverOpts::default()), + ); + let txt_data = resolve_txt_record(domain_name, &resolver).await?; + Ok(txt_data.split(" ").map(|x| x.to_string()).collect()) + } + #[async_recursion::async_recursion] async fn next(&mut self) -> Option { if self.ips.is_empty() { @@ -51,10 +100,35 @@ impl HostResolverIter { format!("{}:3478", host) }; + if host.starts_with("txt:") { + let domain_name = host.trim_start_matches("txt:"); + match Self::get_txt_record(domain_name).await { + Ok(hosts) => { + tracing::info!( + ?domain_name, + ?hosts, + "get txt record success when resolve stun server" + ); + // insert hosts to the head of hostnames + self.hostnames.splice(0..0, hosts.into_iter()); + } + Err(e) => { + tracing::warn!( + ?domain_name, + ?e, + "get txt record failed when resolve stun server" + ); + } + } + return self.next().await; + } + + let use_ipv6 = self.use_ipv6; + match lookup_host(&host).await { Ok(ips) => { self.ips = ips - .filter(|x| x.is_ipv4()) + .filter(|x| if use_ipv6 { x.is_ipv6() } else { x.is_ipv4() }) .choose_multiple(&mut rand::thread_rng(), self.max_ip_per_domain as usize); if self.ips.is_empty() { @@ -400,7 +474,7 @@ impl UdpNatTypeDetectResult { // find resp with distinct stun server self.stun_resps .iter() - .map(|x| x.stun_server_addr) + .map(|x| x.recv_from_addr) .collect::>() .len() } @@ -555,8 +629,11 @@ impl UdpNatTypeDetector { udp: Arc, ) -> Result { let mut stun_servers = vec![]; - let mut host_resolver = - HostResolverIter::new(self.stun_server_hosts.clone(), self.max_ip_per_domain); + let mut host_resolver = HostResolverIter::new( + self.stun_server_hosts.clone(), + self.max_ip_per_domain, + false, + ); while let Some(addr) = host_resolver.next().await { stun_servers.push(addr); } @@ -602,7 +679,9 @@ pub trait StunInfoCollectorTrait: Send + Sync { pub struct StunInfoCollector { stun_servers: Arc>>, + stun_servers_v6: Arc>>, udp_nat_test_result: Arc>>, + public_ipv6: Arc>>, nat_test_result_time: Arc>>, redetect_notify: Arc, tasks: std::sync::Mutex>, @@ -621,7 +700,12 @@ impl StunInfoCollectorTrait for StunInfoCollector { udp_nat_type: result.nat_type() as i32, tcp_nat_type: 0, last_update_time: self.nat_test_result_time.load().timestamp(), - public_ip: result.public_ips().iter().map(|x| x.to_string()).collect(), + public_ip: result + .public_ips() + .iter() + .map(|x| x.to_string()) + .chain(self.public_ipv6.load().map(|x| x.to_string())) + .collect(), min_port: result.min_port() as u32, max_port: result.max_port() as u32, } @@ -640,7 +724,7 @@ impl StunInfoCollectorTrait for StunInfoCollector { if stun_servers.is_empty() { let mut host_resolver = - HostResolverIter::new(self.stun_servers.read().unwrap().clone(), 2); + HostResolverIter::new(self.stun_servers.read().unwrap().clone(), 2, false); while let Some(addr) = host_resolver.next().await { stun_servers.push(addr); if stun_servers.len() >= 2 { @@ -680,7 +764,9 @@ impl StunInfoCollector { pub fn new(stun_servers: Vec) -> Self { Self { stun_servers: Arc::new(RwLock::new(stun_servers)), + stun_servers_v6: Arc::new(RwLock::new(Self::get_default_servers_v6())), udp_nat_test_result: Arc::new(RwLock::new(None)), + public_ipv6: Arc::new(AtomicCell::new(None)), nat_test_result_time: Arc::new(AtomicCell::new(Local::now())), redetect_notify: Arc::new(tokio::sync::Notify::new()), tasks: std::sync::Mutex::new(JoinSet::new()), @@ -696,28 +782,42 @@ impl StunInfoCollector { // NOTICE: we may need to choose stun stun server based on geo location // stun server cross nation may return a external ip address with high latency and loss rate vec![ + "txt:stun.easytier.cn", "stun.miwifi.com", "stun.chat.bilibili.com", "stun.hitv.com", - "stun.cdnbye.com", - "stun.douyucdn.cn:18000", - "fwa.lifesizecloud.com", - "global.turn.twilio.com", - "turn.cloudflare.com", - "stun.isp.net.au", - "stun.nextcloud.com", - "stun.freeswitch.org", - "stun.voip.blackberry.com", - "stunserver.stunprotocol.org", - "stun.sipnet.com", - "stun.radiojar.com", - "stun.sonetel.com", ] .iter() .map(|x| x.to_string()) .collect() } + pub fn get_default_servers_v6() -> Vec { + vec!["txt:stun-v6.easytier.cn"] + .iter() + .map(|x| x.to_string()) + .collect() + } + + async fn get_public_ipv6(servers: &Vec) -> Option { + let mut ips = HostResolverIter::new(servers.to_vec(), 10, true); + while let Some(ip) = ips.next().await { + let udp = Arc::new(UdpSocket::bind(format!("[::]:0")).await.unwrap()); + let ret = StunClientBuilder::new(udp.clone()) + .new_stun_client(ip) + .bind_request(false, false) + .await; + tracing::debug!(?ret, "finish ipv6 udp nat type detect"); + match ret.map(|x| x.mapped_socket_addr.map(|x| x.ip())) { + Ok(Some(IpAddr::V6(v6))) => { + return Some(v6); + } + _ => {} + } + } + None + } + fn start_stun_routine(&self) { if self.started.load(std::sync::atomic::Ordering::Relaxed) { return; @@ -784,6 +884,30 @@ impl StunInfoCollector { } } }); + + // for ipv6 + let stun_servers = self.stun_servers_v6.clone(); + let stored_ipv6 = self.public_ipv6.clone(); + let redetect_notify = self.redetect_notify.clone(); + self.tasks.lock().unwrap().spawn(async move { + loop { + let servers = stun_servers.read().unwrap().clone(); + Self::get_public_ipv6(&servers) + .await + .map(|x| stored_ipv6.store(Some(x))); + + let sleep_sec = if stored_ipv6.load().is_none() { + 60 + } else { + 360 + }; + + tokio::select! { + _ = redetect_notify.notified() => {} + _ = tokio::time::sleep(Duration::from_secs(sleep_sec)) => {} + } + } + }); } pub fn update_stun_info(&self) { @@ -862,6 +986,48 @@ mod tests { let detector = UdpNatTypeDetector::new(stun_servers, 1); let ret = detector.detect_nat_type(0).await; println!("{:#?}, {:?}", ret, ret.as_ref().unwrap().nat_type()); - assert_eq!(ret.unwrap().nat_type(), NatType::PortRestricted); + assert_eq!(ret.unwrap().nat_type(), NatType::Restricted); + } + + #[tokio::test] + async fn test_txt_public_stun_server() { + let stun_servers = vec!["txt:stun.easytier.cn".to_string()]; + let detector = UdpNatTypeDetector::new(stun_servers, 1); + let ret = detector.detect_nat_type(0).await; + println!("{:#?}, {:?}", ret, ret.as_ref().unwrap().nat_type()); + assert!(!ret.unwrap().stun_resps.is_empty()); + } + + #[tokio::test] + async fn test_v4_stun() { + let mut udp_server = UdpTunnelListener::new("udp://0.0.0.0:55355".parse().unwrap()); + let mut tasks = JoinSet::new(); + tasks.spawn(async move { + udp_server.listen().await.unwrap(); + loop { + udp_server.accept().await.unwrap(); + } + }); + let stun_servers = vec!["127.0.0.1:55355".to_string()]; + + let detector = UdpNatTypeDetector::new(stun_servers, 1); + let ret = detector.detect_nat_type(0).await; + println!("{:#?}, {:?}", ret, ret.as_ref().unwrap().nat_type()); + assert_eq!(ret.unwrap().nat_type(), NatType::Restricted); + } + + #[tokio::test] + async fn test_v6_stun() { + let mut udp_server = UdpTunnelListener::new("udp://[::]:55355".parse().unwrap()); + let mut tasks = JoinSet::new(); + tasks.spawn(async move { + udp_server.listen().await.unwrap(); + loop { + udp_server.accept().await.unwrap(); + } + }); + let stun_servers = vec!["::1:55355".to_string()]; + let ret = StunInfoCollector::get_public_ipv6(&stun_servers).await; + println!("{:#?}", ret); } } diff --git a/rust/easytier/src/connector/direct.rs b/rust/easytier/src/connector/direct.rs index 7dff78c..53db83f 100644 --- a/rust/easytier/src/connector/direct.rs +++ b/rust/easytier/src/connector/direct.rs @@ -1,7 +1,9 @@ // try connect peers directly, with either its public ip or lan ip use std::{ - net::SocketAddr, + collections::HashSet, + net::{Ipv6Addr, SocketAddr}, + str::FromStr, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -79,7 +81,6 @@ struct DstListenerUrlBlackListItem(PeerId, url::Url); struct DirectConnectorManagerData { global_ctx: ArcGlobalCtx, peer_manager: Arc, - dst_blacklist: timedmap::TimedMap, dst_listener_blacklist: timedmap::TimedMap, } @@ -88,7 +89,6 @@ impl DirectConnectorManagerData { Self { global_ctx, peer_manager, - dst_blacklist: timedmap::TimedMap::new(), dst_listener_blacklist: timedmap::TimedMap::new(), } } @@ -150,7 +150,9 @@ impl DirectConnectorManager { let peers = data.peer_manager.list_peers().await; let mut tasks = JoinSet::new(); for peer_id in peers { - if peer_id == my_peer_id { + if peer_id == my_peer_id + || data.peer_manager.has_directly_connected_conn(peer_id) + { continue; } tasks.spawn(Self::do_try_direct_connect(data.clone(), peer_id)); @@ -173,24 +175,13 @@ impl DirectConnectorManager { dst_peer_id: PeerId, addr: String, ) -> Result<(), Error> { - data.dst_blacklist.cleanup(); - if data - .dst_blacklist - .contains(&DstBlackListItem(dst_peer_id.clone(), addr.clone())) - { - tracing::debug!("try_connect_to_ip failed, addr in blacklist: {}", addr); - return Err(Error::UrlInBlacklist); - } - let connector = create_connector_by_url(&addr, &data.global_ctx).await?; let (peer_id, conn_id) = timeout( - std::time::Duration::from_secs(5), - data.peer_manager.try_connect(connector), + std::time::Duration::from_secs(3), + data.peer_manager.try_direct_connect(connector), ) .await??; - // let (peer_id, conn_id) = data.peer_manager.try_connect(connector).await?; - if peer_id != dst_peer_id && !TESTING.load(Ordering::Relaxed) { tracing::info!( "connect to ip succ: {}, but peer id mismatch, expect: {}, actual: {}", @@ -204,6 +195,7 @@ impl DirectConnectorManager { .await?; return Err(Error::InvalidUrl(addr)); } + Ok(()) } @@ -214,7 +206,7 @@ impl DirectConnectorManager { addr: String, ) -> Result<(), Error> { let mut rand_gen = rand::rngs::OsRng::default(); - let backoff_ms = vec![1000, 2000, 4000]; + let backoff_ms = vec![1000, 2000]; let mut backoff_idx = 0; loop { @@ -237,12 +229,6 @@ impl DirectConnectorManager { backoff_idx += 1; continue; } else { - data.dst_blacklist.insert( - DstBlackListItem(dst_peer_id.clone(), addr.clone()), - (), - std::time::Duration::from_secs(DIRECT_CONNECTOR_BLACKLIST_TIMEOUT_SEC), - ); - return ret; } } @@ -273,61 +259,43 @@ impl DirectConnectorManager { tracing::debug!(?available_listeners, "got available listeners"); - let mut listener = available_listeners.get(0).ok_or(anyhow::anyhow!( - "peer {} have no valid listener", - dst_peer_id - ))?; + if available_listeners.is_empty() { + return Err(anyhow::anyhow!("peer {} have no valid listener", dst_peer_id).into()); + } // if have default listener, use it first - listener = available_listeners + let listener = available_listeners .iter() .find(|l| l.scheme() == data.global_ctx.get_flags().default_protocol) - .unwrap_or(listener); + .unwrap_or(available_listeners.get(0).unwrap()); - let mut tasks = JoinSet::new(); + let mut tasks = bounded_join_set::JoinSet::new(2); let listener_host = listener.socket_addrs(|| None).unwrap().pop(); match listener_host { Some(SocketAddr::V4(s_addr)) => { if s_addr.ip().is_unspecified() { - ip_list.interface_ipv4s.iter().for_each(|ip| { - let mut addr = (*listener).clone(); - if addr.set_host(Some(ip.to_string().as_str())).is_ok() { - tasks.spawn(Self::try_connect_to_ip( - data.clone(), - dst_peer_id.clone(), - addr.to_string(), - )); - } else { - tracing::error!( - ?ip, - ?listener, - ?dst_peer_id, - "failed to set host for interface ipv4" - ); - } - }); - - if let Some(public_ipv4) = ip_list.public_ipv4 { - let mut addr = (*listener).clone(); - if addr - .set_host(Some(public_ipv4.to_string().as_str())) - .is_ok() - { - tasks.spawn(Self::try_connect_to_ip( - data.clone(), - dst_peer_id.clone(), - addr.to_string(), - )); - } else { - tracing::error!( - ?public_ipv4, - ?listener, - ?dst_peer_id, - "failed to set host for public ipv4" - ); - } - } + ip_list + .interface_ipv4s + .iter() + .chain(ip_list.public_ipv4.iter()) + .for_each(|ip| { + let mut addr = (*listener).clone(); + if addr.set_host(Some(ip.to_string().as_str())).is_ok() { + tasks.spawn(Self::try_connect_to_ip( + data.clone(), + dst_peer_id.clone(), + addr.to_string(), + )); + } else { + tracing::error!( + ?ip, + ?listener, + ?dst_peer_id, + "failed to set host for interface ipv4" + ); + } + }); } else if !s_addr.ip().is_loopback() || TESTING.load(Ordering::Relaxed) { tasks.spawn(Self::try_connect_to_ip( data.clone(), @@ -338,47 +306,42 @@ impl DirectConnectorManager { } Some(SocketAddr::V6(s_addr)) => { if s_addr.ip().is_unspecified() { - ip_list.interface_ipv6s.iter().for_each(|ip| { - let mut addr = (*listener).clone(); - if addr - .set_host(Some(format!("[{}]", ip.to_string()).as_str())) - .is_ok() - { - tasks.spawn(Self::try_connect_to_ip( - data.clone(), - dst_peer_id.clone(), - addr.to_string(), - )); - } else { - tracing::error!( - ?ip, - ?listener, - ?dst_peer_id, - "failed to set host for interface ipv6" - ); - } - }); - - if let Some(public_ipv6) = ip_list.public_ipv6 { - let mut addr = (*listener).clone(); - if addr - .set_host(Some(format!("[{}]", public_ipv6.to_string()).as_str())) - .is_ok() - { - tasks.spawn(Self::try_connect_to_ip( - data.clone(), - dst_peer_id.clone(), - addr.to_string(), - )); - } else { - tracing::error!( - ?public_ipv6, - ?listener, - ?dst_peer_id, - "failed to set host for public ipv6" - ); - } - } + // for ipv6, only try public ip + ip_list + .interface_ipv6s + .iter() + .chain(ip_list.public_ipv6.iter()) + .filter_map(|x| Ipv6Addr::from_str(&x.to_string()).ok()) + .filter(|x| { + TESTING.load(Ordering::Relaxed) + || (!x.is_loopback() + && !x.is_unspecified() + && !x.is_unique_local() + && !x.is_unicast_link_local() + && !x.is_multicast()) + }) + .collect::>() + .iter() + .for_each(|ip| { + let mut addr = (*listener).clone(); + if addr + .set_host(Some(format!("[{}]", ip.to_string()).as_str())) + .is_ok() + { + tasks.spawn(Self::try_connect_to_ip( + data.clone(), + dst_peer_id.clone(), + addr.to_string(), + )); + } else { + tracing::error!( + ?ip, + ?listener, + ?dst_peer_id, + "failed to set host for public ipv6" + ); + } + }); } else if !s_addr.ip().is_loopback() || TESTING.load(Ordering::Relaxed) { tasks.spawn(Self::try_connect_to_ip( data.clone(), @@ -430,14 +393,6 @@ impl DirectConnectorManager { dst_peer_id: PeerId, ) -> Result<(), Error> { let peer_manager = data.peer_manager.clone(); - // check if we have direct connection with dst_peer_id - if let Some(c) = peer_manager.list_peer_conns(dst_peer_id).await { - // currently if we have any type of direct connection (udp or tcp), we will not try to connect - if !c.is_empty() { - return Ok(()); - } - } - tracing::debug!("try direct connect to peer: {}", dst_peer_id); let rpc_stub = peer_manager @@ -466,8 +421,7 @@ mod tests { use crate::{ connector::direct::{ - DirectConnectorManager, DirectConnectorManagerData, DstBlackListItem, - DstListenerUrlBlackListItem, + DirectConnectorManager, DirectConnectorManagerData, DstListenerUrlBlackListItem, }, instance::listeners::ListenerManager, peers::tests::{ @@ -526,9 +480,7 @@ mod tests { #[values("tcp", "udp", "wg")] proto: &str, #[values("true", "false")] ipv6: bool, ) { - if ipv6 && proto != "udp" { - return; - } + TESTING.store(true, std::sync::atomic::Ordering::Relaxed); let p_a = create_mock_peer_manager().await; let p_b = create_mock_peer_manager().await; @@ -544,14 +496,18 @@ mod tests { dm_a.run_as_client(); dm_c.run_as_server(); + let port = if proto == "wg" { 11040 } else { 11041 }; if !ipv6 { - let port = if proto == "wg" { 11040 } else { 11041 }; p_c.get_global_ctx().config.set_listeners(vec![format!( "{}://0.0.0.0:{}", proto, port ) .parse() .unwrap()]); + } else { + p_c.get_global_ctx() + .config + .set_listeners(vec![format!("{}://[::]:{}", proto, port).parse().unwrap()]); } let mut f = p_c.get_global_ctx().config.get_flags(); f.enable_ipv6 = ipv6; @@ -592,9 +548,5 @@ mod tests { 1, "tcp://127.0.0.1:10222".parse().unwrap() ))); - - assert!(data - .dst_blacklist - .contains(&DstBlackListItem(1, ip_list.listeners[0].to_string()))); } } diff --git a/rust/easytier/src/connector/dns_connector.rs b/rust/easytier/src/connector/dns_connector.rs index 6d37e60..c2ac24b 100644 --- a/rust/easytier/src/connector/dns_connector.rs +++ b/rust/easytier/src/connector/dns_connector.rs @@ -1,13 +1,17 @@ use std::{net::SocketAddr, sync::Arc}; use crate::{ - common::{error::Error, global_ctx::ArcGlobalCtx}, - tunnel::{Tunnel, TunnelConnector, TunnelError, PROTO_PORT_OFFSET}, + common::{ + error::Error, + global_ctx::ArcGlobalCtx, + stun::{get_default_resolver_config, resolve_txt_record}, + }, + tunnel::{IpVersion, Tunnel, TunnelConnector, TunnelError, PROTO_PORT_OFFSET}, }; use anyhow::Context; use dashmap::DashSet; use hickory_resolver::{ - config::{NameServerConfig, Protocol, ResolverConfig, ResolverOpts}, + config::{ResolverConfig, ResolverOpts}, proto::rr::rdata::SRV, TokioAsyncResolver, }; @@ -38,6 +42,7 @@ pub struct DNSTunnelConnector { addr: url::Url, bind_addrs: Vec, global_ctx: ArcGlobalCtx, + ip_version: IpVersion, default_resolve_config: ResolverConfig, default_resolve_opts: ResolverOpts, @@ -45,21 +50,13 @@ pub struct DNSTunnelConnector { impl DNSTunnelConnector { pub fn new(addr: url::Url, global_ctx: ArcGlobalCtx) -> Self { - let mut default_resolve_config = ResolverConfig::new(); - default_resolve_config.add_name_server(NameServerConfig::new( - "223.5.5.5:53".parse().unwrap(), - Protocol::Udp, - )); - default_resolve_config.add_name_server(NameServerConfig::new( - "180.184.1.1:53".parse().unwrap(), - Protocol::Udp, - )); Self { addr, bind_addrs: Vec::new(), global_ctx, + ip_version: IpVersion::Both, - default_resolve_config, + default_resolve_config: get_default_resolver_config(), default_resolve_opts: ResolverOpts::default(), } } @@ -69,26 +66,14 @@ impl DNSTunnelConnector { &self, domain_name: &str, ) -> Result, Error> { - let resolver = TokioAsyncResolver::tokio_from_system_conf().unwrap_or( - TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default()), - ); - - let response = resolver.txt_lookup(domain_name).await.with_context(|| { - format!( - "txt_lookup failed, domain_name: {}", - domain_name.to_string() - ) - })?; - - let txt_record = response.iter().next().with_context(|| { - format!( - "no txt record found, domain_name: {}", - domain_name.to_string() - ) - })?; - - let txt_data = String::from_utf8_lossy(&txt_record.txt_data()[0]); - tracing::info!(?txt_data, ?domain_name, "get txt record"); + let resolver = + TokioAsyncResolver::tokio_from_system_conf().unwrap_or(TokioAsyncResolver::tokio( + self.default_resolve_config.clone(), + self.default_resolve_opts.clone(), + )); + let txt_data = resolve_txt_record(domain_name, &resolver) + .await + .with_context(|| format!("resolve txt record failed, domain_name: {}", domain_name))?; let candidate_urls = txt_data .split(" ") @@ -106,9 +91,9 @@ impl DNSTunnelConnector { ) })?; - let connector = create_connector_by_url(url.as_str(), &self.global_ctx).await; - - connector + let mut connector = create_connector_by_url(url.as_str(), &self.global_ctx).await?; + connector.set_ip_version(self.ip_version); + Ok(connector) } fn handle_one_srv_record(record: &SRV, protocol: &str) -> Result<(url::Url, u64), Error> { @@ -141,9 +126,11 @@ impl DNSTunnelConnector { ) -> Result, Error> { tracing::info!("handle_srv_record: {}", domain_name); - let resolver = TokioAsyncResolver::tokio_from_system_conf().unwrap_or( - TokioAsyncResolver::tokio(ResolverConfig::default(), ResolverOpts::default()), - ); + let resolver = + TokioAsyncResolver::tokio_from_system_conf().unwrap_or(TokioAsyncResolver::tokio( + self.default_resolve_config.clone(), + self.default_resolve_opts.clone(), + )); let srv_domains = PROTO_PORT_OFFSET .iter() @@ -192,8 +179,9 @@ impl DNSTunnelConnector { ) })?; - let connector = create_connector_by_url(url.as_str(), &self.global_ctx).await; - connector + let mut connector = create_connector_by_url(url.as_str(), &self.global_ctx).await?; + connector.set_ip_version(self.ip_version); + Ok(connector) } } @@ -238,6 +226,10 @@ impl super::TunnelConnector for DNSTunnelConnector { fn set_bind_addrs(&mut self, addrs: Vec) { self.bind_addrs = addrs; } + + fn set_ip_version(&mut self, ip_version: IpVersion) { + self.ip_version = ip_version; + } } #[cfg(test)] diff --git a/rust/easytier/src/connector/manual.rs b/rust/easytier/src/connector/manual.rs index 4181cfa..ab24149 100644 --- a/rust/easytier/src/connector/manual.rs +++ b/rust/easytier/src/connector/manual.rs @@ -293,7 +293,6 @@ impl ManualConnectorManager { ip_version: IpVersion, ) -> Result { let ip_collector = data.global_ctx.get_ip_collector(); - let net_ns = data.net_ns.clone(); connector.lock().await.set_ip_version(ip_version); @@ -309,18 +308,11 @@ impl ManualConnectorManager { data.global_ctx.issue_event(GlobalCtxEvent::Connecting( connector.lock().await.remote_url().clone(), )); - - let _g = net_ns.guard(); tracing::info!("reconnect try connect... conn: {:?}", connector); - let tunnel = connector.lock().await.connect().await?; - tracing::info!("reconnect get tunnel succ: {:?}", tunnel); - assert_eq!( - dead_url, - tunnel.info().unwrap().remote_addr.unwrap().to_string(), - "info: {:?}", - tunnel.info() - ); - let (peer_id, conn_id) = data.peer_manager.add_client_tunnel(tunnel).await?; + let (peer_id, conn_id) = data + .peer_manager + .try_direct_connect(connector.lock().await.as_mut()) + .await?; tracing::info!("reconnect succ: {} {} {}", peer_id, conn_id, dead_url); Ok(ReconnResult { dead_url, diff --git a/rust/easytier/src/connector/udp_hole_punch/common.rs b/rust/easytier/src/connector/udp_hole_punch/common.rs index 11cbd06..ec45b4f 100644 --- a/rust/easytier/src/connector/udp_hole_punch/common.rs +++ b/rust/easytier/src/connector/udp_hole_punch/common.rs @@ -388,7 +388,7 @@ impl UdpHolePunchListener { tracing::warn!(?conn, "udp hole punching listener got peer connection"); let peer_mgr = peer_mgr.clone(); tokio::spawn(async move { - if let Err(e) = peer_mgr.add_tunnel_as_server(conn).await { + if let Err(e) = peer_mgr.add_tunnel_as_server(conn, false).await { tracing::error!( ?e, "failed to add tunnel as server in hole punch listener" diff --git a/rust/easytier/src/easytier-cli.rs b/rust/easytier/src/easytier-cli.rs index 0b16a89..f908585 100644 --- a/rust/easytier/src/easytier-cli.rs +++ b/rust/easytier/src/easytier-cli.rs @@ -1,8 +1,14 @@ use std::{ - ffi::OsString, fmt::Write, net::SocketAddr, path::PathBuf, sync::Mutex, time::Duration, vec, + ffi::OsString, + fmt::Write, + net::{IpAddr, SocketAddr}, + path::PathBuf, + sync::Mutex, + time::Duration, + vec, }; -use anyhow::{Context, Ok}; +use anyhow::Context; use clap::{command, Args, Parser, Subcommand}; use humansize::format_size; use service_manager::*; @@ -311,7 +317,11 @@ impl CommandHandler { ipv4: route.ipv4_addr.map(|ip| ip.to_string()).unwrap_or_default(), hostname: route.hostname.clone(), cost: cost_to_str(route.cost), - lat_ms: float_to_str(p.get_latency_ms().unwrap_or(0.0), 3), + lat_ms: if route.cost == 1 { + float_to_str(p.get_latency_ms().unwrap_or(0.0), 3) + } else { + route.path_latency_latency_first().to_string() + }, loss_rate: float_to_str(p.get_loss_rate().unwrap_or(0.0), 3), rx_bytes: format_size(p.get_rx_bytes().unwrap_or(0), humansize::DECIMAL), tx_bytes: format_size(p.get_tx_bytes().unwrap_or(0), humansize::DECIMAL), @@ -1036,6 +1046,7 @@ async fn main() -> Result<(), Error> { match sub_cmd.sub_command { Some(NodeSubCommand::Info) | None => { let stun_info = node_info.stun_info.clone().unwrap_or_default(); + let ip_list = node_info.ip_list.clone().unwrap_or_default(); let mut builder = tabled::builder::Builder::default(); builder.push_record(vec!["Virtual IP", node_info.ipv4_addr.as_str()]); @@ -1045,11 +1056,32 @@ async fn main() -> Result<(), Error> { node_info.proxy_cidrs.join(", ").as_str(), ]); builder.push_record(vec!["Peer ID", node_info.peer_id.to_string().as_str()]); - builder.push_record(vec!["Public IP", stun_info.public_ip.join(", ").as_str()]); + stun_info.public_ip.iter().for_each(|ip| { + let Ok(ip) = ip.parse::() else { + return; + }; + if ip.is_ipv4() { + builder.push_record(vec!["Public IPv4", ip.to_string().as_str()]); + } else { + builder.push_record(vec!["Public IPv6", ip.to_string().as_str()]); + } + }); builder.push_record(vec![ "UDP Stun Type", format!("{:?}", stun_info.udp_nat_type()).as_str(), ]); + ip_list.interface_ipv4s.iter().for_each(|ip| { + builder.push_record(vec![ + "Interface IPv4", + format!("{}", ip.to_string()).as_str(), + ]); + }); + ip_list.interface_ipv6s.iter().for_each(|ip| { + builder.push_record(vec![ + "Interface IPv6", + format!("{}", ip.to_string()).as_str(), + ]); + }); for (idx, l) in node_info.listeners.iter().enumerate() { if l.starts_with("ring") { continue; diff --git a/rust/easytier/src/easytier-core.rs b/rust/easytier/src/easytier-core.rs index 249000b..a1bdc0b 100644 --- a/rust/easytier/src/easytier-core.rs +++ b/rust/easytier/src/easytier-core.rs @@ -308,12 +308,6 @@ struct Cli { )] socks5: Option, - #[arg( - long, - help = t!("core_clap.ipv6_listener").to_string() - )] - ipv6_listener: Option, - #[arg( long, help = t!("core_clap.compression").to_string(), @@ -576,11 +570,6 @@ impl TryFrom<&Cli> for TomlConfigLoader { f.disable_p2p = cli.disable_p2p; f.disable_udp_hole_punching = cli.disable_udp_hole_punching; f.relay_all_peer_rpc = cli.relay_all_peer_rpc; - if let Some(ipv6_listener) = cli.ipv6_listener.as_ref() { - f.ipv6_listener = ipv6_listener - .parse() - .with_context(|| format!("failed to parse ipv6 listener: {}", ipv6_listener))? - } f.multi_thread = cli.multi_thread; f.data_compress_algo = match cli.compression.as_str() { "none" => CompressionAlgoPb::None, diff --git a/rust/easytier/src/instance/listeners.rs b/rust/easytier/src/instance/listeners.rs index 91aceb2..65350f9 100644 --- a/rust/easytier/src/instance/listeners.rs +++ b/rust/easytier/src/instance/listeners.rs @@ -1,5 +1,6 @@ use std::{fmt::Debug, sync::Arc}; +use anyhow::Context; use async_trait::async_trait; use tokio::task::JoinSet; @@ -49,6 +50,10 @@ pub fn get_listener_by_url( }) } +pub fn is_url_host_ipv6(l: &url::Url) -> bool { + l.host_str().map_or(false, |h| h.contains(':')) +} + #[async_trait] pub trait TunnelHandlerForListener { async fn handle_tunnel(&self, tunnel: Box) -> Result<(), Error>; @@ -58,7 +63,7 @@ pub trait TunnelHandlerForListener { impl TunnelHandlerForListener for PeerManager { #[tracing::instrument] async fn handle_tunnel(&self, tunnel: Box) -> Result<(), Error> { - self.add_tunnel_as_server(tunnel).await + self.add_tunnel_as_server(tunnel, true).await } } @@ -113,22 +118,26 @@ impl ListenerManage continue; }; let ctx = self.global_ctx.clone(); - self.add_listener(move || get_listener_by_url(&l, ctx.clone()).unwrap(), true) - .await?; - } - if self.global_ctx.config.get_flags().enable_ipv6 { - let ipv6_listener = self.global_ctx.config.get_flags().ipv6_listener.clone(); - let _ = self - .add_listener( - move || { - Box::new(UdpTunnelListener::new( - ipv6_listener.clone().parse().unwrap(), - )) - }, + let listener = l.clone(); + self.add_listener( + move || get_listener_by_url(&listener, ctx.clone()).unwrap(), + true, + ) + .await?; + + if self.global_ctx.config.get_flags().enable_ipv6 && !is_url_host_ipv6(&l) { + let mut ipv6_listener = l.clone(); + ipv6_listener + .set_host(Some("[::]".to_string().as_str())) + .with_context(|| format!("failed to set ipv6 host for listener: {}", l))?; + let ctx = self.global_ctx.clone(); + self.add_listener( + move || get_listener_by_url(&ipv6_listener, ctx.clone()).unwrap(), false, ) .await?; + } } Ok(()) @@ -161,11 +170,11 @@ impl ListenerManage global_ctx.issue_event(GlobalCtxEvent::ListenerAdded(l.local_url())); } Err(e) => { + tracing::error!(?e, ?l, "listener listen error"); global_ctx.issue_event(GlobalCtxEvent::ListenerAddFailed( l.local_url(), format!("error: {:?}, retry listen later...", e), )); - tracing::error!(?e, ?l, "listener listen error"); tokio::time::sleep(std::time::Duration::from_secs(1)).await; continue; } @@ -217,6 +226,15 @@ impl ListenerManage pub async fn run(&mut self) -> Result<(), Error> { for listener in &self.listeners { + if listener.must_succ { + // try listen once + let mut l = (listener.creator_fn)(); + let _g = self.net_ns.guard(); + l.listen() + .await + .with_context(|| format!("failed to listen on {}", l.local_url()))?; + } + self.tasks.spawn(Self::run_listener( listener.creator_fn.clone(), self.peer_manager.clone(), diff --git a/rust/easytier/src/peers/foreign_network_manager.rs b/rust/easytier/src/peers/foreign_network_manager.rs index dfc143c..df76d4f 100644 --- a/rust/easytier/src/peers/foreign_network_manager.rs +++ b/rust/easytier/src/peers/foreign_network_manager.rs @@ -695,7 +695,8 @@ mod tests { let (a_ring, b_ring) = crate::tunnel::ring::create_ring_tunnel_pair(); let b_mgr_copy = pm_center.clone(); - let s_ret = tokio::spawn(async move { b_mgr_copy.add_tunnel_as_server(b_ring).await }); + let s_ret = + tokio::spawn(async move { b_mgr_copy.add_tunnel_as_server(b_ring, true).await }); pma_net1.add_client_tunnel(a_ring).await.unwrap(); diff --git a/rust/easytier/src/peers/peer.rs b/rust/easytier/src/peers/peer.rs index 248bfc2..e3bb12e 100644 --- a/rust/easytier/src/peers/peer.rs +++ b/rust/easytier/src/peers/peer.rs @@ -11,7 +11,7 @@ use super::{ peer_conn::{PeerConn, PeerConnId}, PacketRecvChan, }; -use crate::proto::cli::PeerConnInfo; +use crate::{common::scoped_task::ScopedTask, proto::cli::PeerConnInfo}; use crate::{ common::{ error::Error, @@ -36,7 +36,8 @@ pub struct Peer { shutdown_notifier: Arc, - default_conn_id: AtomicCell, + default_conn_id: Arc>, + default_conn_id_clear_task: ScopedTask<()>, } impl Peer { @@ -88,6 +89,19 @@ impl Peer { )), ); + let default_conn_id = Arc::new(AtomicCell::new(PeerConnId::default())); + + let conns_copy = conns.clone(); + let default_conn_id_copy = default_conn_id.clone(); + let default_conn_id_clear_task = ScopedTask::from(tokio::spawn(async move { + loop { + tokio::time::sleep(std::time::Duration::from_secs(5)).await; + if conns_copy.len() > 1 { + default_conn_id_copy.store(PeerConnId::default()); + } + } + })); + Peer { peer_node_id, conns: conns.clone(), @@ -98,7 +112,8 @@ impl Peer { close_event_listener, shutdown_notifier, - default_conn_id: AtomicCell::new(PeerConnId::default()), + default_conn_id, + default_conn_id_clear_task, } } @@ -117,14 +132,19 @@ impl Peer { return Some(conn.clone()); } - let conn = self.conns.iter().next(); - if conn.is_none() { - return None; + // find a conn with the smallest latency + let mut min_latency = std::u64::MAX; + for conn in self.conns.iter() { + let latency = conn.value().get_stats().latency_us; + if latency < min_latency { + min_latency = latency; + self.default_conn_id.store(conn.get_conn_id()); + } } - let conn = conn.unwrap().clone(); - self.default_conn_id.store(conn.get_conn_id()); - Some(conn) + self.conns + .get(&self.default_conn_id.load()) + .map(|conn| conn.clone()) } pub async fn send_msg(&self, msg: ZCPacket) -> Result<(), Error> { @@ -158,6 +178,10 @@ impl Peer { } ret } + + pub fn get_default_conn_id(&self) -> PeerConnId { + self.default_conn_id.load() + } } // pritn on drop diff --git a/rust/easytier/src/peers/peer_manager.rs b/rust/easytier/src/peers/peer_manager.rs index e6b7f0a..610fad9 100644 --- a/rust/easytier/src/peers/peer_manager.rs +++ b/rust/easytier/src/peers/peer_manager.rs @@ -8,7 +8,7 @@ use std::{ use anyhow::Context; use async_trait::async_trait; -use dashmap::DashMap; +use dashmap::{DashMap, DashSet}; use tokio::{ sync::{ @@ -23,7 +23,7 @@ use crate::{ compressor::{Compressor as _, DefaultCompressor}, constants::EASYTIER_VERSION, error::Error, - global_ctx::{ArcGlobalCtx, NetworkIdentity}, + global_ctx::{ArcGlobalCtx, GlobalCtxEvent, NetworkIdentity}, stun::StunInfoCollectorTrait, PeerId, }, @@ -141,6 +141,9 @@ pub struct PeerManager { data_compress_algo: CompressorAlgo, exit_nodes: Vec, + + // conns that are directly connected (which are not hole punched) + directly_connected_conn_map: Arc>>, } impl Debug for PeerManager { @@ -267,6 +270,8 @@ impl PeerManager { data_compress_algo, exit_nodes, + + directly_connected_conn_map: Arc::new(DashMap::new()), } } @@ -325,8 +330,48 @@ impl PeerManager { Ok((peer_id, conn_id)) } + fn add_directly_connected_conn(&self, peer_id: PeerId, conn_id: uuid::Uuid) { + let _ = self + .directly_connected_conn_map + .entry(peer_id) + .or_insert_with(DashSet::new) + .insert(conn_id); + } + + pub fn has_directly_connected_conn(&self, peer_id: PeerId) -> bool { + self.directly_connected_conn_map + .get(&peer_id) + .map_or(false, |x| !x.is_empty()) + } + + async fn start_peer_conn_close_event_handler(&self) { + let dmap = self.directly_connected_conn_map.clone(); + let mut event_recv = self.global_ctx.subscribe(); + self.tasks.lock().await.spawn(async move { + while let Ok(event) = event_recv.recv().await { + match event { + GlobalCtxEvent::PeerConnRemoved(info) => { + if let Some(set) = dmap.get_mut(&info.peer_id) { + let conn_id = info.conn_id.parse().unwrap(); + let old = set.remove(&conn_id); + tracing::info!( + ?old, + ?info, + "try remove conn id from directly connected map" + ); + } + } + _ => {} + } + } + }); + } + #[tracing::instrument] - pub async fn try_connect(&self, mut connector: C) -> Result<(PeerId, PeerConnId), Error> + pub async fn try_direct_connect( + &self, + mut connector: C, + ) -> Result<(PeerId, PeerConnId), Error> where C: TunnelConnector + Debug, { @@ -334,18 +379,28 @@ impl PeerManager { let t = ns .run_async(|| async move { connector.connect().await }) .await?; - self.add_client_tunnel(t).await + let (peer_id, conn_id) = self.add_client_tunnel(t).await?; + self.add_directly_connected_conn(peer_id, conn_id); + Ok((peer_id, conn_id)) } #[tracing::instrument] - pub async fn add_tunnel_as_server(&self, tunnel: Box) -> Result<(), Error> { + pub async fn add_tunnel_as_server( + &self, + tunnel: Box, + is_directly_connected: bool, + ) -> Result<(), Error> { tracing::info!("add tunnel as server start"); let mut peer = PeerConn::new(self.my_peer_id, self.global_ctx.clone(), tunnel); peer.do_handshake_as_server().await?; if peer.get_network_identity().network_name == self.global_ctx.get_network_identity().network_name { + let (peer_id, conn_id) = (peer.get_peer_id(), peer.get_conn_id()); self.add_new_peer_conn(peer).await?; + if is_directly_connected { + self.add_directly_connected_conn(peer_id, conn_id); + } } else { self.foreign_network_manager.add_peer_conn(peer).await?; } @@ -857,9 +912,11 @@ impl PeerManager { async fn run_clean_peer_without_conn_routine(&self) { let peer_map = self.peers.clone(); + let dmap = self.directly_connected_conn_map.clone(); self.tasks.lock().await.spawn(async move { loop { peer_map.clean_peer_without_conn().await; + dmap.retain(|p, v| peer_map.has_peer(*p) && !v.is_empty()); tokio::time::sleep(std::time::Duration::from_secs(3)).await; } }); @@ -876,6 +933,8 @@ impl PeerManager { } pub async fn run(&self) -> Result<(), Error> { + self.start_peer_conn_close_event_handler().await; + match &self.route_algo_inst { RouteAlgoInst::Ospf(route) => self.add_route(route.clone()).await, RouteAlgoInst::None => {} @@ -924,7 +983,7 @@ impl PeerManager { self.foreign_network_client.clone() } - pub fn get_my_info(&self) -> cli::NodeInfo { + pub async fn get_my_info(&self) -> cli::NodeInfo { cli::NodeInfo { peer_id: self.my_peer_id, ipv4_addr: self @@ -950,6 +1009,7 @@ impl PeerManager { config: self.global_ctx.config.dump(), version: EASYTIER_VERSION.to_string(), feature_flag: Some(self.global_ctx.get_feature_flags()), + ip_list: Some(self.global_ctx.get_ip_collector().collect_ip_addrs().await), } } @@ -958,6 +1018,13 @@ impl PeerManager { tokio::time::sleep(std::time::Duration::from_secs(1)).await; } } + + pub fn get_directly_connections(&self, peer_id: PeerId) -> DashSet { + self.directly_connected_conn_map + .get(&peer_id) + .map(|x| x.clone()) + .unwrap_or_default() + } } #[cfg(test)] @@ -1026,7 +1093,7 @@ mod tests { tokio::spawn(async move { client.set_bind_addrs(vec![]); - client_mgr.try_connect(client).await.unwrap(); + client_mgr.try_direct_connect(client).await.unwrap(); }); server_mgr diff --git a/rust/easytier/src/peers/peer_map.rs b/rust/easytier/src/peers/peer_map.rs index 26aaf37..b6ae05d 100644 --- a/rust/easytier/src/peers/peer_map.rs +++ b/rust/easytier/src/peers/peer_map.rs @@ -212,6 +212,11 @@ impl PeerMap { } } + pub async fn get_peer_default_conn_id(&self, peer_id: PeerId) -> Option { + self.get_peer_by_id(peer_id) + .map(|p| p.get_default_conn_id()) + } + pub async fn close_peer_conn( &self, peer_id: PeerId, diff --git a/rust/easytier/src/peers/rpc_service.rs b/rust/easytier/src/peers/rpc_service.rs index 34dfac0..14f8f19 100644 --- a/rust/easytier/src/peers/rpc_service.rs +++ b/rust/easytier/src/peers/rpc_service.rs @@ -32,12 +32,23 @@ impl PeerManagerRpcService { .await .iter(), ); + let peer_map = self.peer_manager.get_peer_map(); let mut peer_infos = Vec::new(); for peer in peers { let mut peer_info = PeerInfo::default(); peer_info.peer_id = peer; + peer_info.default_conn_id = peer_map + .get_peer_default_conn_id(peer) + .await + .map(Into::into); + peer_info.directly_connected_conns = self + .peer_manager + .get_directly_connections(peer) + .into_iter() + .map(Into::into) + .collect(); - if let Some(conns) = self.peer_manager.get_peer_map().list_peer_conns(peer).await { + if let Some(conns) = peer_map.list_peer_conns(peer).await { peer_info.conns = conns; } else if let Some(conns) = self .peer_manager @@ -121,7 +132,7 @@ impl PeerManageRpc for PeerManagerRpcService { _request: ShowNodeInfoRequest, // Accept request of type HelloRequest ) -> Result { Ok(ShowNodeInfoResponse { - node_info: Some(self.peer_manager.get_my_info()), + node_info: Some(self.peer_manager.get_my_info().await), }) } } diff --git a/rust/easytier/src/peers/tests.rs b/rust/easytier/src/peers/tests.rs index 0b1d971..90ffe5c 100644 --- a/rust/easytier/src/peers/tests.rs +++ b/rust/easytier/src/peers/tests.rs @@ -45,7 +45,7 @@ pub async fn connect_peer_manager(client: Arc, server: Arc Option { let mut ret = u64::MAX; let p = self.peer.as_ref()?; + let default_conn_id = p.default_conn_id.map(|id| id.to_string()); for conn in p.conns.iter() { let Some(stats) = &conn.stats else { continue; }; + if default_conn_id == Some(conn.conn_id.to_string()) { + return Some(f64::from(stats.latency_us as u32) / 1000.0); + } ret = ret.min(stats.latency_us); } diff --git a/rust/easytier/src/proto/common.proto b/rust/easytier/src/proto/common.proto index 7519860..2494bd0 100644 --- a/rust/easytier/src/proto/common.proto +++ b/rust/easytier/src/proto/common.proto @@ -18,7 +18,7 @@ message FlagsInConfig { bool disable_p2p = 11; bool relay_all_peer_rpc = 12; bool disable_udp_hole_punching = 13; - string ipv6_listener = 14; + // string ipv6_listener = 14; [deprecated = true]; use -l udp://[::]:12345 instead bool multi_thread = 15; CompressionAlgoPb data_compress_algo = 16; bool bind_device = 17; diff --git a/rust/easytier/src/tunnel/common.rs b/rust/easytier/src/tunnel/common.rs index cc5ee29..b834d15 100644 --- a/rust/easytier/src/tunnel/common.rs +++ b/rust/easytier/src/tunnel/common.rs @@ -360,7 +360,13 @@ pub(crate) fn setup_sokcet2_ext( socket2_socket.set_nonblocking(true)?; socket2_socket.set_reuse_address(true)?; - socket2_socket.bind(&socket2::SockAddr::from(*bind_addr))?; + if let Err(e) = socket2_socket.bind(&socket2::SockAddr::from(*bind_addr)) { + if bind_addr.is_ipv4() { + return Err(e.into()); + } else { + tracing::warn!(?e, "bind failed, do not return error for ipv6"); + } + } // #[cfg(all(unix, not(target_os = "solaris"), not(target_os = "illumos")))] // socket2_socket.set_reuse_port(true)?; diff --git a/rust/easytier/src/tunnel/mod.rs b/rust/easytier/src/tunnel/mod.rs index b3deb4e..958f9df 100644 --- a/rust/easytier/src/tunnel/mod.rs +++ b/rust/easytier/src/tunnel/mod.rs @@ -126,7 +126,7 @@ pub trait TunnelListener: Send { } #[async_trait] -#[auto_impl::auto_impl(Box)] +#[auto_impl::auto_impl(Box, &mut)] pub trait TunnelConnector: Send { async fn connect(&mut self) -> Result, TunnelError>; fn remote_url(&self) -> url::Url; diff --git a/rust/easytier/src/tunnel/tcp.rs b/rust/easytier/src/tunnel/tcp.rs index d5efaf7..d0d4b0d 100644 --- a/rust/easytier/src/tunnel/tcp.rs +++ b/rust/easytier/src/tunnel/tcp.rs @@ -150,9 +150,9 @@ impl TcpTunnelConnector { &mut self, addr: SocketAddr, ) -> Result, super::TunnelError> { - tracing::info!(addr = ?self.addr, "connect tcp start"); + tracing::info!(url = ?self.addr, ?addr, "connect tcp start, bind addrs: {:?}", self.bind_addrs); let stream = TcpStream::connect(addr).await?; - tracing::info!(addr = ?self.addr, "connect tcp succ"); + tracing::info!(url = ?self.addr, ?addr, "connect tcp succ"); return get_tunnel_with_tcp_stream(stream, self.addr.clone().into()); } @@ -190,7 +190,7 @@ impl super::TunnelConnector for TcpTunnelConnector { async fn connect(&mut self) -> Result, super::TunnelError> { let addr = check_scheme_and_get_socket_addr_ext::(&self.addr, "tcp", self.ip_version)?; - if self.bind_addrs.is_empty() || addr.is_ipv6() { + if self.bind_addrs.is_empty() { self.connect_with_default_bind(addr).await } else { self.connect_with_custom_bind(addr).await diff --git a/rust/easytier/src/tunnel/udp.rs b/rust/easytier/src/tunnel/udp.rs index 07c5d46..b3c808f 100644 --- a/rust/easytier/src/tunnel/udp.rs +++ b/rust/easytier/src/tunnel/udp.rs @@ -141,12 +141,27 @@ async fn respond_stun_packet( .encode_into_bytes(resp_msg.clone()) .map_err(|e| anyhow::anyhow!("stun encode error: {:?}", e))?; - socket - .send_to(&rsp_buf, addr.clone()) - .await - .with_context(|| "send stun response error")?; + let change_req = req_msg + .get_attribute::() + .map(|r| r.ip() || r.port()) + .unwrap_or(false); - tracing::debug!(?addr, ?req_msg, "udp respond stun packet done"); + if !change_req { + socket + .send_to(&rsp_buf, addr.clone()) + .await + .with_context(|| "send stun response error")?; + } else { + // send from a new udp socket + let socket = if addr.is_ipv4() { + UdpSocket::bind("0.0.0.0:0").await? + } else { + UdpSocket::bind("[::]:0").await? + }; + socket.send_to(&rsp_buf, addr.clone()).await?; + } + + tracing::debug!(?addr, ?req_msg, ?change_req, "udp respond stun packet done"); Ok(()) } diff --git a/rust/src/api/simple.rs b/rust/src/api/simple.rs index 63ffce8..4fb10da 100644 --- a/rust/src/api/simple.rs +++ b/rust/src/api/simple.rs @@ -573,7 +573,7 @@ pub fn create_server( specified_ip: String, room_name: String, room_password: String, - severurl: String, + severurl: Vec, ) { RT.spawn(async move { // 创建一个示例配置 @@ -584,14 +584,16 @@ pub fn create_server( // flags.dev_name = "astral".to_string(); cfg.set_flags(flags); // 创建TCP和UDP连接配置列表 - let peer_configs = vec![ - PeerConfig { - uri: format!("tcp://{}", severurl).parse().unwrap(), - }, - PeerConfig { - uri: format!("udp://{}", severurl).parse().unwrap(), - } - ]; + let mut peer_configs = Vec::new(); + // 为每个服务器URL创建TCP和UDP配置 + for url in severurl { + peer_configs.push(PeerConfig { + uri: format!("tcp://{}", url).parse().unwrap(), + }); + peer_configs.push(PeerConfig { + uri: format!("udp://{}", url).parse().unwrap(), + }); + } cfg.set_peers(peer_configs); if enable_dhcp == false { diff --git a/rust/src/frb_generated.rs b/rust/src/frb_generated.rs index 9bdae1c..7422e25 100644 --- a/rust/src/frb_generated.rs +++ b/rust/src/frb_generated.rs @@ -107,7 +107,7 @@ fn wire__crate__api__simple__create_server_impl( let api_specified_ip = ::sse_decode(&mut deserializer); let api_room_name = ::sse_decode(&mut deserializer); let api_room_password = ::sse_decode(&mut deserializer); - let api_severurl = ::sse_decode(&mut deserializer); + let api_severurl = >::sse_decode(&mut deserializer); deserializer.end(); move |context| { transform_result_sse::<_, ()>((move || { @@ -608,6 +608,18 @@ impl SseDecode for Vec { } } +impl SseDecode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { + let mut len_ = ::sse_decode(deserializer); + let mut ans_ = vec![]; + for idx_ in 0..len_ { + ans_.push(::sse_decode(deserializer)); + } + return ans_; + } +} + impl SseDecode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_decode(deserializer: &mut flutter_rust_bridge::for_generated::SseDeserializer) -> Self { @@ -1022,6 +1034,16 @@ impl SseEncode for Vec { } } +impl SseEncode for Vec { + // Codec=Sse (Serialization based), see doc to use other codecs + fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) { + ::sse_encode(self.len() as _, serializer); + for item in self { + ::sse_encode(item, serializer); + } + } +} + impl SseEncode for Vec { // Codec=Sse (Serialization based), see doc to use other codecs fn sse_encode(self, serializer: &mut flutter_rust_bridge::for_generated::SseSerializer) {