1ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline/* 2ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * Copyright (C) 2016 The Android Open Source Project 3ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * 4ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * Licensed under the Apache License, Version 2.0 (the "License"); 5ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * you may not use this file except in compliance with the License. 6ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * You may obtain a copy of the License at 7ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * 8ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * http://www.apache.org/licenses/LICENSE-2.0 9ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * 10ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * Unless required by applicable law or agreed to in writing, software 11ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * distributed under the License is distributed on an "AS IS" BASIS, 12ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * See the License for the specific language governing permissions and 14ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * limitations under the License. 15ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline */ 16ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 17ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klinepackage android.net.util; 18ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 1984714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klineimport static android.net.util.PacketReader.DEFAULT_RECV_BUF_SIZE; 20ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport static android.system.OsConstants.*; 214a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertEquals; 224a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertFalse; 234a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.assertTrue; 244a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport static org.junit.Assert.fail; 25ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 26f840e07f821cb17c9ae1e6583a28eff548b90892Erik Klineimport android.os.Handler; 27f840e07f821cb17c9ae1e6583a28eff548b90892Erik Klineimport android.os.HandlerThread; 284a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport android.support.test.filters.SmallTest; 294a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport android.support.test.runner.AndroidJUnit4; 30ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport android.system.ErrnoException; 31ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport android.system.Os; 32ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport android.system.StructTimeval; 33ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 34ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.io.FileDescriptor; 35ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.io.FileInputStream; 36ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.io.IOException; 37f840e07f821cb17c9ae1e6583a28eff548b90892Erik Klineimport java.io.UncheckedIOException; 38ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.DatagramPacket; 39ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.DatagramSocket; 40ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.Inet6Address; 41ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.InetAddress; 42ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.InetSocketAddress; 43ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.net.SocketException; 44ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.util.Arrays; 45ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.util.concurrent.CountDownLatch; 46ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Klineimport java.util.concurrent.TimeUnit; 47ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 484a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.runner.RunWith; 494a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.After; 504a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.Before; 514a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport org.junit.Test; 52ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 534a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichiimport libcore.io.IoBridge; 54ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 55ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline/** 5684714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline * Tests for PacketReader. 57ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * 58ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline * @hide 59ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline */ 604a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi@RunWith(AndroidJUnit4.class) 614a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi@SmallTest 6284714bffa1a58fe1f6a114ae015f8e38be46f32dErik Klinepublic class PacketReaderTest { 63ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline static final InetAddress LOOPBACK6 = Inet6Address.getLoopbackAddress(); 64ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline static final StructTimeval TIMEO = StructTimeval.fromMillis(500); 65ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 66ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline protected CountDownLatch mLatch; 67ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline protected FileDescriptor mLocalSocket; 68ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline protected InetSocketAddress mLocalSockName; 69ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline protected byte[] mLastRecvBuf; 70f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected boolean mStopped; 71f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected HandlerThread mHandlerThread; 7284714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline protected PacketReader mReceiver; 73ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 7484714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline class UdpLoopbackReader extends PacketReader { 75f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline public UdpLoopbackReader(Handler h) { 76f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline super(h); 77f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 78f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 79f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline @Override 80f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected FileDescriptor createFd() { 81f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline FileDescriptor s = null; 82f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline try { 83f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline s = Os.socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 84f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline Os.bind(s, LOOPBACK6, 0); 85f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLocalSockName = (InetSocketAddress) Os.getsockname(s); 86f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO); 87f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } catch (ErrnoException|SocketException e) { 88f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline closeFd(s); 89f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline fail(); 90f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline return null; 91f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 92f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 93f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLocalSocket = s; 94f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline return s; 95f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 96f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 97f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline @Override 98f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected void handlePacket(byte[] recvbuf, int length) { 99f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLastRecvBuf = Arrays.copyOf(recvbuf, length); 100f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLatch.countDown(); 101f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 102f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 103f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline @Override 104f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected void onStart() { 105f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mStopped = false; 106f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLatch.countDown(); 107f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 108f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 109f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline @Override 110f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline protected void onStop() { 111f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mStopped = true; 112f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLatch.countDown(); 113f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 114f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline }; 115f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 1164a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi @Before 117ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline public void setUp() { 118ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline resetLatch(); 119ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline mLocalSocket = null; 120ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline mLocalSockName = null; 121ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline mLastRecvBuf = null; 122f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mStopped = false; 123ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 12484714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline mHandlerThread = new HandlerThread(PacketReaderTest.class.getSimpleName()); 125f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mHandlerThread.start(); 126ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline } 127ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 1284a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi @After 129f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline public void tearDown() throws Exception { 130f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline if (mReceiver != null) { 131f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mHandlerThread.getThreadHandler().post(() -> { mReceiver.stop(); }); 132f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline waitForActivity(); 133f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 134ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline mReceiver = null; 135f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mHandlerThread.quit(); 136f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mHandlerThread = null; 137ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline } 138ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 139ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline void resetLatch() { mLatch = new CountDownLatch(1); } 140ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 141ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline void waitForActivity() throws Exception { 142f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline try { 143f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mLatch.await(1000, TimeUnit.MILLISECONDS); 144f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } finally { 145f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline resetLatch(); 146f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 147ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline } 148ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 149ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline void sendPacket(byte[] contents) throws Exception { 150ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline final DatagramSocket sender = new DatagramSocket(); 151ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline sender.connect(mLocalSockName); 152ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline sender.send(new DatagramPacket(contents, contents.length)); 153ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline sender.close(); 154ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline } 155ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 1564a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi @Test 157ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline public void testBasicWorking() throws Exception { 158f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline final Handler h = mHandlerThread.getThreadHandler(); 159f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mReceiver = new UdpLoopbackReader(h); 160f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 161f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline h.post(() -> { mReceiver.start(); }); 162f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline waitForActivity(); 163ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(mLocalSockName != null); 164ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertEquals(LOOPBACK6, mLocalSockName.getAddress()); 165ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(0 < mLocalSockName.getPort()); 166ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(mLocalSocket != null); 167f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline assertFalse(mStopped); 168ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 169ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline final byte[] one = "one 1".getBytes("UTF-8"); 170ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline sendPacket(one); 171ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline waitForActivity(); 172ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertEquals(1, mReceiver.numPacketsReceived()); 173ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(Arrays.equals(one, mLastRecvBuf)); 174f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline assertFalse(mStopped); 175ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 176ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline final byte[] two = "two 2".getBytes("UTF-8"); 177ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline sendPacket(two); 178ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline waitForActivity(); 179ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertEquals(2, mReceiver.numPacketsReceived()); 180ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(Arrays.equals(two, mLastRecvBuf)); 181f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline assertFalse(mStopped); 182ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline 183ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline mReceiver.stop(); 184ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline waitForActivity(); 185ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertEquals(2, mReceiver.numPacketsReceived()); 186ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline assertTrue(Arrays.equals(two, mLastRecvBuf)); 187f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline assertTrue(mStopped); 188f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline mReceiver = null; 189f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 190f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 19184714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline class NullPacketReader extends PacketReader { 19284714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline public NullPacketReader(Handler h, int recvbufsize) { 193f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline super(h, recvbufsize); 194f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 195f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 196f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline @Override 197f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline public FileDescriptor createFd() { return null; } 198f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 199f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 2004a0c5d7ef7144280fe8a209a871bbd4ef90d6368Hugo Benichi @Test 201f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline public void testMinimalRecvBufSize() throws Exception { 202f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline final Handler h = mHandlerThread.getThreadHandler(); 203f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline 204f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline for (int i : new int[]{-1, 0, 1, DEFAULT_RECV_BUF_SIZE-1}) { 20584714bffa1a58fe1f6a114ae015f8e38be46f32dErik Kline final PacketReader b = new NullPacketReader(h, i); 206f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline assertEquals(DEFAULT_RECV_BUF_SIZE, b.recvBufSize()); 207f840e07f821cb17c9ae1e6583a28eff548b90892Erik Kline } 208ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline } 209ade3a8ccb0acc1ba1ee29e5668b5e78670f26002Erik Kline} 210