@@ -2,8 +2,6 @@ import 'dart:async';
22import 'dart:convert' ;
33import 'package:http/http.dart' as http;
44import 'package:dart_ping/dart_ping.dart' ;
5- import 'package:vpnclient_engine_flutter/vpnclient_engine/core.dart' ;
6-
75import 'package:flutter/foundation.dart' ;
86import 'package:flutter_v2ray/flutter_v2ray.dart' ;
97import 'package:rxdart/rxdart.dart' ;
@@ -96,17 +94,6 @@ class RoutingRule {
9694 RoutingRule ({this .appName, this .domain, required this .action});
9795}
9896
99- class WireGuardCore implements VpnCore {
100- @override
101- Future <void > connect ({
102- required int subscriptionIndex,
103- required int serverIndex,
104- }) {
105- // TODO: implement connect
106- throw UnimplementedError ();
107- }
108- }
109-
11097abstract class VpnCore {
11198 Future <void > connect ({
11299 required int subscriptionIndex,
@@ -122,300 +109,3 @@ abstract class VpnCore {
122109 void setAutoConnect ({required bool enable});
123110 void setKillSwitch ({required bool enable});
124111}
125-
126- class V2RayCore implements VpnCore {
127- final FlutterV2ray _flutterV2ray = FlutterV2ray (
128- onStatusChanged: (status) {
129- // do something
130- },
131- );
132- List <List <String >> _subscriptionServers = [];
133- List <String > _subscriptions = [];
134-
135- final _connectionStatusSubject = BehaviorSubject <ConnectionStatus >();
136- Stream <ConnectionStatus > get onConnectionStatusChanged =>
137- _connectionStatusSubject.stream;
138-
139- final _errorSubject = BehaviorSubject <ErrorDetails >();
140- Stream <ErrorDetails > get onError => _errorSubject.stream;
141-
142- final _serverSwitchedSubject = BehaviorSubject <String >();
143- Stream <String > get onServerSwitched => _serverSwitchedSubject.stream;
144-
145- final _pingResultSubject = BehaviorSubject <PingResult >();
146- Stream <PingResult > get onPingResult => _pingResultSubject.stream;
147-
148- final _subscriptionLoadedSubject = BehaviorSubject <SubscriptionDetails >();
149- Stream <SubscriptionDetails > get onSubscriptionLoaded =>
150- _subscriptionLoadedSubject.stream;
151-
152- final _dataUsageUpdatedSubject = BehaviorSubject <SessionStatistics >();
153- Stream <SessionStatistics > get onDataUsageUpdated =>
154- _dataUsageUpdatedSubject.stream;
155-
156- final _routingRulesAppliedSubject = BehaviorSubject <List <RoutingRule >>();
157- Stream <List <RoutingRule >> get onRoutingRulesApplied =>
158- _routingRulesAppliedSubject.stream;
159-
160- final _killSwitchTriggeredSubject = BehaviorSubject <void >();
161- Stream <void > get onKillSwitchTriggered => _killSwitchTriggeredSubject.stream;
162-
163- void _emitError (ErrorCode code, String message) {
164- _errorSubject.add (ErrorDetails (errorCode: code, errorMessage: message));
165- }
166-
167- void initialize () {
168- print ('V2RayCore initialized' );
169- }
170-
171- void clearSubscriptions () {
172- _subscriptions.clear ();
173- print ('All subscriptions cleared' );
174- }
175-
176- void addSubscription ({required String subscriptionURL}) {
177- _subscriptions.add (subscriptionURL);
178- print ('Subscription added: $subscriptionURL ' );
179- }
180-
181- void addSubscriptions ({required List <String > subscriptionURLs}) {
182- _subscriptions.addAll (subscriptionURLs);
183- print ('Subscriptions added: ${subscriptionURLs .join (", " )}' );
184- }
185-
186- Future <void > updateSubscription ({required int subscriptionIndex}) async {
187- if (subscriptionIndex < 0 || subscriptionIndex >= _subscriptions.length) {
188- print ('Invalid subscription index' );
189- return ;
190- }
191-
192- final url = _subscriptions[subscriptionIndex];
193- print ('Fetching subscription data from: $url ' );
194-
195- try {
196- final response = await http.get (Uri .parse (url));
197-
198- if (response.statusCode != 200 ) {
199- print ('Failed to fetch subscription: HTTP ${response .statusCode }' );
200- return ;
201- }
202-
203- final content = response.body.trim ();
204-
205- List <String > servers = [];
206-
207- if (content.startsWith ('[' )) {
208- final jsonList = jsonDecode (content) as List <dynamic >;
209- for (var server in jsonList) {
210- servers.add (server.toString ());
211- }
212- print ('Parsed JSON subscription: ${servers .length } servers loaded' );
213- } else {
214- servers =
215- content
216- .split ('\n ' )
217- .where ((line) => line.trim ().isNotEmpty)
218- .toList ();
219- print ('Parsed NEWLINE subscription: ${servers .length } servers loaded' );
220- }
221-
222- while (_subscriptionServers.length <= subscriptionIndex) {
223- _subscriptionServers.add ([]);
224- }
225-
226- _subscriptionServers[subscriptionIndex] = servers;
227- _subscriptionLoadedSubject.add (SubscriptionDetails ());
228-
229- print ('Subscription #$subscriptionIndex servers updated successfully' );
230- } catch (e) {
231- print ('Error updating subscription: $e ' );
232- _emitError (ErrorCode .unknownError, 'Error updating subscription: $e ' );
233- }
234- }
235-
236- @override
237- Future <void > connect ({
238- required int subscriptionIndex,
239- required int serverIndex,
240- }) async {
241- try {
242- if (subscriptionIndex < 0 ||
243- subscriptionIndex >= _subscriptionServers.length) {
244- print ('Invalid subscription index' );
245- return ;
246- }
247- if (serverIndex < 0 ||
248- serverIndex >= _subscriptionServers[subscriptionIndex].length) {
249- print ('Invalid server index' );
250- return ;
251- }
252-
253- await _flutterV2ray.initializeV2Ray ();
254-
255- final serverAddress =
256- _subscriptionServers[subscriptionIndex][serverIndex];
257- V2RayURL parser = FlutterV2ray .parseFromURL (serverAddress);
258-
259- _connectionStatusSubject.add (ConnectionStatus .connecting);
260- if (await _flutterV2ray.requestPermission ()) {
261- _flutterV2ray.startV2Ray (
262- remark: parser.remark,
263- config: parser.getFullConfiguration (),
264- blockedApps: null ,
265- bypassSubnets: null ,
266- proxyOnly: false ,
267- );
268- }
269- _serverSwitchedSubject.add (serverAddress);
270- _connectionStatusSubject.add (ConnectionStatus .connected);
271- print ('Successfully connected' );
272- } catch (e) {
273- _emitError (ErrorCode .unknownError, 'Error connecting: $e ' );
274- _connectionStatusSubject.add (ConnectionStatus .error);
275- }
276- }
277-
278- @override
279- Future <void > disconnect () async {
280- _flutterV2ray.stopV2Ray ();
281- _connectionStatusSubject.add (ConnectionStatus .disconnected);
282- print ('Disconnected successfully' );
283- }
284-
285- @override
286- void setRoutingRules ({required List <RoutingRule > rules}) {
287- for (var rule in rules) {
288- if (rule.appName != null ) {
289- print ('Routing rule for app ${rule .appName }: ${rule .action }' );
290- } else if (rule.domain != null ) {
291- print ('Routing rule for domain ${rule .domain }: ${rule .action }' );
292- }
293- }
294- }
295-
296- @override
297- void pingServer ({required int subscriptionIndex, required int index}) async {
298- if (subscriptionIndex < 0 ||
299- subscriptionIndex >= _subscriptionServers.length) {
300- print ('Invalid subscription index' );
301- _emitError (ErrorCode .unknownError, 'Invalid subscription index' );
302- return ;
303- }
304- if (index < 0 || index >= _subscriptionServers[subscriptionIndex].length) {
305- print ('Invalid server index' );
306- _emitError (ErrorCode .unknownError, 'Invalid server index' );
307- return ;
308- }
309- final serverAddress = _subscriptionServers[subscriptionIndex][index];
310- print ('Pinging server: $serverAddress ' );
311- try {
312- final ping = Ping (serverAddress, count: 3 );
313- final pingData = await ping.stream.firstWhere (
314- (data) => data.response != null ,
315- );
316- if (pingData.response != null ) {
317- final latency = pingData.response! .time! .inMilliseconds;
318- final result = PingResult (
319- subscriptionIndex: subscriptionIndex,
320- serverIndex: index,
321- latencyInMs: latency,
322- );
323- _pingResultSubject.add (result);
324- print (
325- 'Ping result: sub=${result .subscriptionIndex }, server=${result .serverIndex }, latency=${result .latencyInMs } ms' ,
326- );
327- } else {
328- print ('Ping failed: No response' );
329- _pingResultSubject.add (
330- PingResult (
331- subscriptionIndex: subscriptionIndex,
332- serverIndex: index,
333- latencyInMs: - 1 ,
334- ),
335- );
336- _emitError (ErrorCode .serverUnavailable, 'Ping failed: No response' );
337- }
338- } catch (e) {
339- print ('Ping error: $e ' );
340- _pingResultSubject.add (
341- PingResult (
342- subscriptionIndex: subscriptionIndex,
343- serverIndex: index,
344- latencyInMs: - 1 ,
345- ),
346- );
347- _emitError (ErrorCode .unknownError, 'Ping error: $e ' );
348- }
349- }
350-
351- @override
352- String getConnectionStatus () {
353- return 'disconnected' ;
354- }
355-
356- @override
357- List <Server > getServerList () {
358- return [
359- Server (
360- address: 'server1.com' ,
361- latency: 50 ,
362- location: 'USA' ,
363- isPreferred: true ,
364- ),
365- Server (
366- address: 'server2.com' ,
367- latency: 100 ,
368- location: 'UK' ,
369- isPreferred: false ,
370- ),
371- Server (
372- address: 'server3.com' ,
373- latency: 75 ,
374- location: 'Canada' ,
375- isPreferred: false ,
376- ),
377- ];
378- }
379-
380- @override
381- Future <void > loadSubscriptions ({
382- required List <String > subscriptionLinks,
383- }) async {
384- print ('loadSubscriptions: ${subscriptionLinks .join (", " )}' );
385- _subscriptions.addAll (subscriptionLinks);
386- print ('Subscriptions added: ${subscriptionLinks .join (", " )}' );
387- for (var index = 0 ; index < subscriptionLinks.length; index++ ) {
388- await updateSubscription (subscriptionIndex: index);
389- }
390- }
391-
392- @override
393- SessionStatistics getSessionStatistics () {
394- return SessionStatistics (
395- sessionDuration: Duration (minutes: 30 ),
396- dataInBytes: 1024 * 1024 * 100 ,
397- dataOutBytes: 1024 * 1024 * 50 ,
398- );
399- }
400-
401- @override
402- void setAutoConnect ({required bool enable}) {
403- print ('setAutoConnect: $enable ' );
404- }
405-
406- @override
407- void setKillSwitch ({required bool enable}) {
408- print ('setKillSwitch: $enable ' );
409- }
410- }
411-
412- class OpenVPNCore implements VpnCore {
413- @override
414- Future <void > connect ({
415- required int subscriptionIndex,
416- required int serverIndex,
417- }) {
418- // TODO: implement connect
419- throw UnimplementedError ();
420- }
421- }
0 commit comments