6363import org .fptn .vpn .enums .PerAppVpnMode ;
6464import org .fptn .vpn .enums .SniSpoofingMode ;
6565import org .fptn .vpn .services .tile .FptnTileService ;
66+ import org .fptn .vpn .services .websocket .DnsServers ;
6667import org .fptn .vpn .utils .NetworkUtils ;
6768import org .fptn .vpn .utils .NotificationUtils ;
6869import org .fptn .vpn .utils .SharedPrefUtils ;
@@ -110,6 +111,11 @@ public class FptnService extends VpnService {
110111 private ConnectivityManager .NetworkCallback networkWaitCallback ;
111112 private volatile int pendingServerId = SELECTED_SERVER_ID_AUTO ;
112113
114+ private volatile DnsServers cachedDnsServers = null ;
115+ private volatile int cachedDnsServersServerId = -1 ;
116+
117+ private volatile boolean restoringSession = false ;
118+
113119 // Pending Intent for launch MainActivity when notification tapped
114120 private PendingIntent launchMainActivityPendingIntent ;
115121
@@ -202,6 +208,19 @@ public void sendExceptionToService(PVNClientException exception, int senderConne
202208 submittedConnectionAttempt = executorService .submit (this ::handleFallbackToAllServers );
203209 return ;
204210 }
211+ if (restoringSession && Objects .equals (exception .errorCode , ErrorCode .CONNECT_TO_SERVER_ERROR )) {
212+ if (!NetworkUtils .isOnline (connectivityManager )) {
213+ XLog .tag (TAG ).i ("Reconnect couldn't re-establish, offline — waiting for network [server=%d]" ,
214+ current .getServerEntity ().getId ());
215+ enterWaitingForNetwork (current .getServerEntity ().getId ());
216+ } else {
217+ XLog .tag (TAG ).i ("Reconnect couldn't re-establish — scanning for a working server" );
218+ setActiveConnection (null );
219+ submittedConnectionAttempt = executorService .submit (this ::handleFallbackToAllServers );
220+ }
221+ return ;
222+ }
223+ restoringSession = false ;
205224 disconnect (exception );
206225 if (Objects .equals (exception .errorCode , ErrorCode .RECONNECTING_FAILED )) {
207226 showReconnectionFailedNotification ();
@@ -224,6 +243,11 @@ public void updateConnectionState(ConnectionState connectionState, int reconnect
224243 switchState (connectionState , reconnectionCount , disconnectReason );
225244 }
226245
246+ public void cacheDnsServers (int serverId , DnsServers dnsServers ) {
247+ cachedDnsServers = dnsServers ;
248+ cachedDnsServersServerId = serverId ;
249+ }
250+
227251 /* Static methods to start/stop service */
228252 public synchronized static void startToConnect (Context context , ServerEntity serverEntity ) {
229253 Intent intent = new Intent (context , FptnService .class );
@@ -325,6 +349,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
325349 XLog .tag (TAG ).i ("Received command [action=%s, state=%s]" , intent .getAction (), currentState );
326350
327351 if (ACTION_CONNECT .equals (intent .getAction ()) && !isActiveState ) {
352+ restoringSession = false ;
328353 if (submittedConnectionAttempt != null && !submittedConnectionAttempt .isDone ()) {
329354 XLog .tag (TAG ).w ("Ignoring CONNECT — connection attempt already in progress [state=%s]" , currentState );
330355 return START_STICKY ;
@@ -463,6 +488,8 @@ private synchronized void unregisterNetworkCallback() {
463488
464489 public void enterWaitingForNetwork (int serverId ) {
465490 XLog .tag (TAG ).i ("Network offline — entering WAITING_FOR_NETWORK [pendingServerId=%d]" , serverId );
491+ restoringSession = true ;
492+
466493 String serverInfo = getActionConnectServerInfo (); // capture before teardown nulls the connection
467494 pendingServerId = serverId ;
468495 updateNotificationWithMessage (getString (R .string .waiting_for_network ), serverInfo );
@@ -586,6 +613,7 @@ private void switchState(ConnectionState connectionState, int reconnectCount, St
586613 }
587614 case CONNECTING -> setConnectionState (ConnectionState .CONNECTING , null );
588615 case CONNECTED -> {
616+ restoringSession = false ;
589617 String serverInfo = getActionConnectServerInfo ();
590618 updateNotificationWithMessage (getString (R .string .connected_to ) + serverInfo , "" );
591619
@@ -711,6 +739,9 @@ private void connectInternal(ServerEntity serverEntity, String sniHostname, Stri
711739 boolean customDnsEnabled = SharedPrefUtils .getCustomDnsEnabled (this );
712740 String customDnsIpv4 = customDnsEnabled ? SharedPrefUtils .getCustomDnsIpv4 (this ) : null ;
713741
742+ DnsServers preFetchedDnsServers = (cachedDnsServers != null && cachedDnsServersServerId == serverEntity .getId ())
743+ ? cachedDnsServers : null ;
744+
714745 connection = new FptnConnection (
715746 this ,
716747 nextConnectionId .getAndIncrement (),
@@ -729,7 +760,8 @@ private void connectInternal(ServerEntity serverEntity, String sniHostname, Stri
729760 preFetchedToken ,
730761 connectivityManager ,
731762 adBlocker ,
732- customDnsIpv4
763+ customDnsIpv4 ,
764+ preFetchedDnsServers
733765 );
734766 connection .setConfigureVpnIntent (launchMainActivityPendingIntent );
735767 connection .start ();
0 commit comments