Commits

rhynes committed 0562b48

Switched to simple TCP connect for check tunnel test.

Comments (0)

Files changed (2)

Android/PsiphonAndroidLibrary/src/com/psiphon3/psiphonlibrary/PsiphonConstants.java

 
     public final static int DEFAULT_WEB_SERVER_PORT = 443;
     
+    public final static int CHECK_TUNNEL_SERVER_PORT = 7999;
+    
+    public final static int CHECK_TUNNEL_TIMEOUT_MILLISECONDS = 5000;
+    
     public final static int SESSION_ESTABLISHMENT_TIMEOUT_MILLISECONDS = 20000;
     
     public final static String RELAY_PROTOCOL = "OSSH";

Android/PsiphonAndroidLibrary/src/com/psiphon3/psiphonlibrary/TunnelCore.java

 package com.psiphon3.psiphonlibrary;
 
 import java.io.IOException;
+import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ArrayBlockingQueue;
             
             checkSignals(0);
 
+            // Certain Android devices silently fail to route through the VpnService tun device. 
+            // Test connecting to a service available only through the tunnel. Stop when the check fails.
+            if (tunnelWholeDevice)
+            {
+                boolean success = false;
+                try
+                {
+                    SocketChannel channel = SocketChannel.open();
+                    channel.configureBlocking(false);
+                    channel.connect(new InetSocketAddress(entry.ipAddress, PsiphonConstants.CHECK_TUNNEL_SERVER_PORT));
+                    Selector selector = Selector.open();
+                    channel.register(selector, SelectionKey.OP_CONNECT);                    
+                    for (int i = 0;
+                         i < PsiphonConstants.CHECK_TUNNEL_TIMEOUT_MILLISECONDS && selector.select(100) == 0;
+                         i += 100)
+                    {
+                        checkSignals(0);
+                    }
+                    success = channel.finishConnect();                    
+                    selector.close();
+                    channel.close();
+                }
+                catch (IOException e)
+                {
+                }
+
+                if (!success)
+                {
+                    MyLog.w(R.string.check_tunnel_failed, MyLog.Sensitivity.NOT_SENSITIVE);
+                    
+                    // Stop entirely. If this test fails, there's something wrong with routing.
+                    runAgain = false;
+                    return runAgain;
+                }
+            }
+            
+            checkSignals(0);
+
             try
             {
                 m_interface.doHandshakeRequest();
                 throw new IOException();
             }
             
-            checkSignals(0);
-
-            if (tunnelWholeDevice)
-            {
-                try
-                {
-                    m_interface.doCheckTunnelRequest();
-                } 
-                catch (PsiphonServerInterfaceException requestException)
-                {
-                    MyLog.w(R.string.check_tunnel_failed, MyLog.Sensitivity.NOT_SENSITIVE, requestException);
-                    
-                    // Stop entirely. If this test fails, there's something wrong with routing.
-                    runAgain = false;
-                    return runAgain;
-                }
-            }
-            
             if (m_useGenericLogMessages)
             {
                 MyLog.i(R.string.psiphon_running_generic, MyLog.Sensitivity.NOT_SENSITIVE);