android: Poll dropper TUN device for data on older Android systems

It seems that even the NIO version of read() is uninterruptible on
platforms < Android 7 (24).
This commit is contained in:
Tobias Brunner 2018-07-03 15:03:51 +02:00
parent 6ca381be05
commit 4e905b96dd
1 changed files with 30 additions and 8 deletions

View File

@ -1012,20 +1012,42 @@ public class CharonVpnService extends VpnService implements Runnable, VpnStateSe
FileInputStream plain = new FileInputStream(mFd.getFileDescriptor()); FileInputStream plain = new FileInputStream(mFd.getFileDescriptor());
ByteBuffer packet = ByteBuffer.allocate(mCache.mMtu); ByteBuffer packet = ByteBuffer.allocate(mCache.mMtu);
while (true) while (true)
{ /* just read and ignore all data, regular read() is not properly interruptible */ {
int len = plain.getChannel().read(packet); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
packet.clear(); { /* just read and ignore all data, regular read() is not interruptible */
if (len < 0) int len = plain.getChannel().read(packet);
{ packet.clear();
break; 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 */ /* regular interruption */
} }
catch (Exception e) catch (IOException e)
{ {
e.printStackTrace(); e.printStackTrace();
} }