]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
android: Poll dropper TUN device for data on older Android systems
authorTobias Brunner <tobias@strongswan.org>
Tue, 3 Jul 2018 13:03:51 +0000 (15:03 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 3 Jul 2018 13:35:29 +0000 (15:35 +0200)
It seems that even the NIO version of read() is uninterruptible on
platforms < Android 7 (24).

src/frontends/android/app/src/main/java/org/strongswan/android/logic/CharonVpnService.java

index ac22cf5ff2a1e89342b6eea1cd32869bbfd4c487..2777202b595c11e3d70f6346bba3dc7ec833fa72 100644 (file)
@@ -1012,20 +1012,42 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
                                        FileInputStream plain = new FileInputStream(mFd.getFileDescriptor());
                                        ByteBuffer packet = ByteBuffer.allocate(mCache.mMtu);
                                        while (true)
-                                       {       /* just read and ignore all data, regular read() is not properly interruptible */
-                                               int len = plain.getChannel().read(packet);
-                                               packet.clear();
-                                               if (len < 0)
-                                               {
-                                                       break;
+                                       {
+                                               if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
+                                               {       /* just read and ignore all data, regular read() is not interruptible */
+                                                       int len = plain.getChannel().read(packet);
+                                                       packet.clear();
+                                                       if (len < 0)
+                                                       {
+                                                               break;
+                                                       }
+                                               }
+                                               else
+                                               {       /* this is rather ugly but on older platforms not even the NIO version of read() is interruptible */
+                                                       boolean wait = true;
+                                                       if (plain.available() > 0)
+                                                       {
+                                                               int len = plain.read(packet.array());
+                                                               packet.clear();
+                                                               if (len < 0 || Thread.interrupted())
+                                                               {
+                                                                       break;
+                                                               }
+                                                               /* check again right away, there may be another packet */
+                                                               wait = false;
+                                                       }
+                                                       if (wait)
+                                                       {
+                                                               Thread.sleep(250);
+                                                       }
                                                }
                                        }
                                }
-                               catch (ClosedByInterruptException e)
+                               catch (ClosedByInterruptException|InterruptedException e)
                                {
                                        /* regular interruption */
                                }
-                               catch (Exception e)
+                               catch (IOException e)
                                {
                                        e.printStackTrace();
                                }