@@ -383,134 +383,29 @@ class V2RayService extends ChangeNotifier {
383383 }
384384 }
385385
386- // Modern crash-proof ping handling with rate limiting and proper async patterns
387- static final Map <String , Future <int ?>> _ongoingPings = {};
388- static const int _maxConcurrentPings = 5 ; // Limit concurrent pings
389- static int _currentPingCount = 0 ;
390-
386+ /// Simple and reliable ping method similar to flutter_v2ray example
391387 Future <int ?> getServerDelay (V2RayConfig config) async {
392- return _safeExecute <int ?>(
393- operation: () => _performPingWithRateLimit (config),
394- fallbackValue: null ,
395- context: 'getServerDelay for ${config .remark }' ,
396- );
397- }
398-
399- Future <int ?> _performPingWithRateLimit (V2RayConfig config) async {
400- final configId = config.id;
401- final hostKey = '${config .address }:${config .port }' ;
402-
403- // Return cached result if available and not expired (5 minutes cache)
404- final cachedTime = _pingCacheTime[hostKey];
405- if (_pingCache.containsKey (hostKey) &&
406- cachedTime != null &&
407- DateTime .now ().difference (cachedTime).inMinutes < 5 ) {
408- return _pingCache[hostKey];
409- }
410-
411- // Check if ping is already in progress for this host
412- if (_ongoingPings.containsKey (hostKey)) {
413- try {
414- return await _ongoingPings[hostKey]! .timeout (
415- const Duration (seconds: 15 ),
416- onTimeout: () => null ,
417- );
418- } catch (e) {
419- debugPrint ('Error waiting for ongoing ping: $e ' );
420- _ongoingPings.remove (hostKey);
421- return null ;
422- }
423- }
424-
425- // Rate limiting - wait if too many concurrent pings
426- while (_currentPingCount >= _maxConcurrentPings) {
427- await Future .delayed (const Duration (milliseconds: 100 ));
428- }
429-
430- // Start new ping operation
431- _currentPingCount++ ;
432- final pingFuture = _executePingOperation (config, hostKey);
433- _ongoingPings[hostKey] = pingFuture;
434-
435388 try {
436- final result = await pingFuture;
437- return result;
438- } finally {
439- _currentPingCount-- ;
440- _ongoingPings.remove (hostKey);
441- }
442- }
443-
444- Future <int ?> _executePingOperation (V2RayConfig config, String hostKey) async {
445- try {
446- // Ensure V2Ray is initialized with timeout
447- await _safeInitialize ();
448-
449- // Parse config with comprehensive error handling
450- final parser = await _safeParseConfig (config);
451- if (parser == null ) {
452- _updatePingCache (hostKey, null );
453- return null ;
454- }
455-
456- // Execute ping with multiple fallback strategies
457- final delay = await _performPingWithFallback (parser, config);
389+ // Ensure V2Ray is initialized
390+ await initialize ();
458391
459- // Cache result with timestamp
460- _updatePingCache (hostKey, delay);
461- return delay;
392+ // Parse the configuration
393+ final parser = FlutterV2ray .parseFromURL (config.fullConfig);
462394
463- } catch (e) {
464- debugPrint ('Ping operation failed for ${config .remark }: $e ' );
465- _updatePingCache (hostKey, null );
466- return null ;
467- }
468- }
469-
470- Future <int ?> _performPingWithFallback (V2RayURL parser, V2RayConfig config) async {
471- const maxAttempts = 2 ;
472-
473- for (int attempt = 1 ; attempt <= maxAttempts; attempt++ ) {
474- try {
475- final delay = await _flutterV2ray.getServerDelay (
476- config: parser.getFullConfiguration (),
477- ).timeout (
478- Duration (seconds: 6 + attempt), // Progressive timeout
479- onTimeout: () => throw TimeoutException ('Ping timeout' , Duration (seconds: 6 + attempt)),
480- );
481-
482- if (_isValidPing (delay)) {
483- return delay;
484- }
485-
486- if (attempt < maxAttempts) {
487- await Future .delayed (Duration (milliseconds: 500 * attempt));
488- }
489- } on TimeoutException catch (e) {
490- debugPrint ('Ping timeout attempt $attempt for ${config .remark }: $e ' );
491- if (attempt == maxAttempts) return null ;
492- } catch (e) {
493- debugPrint ('Ping error attempt $attempt for ${config .remark }: $e ' );
494- if (attempt == maxAttempts) return null ;
495- }
496- }
497-
498- return null ;
499- }
500-
501- bool _isValidPing (int ? delay) {
502- return delay != null && delay >= 0 && delay < 30000 ; // Max 30 seconds
503- }
504-
505- void _updatePingCache (String hostKey, int ? delay) {
506- try {
507- _pingCache[hostKey] = delay;
508- _pingCacheTime[hostKey] = DateTime .now ();
395+ // Get server delay with timeout
396+ final delay = await _flutterV2ray.getServerDelay (
397+ config: parser.getFullConfiguration (),
398+ ).timeout (
399+ const Duration (seconds: 8 ),
400+ onTimeout: () => - 1 ,
401+ );
402+
403+ // Return valid ping or null for invalid/timeout results
404+ return (delay >= 0 ) ? delay : null ;
509405
510- // Cleanup old cache entries to prevent memory leaks
511- _cleanupPingCache ();
512406 } catch (e) {
513- debugPrint ('Error updating ping cache: $e ' );
407+ debugPrint ('Error getting server delay for ${config .remark }: $e ' );
408+ return null ;
514409 }
515410 }
516411
@@ -1213,27 +1108,4 @@ class V2RayService extends ChangeNotifier {
12131108 return results;
12141109 }
12151110
1216- /// Enhanced memory management
1217- void _performMemoryCleanup () {
1218- try {
1219- // Cleanup ping cache and stale timestamps
1220- _cleanupPingCache ();
1221- debugPrint ('Memory cleanup completed' );
1222- } catch (e) {
1223- debugPrint ('Error during memory cleanup: $e ' );
1224- }
1225- }
1226-
1227- /// Force cleanup all resources
1228- void forceCleanup () {
1229- try {
1230- _currentPingCount = 0 ;
1231- _ongoingPings.clear ();
1232- _performMemoryCleanup ();
1233-
1234- debugPrint ('Force cleanup completed' );
1235- } catch (e) {
1236- debugPrint ('Error in force cleanup: $e ' );
1237- }
1238- }
12391111}
0 commit comments