Ping implements Runnable { @Override public void run() { final int inet, proto; if (mDest instanceof Inet6Address) { inet = OsConstants.AF_INET6; proto = OsConstants.IPPROTO_ICMPV6; } else { inet = OsConstants.AF_INET; proto = OsConstants.IPPROTO_ICMP; } try { final FileDescriptor fd = socket(inet, proto); if (fd.valid()) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mNetwork != null) { mNetwork.bindSocket(fd); } setLowDelay(fd); final StructPollfd structPollfd = new StructPollfd(); structPollfd.fd = fd; structPollfd.events = POLLIN; final StructPollfd[] structPollfds = {structPollfd}; for (int i = 0; i < mCount; i++) { final ByteBuffer byteBuffer = mEchoPacketBuilder.build(); final byte buffer[] = new byte[byteBuffer.limit()]; try { final long start = System.currentTimeMillis(); int rc = sendto(fd, byteBuffer); if (rc >= 0) { rc = poll(structPollfds); final long time = calcLatency(start, System.currentTimeMillis()); if (rc >= 0) { if (structPollfd.revents == POLLIN) { structPollfd.revents = 0; rc = recvfrom(fd, buffer); if (rc < 0) { Log.d(TAG, "recvfrom() return failure: " + rc); } mListener.onPing(time, i); } else { mListener.onPing(TIMED_OUT_MS, i); } } else { mListener.onPingException(new IOException("poll() failed"), i); break; } } else { mListener.onPingException(new IOException("sendto() failed"), i); break; } } catch (ErrnoException e) { mListener.onPingException(e, i); break; } sleep(); } } finally { close(fd); } } else { mListener.onPingException(new IOException("Invalid FD " + fd.toString()), 0); } } catch (ErrnoException | IOException e) { mListener.onPingException(e, 0); } } Ping(final InetAddress dest, final PingListener listener); void setTimeoutMs(final int timeoutMs); int getTimeoutMs(); int getDelayMs(); void setDelayMs(final int delayMs); int getCount(); void setCount(final int count); Network getNetwork(); void setNetwork(final Network network); void setEchoPacketBuilder(final EchoPacketBuilder echoPacketBuilder); @Override void run(); static final int DEFAULT_COUNT; static final long TIMED_OUT_MS; }
@Test public void testCreateSocketFailure() { final MockPingListener listener = new MockPingListener(); final ErrnoException fail = new ErrnoException("socket()", 1); new MockPing(null, listener) { @Override protected FileDescriptor socket(final int inet, final int proto) throws ErrnoException { throw fail; } }.run(); Assert.assertEquals(fail, listener.exception); }
@Test public void testInvalidFd() { final MockPingListener listener = new MockPingListener(); new MockPing(null, listener) { @Override protected FileDescriptor socket(final int inet, final int proto) { try (final FileInputStream in = new FileInputStream(File.createTempFile("testfd", ".bin"))){ return in.getFD(); } catch (IOException e) { throw new RuntimeException(e); } } }.run(); Assert.assertTrue(listener.exception instanceof IOException); }
@Test public void testErrnoException() { final MockPingListener listener = new MockPingListener(); final ErrnoException fail = new ErrnoException("sendto()", 1); new MockPing(null, listener) { @Override protected int sendto(final FileDescriptor fd, final ByteBuffer byteBuffer) throws ErrnoException { throw fail; } }.run(); Assert.assertEquals(fail, listener.exception); }