openPorts);
- }
-
- /**
- * Set the address to ping
- *
- * @param address - Address to be pinged
- * @return this object to allow chaining
- * @throws UnknownHostException - if no IP address for the
- * {@code host} could be found, or if a scope_id was specified
- * for a global IPv6 address.
- */
- public static PortScan onAddress(String address) throws UnknownHostException {
- return onAddress(InetAddress.getByName(address));
- }
-
- /**
- * Set the address to ping
- *
- * @param ia - Address to be pinged
- * @return this object to allow chaining
- */
- public static PortScan onAddress(InetAddress ia) {
- PortScan portScan = new PortScan();
- portScan.setAddress(ia);
- portScan.setDefaultThreadsAndTimeouts();
- return portScan;
- }
-
- /**
- * Sets the timeout for each port scanned
- *
- * If you raise the timeout you may want to consider increasing the thread count {@link #setNoThreads(int)} to compensate.
- * We can afford to have quite a high thread count as most of the time the thread is just sitting
- * idle and waiting for the socket to timeout.
- *
- * @param timeOutMillis - the timeout for each ping in milliseconds
- * Recommendations:
- * Local host: 20 - 500 ms - can be very fast as request doesn't need to go over network
- * Local network 500 - 2500 ms
- * Remote Scan 2500+ ms
- * @return this object to allow chaining
- */
- public PortScan setTimeOutMillis(int timeOutMillis) {
- if (timeOutMillis < 0) throw new IllegalArgumentException("Timeout cannot be less than 0");
- this.timeOutMillis = timeOutMillis;
- return this;
- }
-
- /**
- * Scan the ports to scan
- *
- * @param port - the port to scan
- * @return this object to allow chaining
- */
- public PortScan setPort(int port) {
- ports.clear();
- validatePort(port);
- ports.add(port);
- return this;
- }
-
- /**
- * Scan the ports to scan
- *
- * @param ports - the ports to scan
- * @return this object to allow chaining
- */
- public PortScan setPorts(ArrayList ports) {
-
- // Check all ports are valid
- for (Integer port : ports) {
- validatePort(port);
- }
-
- this.ports = ports;
-
- return this;
- }
-
- /**
- * Scan the ports to scan
- *
- * @param portString - the ports to scan (comma separated, hyphen denotes a range). For example:
- * "21-23,25,45,53,80"
- * @return this object to allow chaining
- */
- public PortScan setPorts(String portString) {
-
- ports.clear();
-
- ArrayList ports = new ArrayList<>();
-
- if (portString == null) {
- throw new IllegalArgumentException("Empty port string not allowed");
- }
-
- portString = portString.substring(portString.indexOf(":") + 1, portString.length());
-
- for (String x : portString.split(",")) {
- if (x.contains("-")) {
- int start = Integer.parseInt(x.split("-")[0]);
- int end = Integer.parseInt(x.split("-")[1]);
- validatePort(start);
- validatePort(end);
- if (end <= start)
- throw new IllegalArgumentException("Start port cannot be greater than or equal to the end port");
-
- for (int j = start; j <= end; j++) {
- ports.add(j);
- }
- } else {
- int start = Integer.parseInt(x);
- validatePort(start);
- ports.add(start);
- }
- }
-
- this.ports = ports;
-
- return this;
- }
-
- /**
- * Checks and throws exception if port is not valid
- *
- * @param port - the port to validate
- */
- private void validatePort(int port) {
- if (port < 1) throw new IllegalArgumentException("Start port cannot be less than 1");
- if (port > 65535) throw new IllegalArgumentException("Start cannot be greater than 65535");
- }
-
- /**
- * Scan all privileged ports
- *
- * @return this object to allow chaining
- */
- public PortScan setPortsPrivileged() {
- ports.clear();
- for (int i = 1; i < 1024; i++) {
- ports.add(i);
- }
- return this;
- }
-
- /**
- * Scan all ports
- *
- * @return this object to allow chaining
- */
- public PortScan setPortsAll() {
- ports.clear();
- for (int i = 1; i < 65536; i++) {
- ports.add(i);
- }
- return this;
- }
-
- private void setAddress(InetAddress address) {
- this.address = address;
- }
-
- private void setDefaultThreadsAndTimeouts() {
- // Try and work out automatically what kind of host we are scanning
- // local host (this device) / local network / remote
- if (IPTools.isIpAddressLocalhost(address)) {
- // If we are scanning a the localhost set the timeout to be very short so we get faster results
- // This will be overridden if user calls setTimeoutMillis manually.
- timeOutMillis = TIMEOUT_LOCALHOST;
- noThreads = DEFAULT_THREADS_LOCALHOST;
- } else if (IPTools.isIpAddressLocalNetwork(address)) {
- // Assume local network (not infallible)
- timeOutMillis = TIMEOUT_LOCALNETWORK;
- noThreads = DEFAULT_THREADS_LOCALNETWORK;
- } else {
- // Assume remote network timeouts
- timeOutMillis = TIMEOUT_REMOTE;
- noThreads = DEFAULT_THREADS_REMOTE;
- }
- }
-
- /**
- * @param noThreads set the number of threads to work with, note we default to a large number
- * as these requests are network heavy not cpu heavy.
- * @return self
- * @throws IllegalArgumentException - if no threads is less than 1
- */
- public PortScan setNoThreads(int noThreads) throws IllegalArgumentException {
- if (noThreads < 1) throw new IllegalArgumentException("Cannot have less than 1 thread");
- this.noThreads = noThreads;
- return this;
- }
-
-
- /**
- * Set scan method, either TCP or UDP
- *
- * @param method - the transport method to use to scan, either PortScan.METHOD_UDP or PortScan.METHOD_TCP
- * @return this object to allow chaining
- * @throws IllegalArgumentException - if invalid method
- */
- private PortScan setMethod(int method) {
- switch (method) {
- case METHOD_UDP:
- case METHOD_TCP:
- this.method = method;
- break;
- default:
- throw new IllegalArgumentException("Invalid method type " + method);
- }
- return this;
- }
-
- /**
- * Set scan method to UDP
- *
- * @return this object to allow chaining
- */
- public PortScan setMethodUDP() {
- setMethod(METHOD_UDP);
- return this;
- }
-
- /**
- * Set scan method to TCP
- *
- * @return this object to allow chaining
- */
- public PortScan setMethodTCP() {
- setMethod(METHOD_TCP);
- return this;
- }
-
-
- /**
- * Cancel a running ping
- */
- public void cancel() {
- this.cancelled = true;
- }
-
- /**
- * Perform a synchronous (blocking) port scan and return a list of open ports
- *
- * @return - ping result
- */
- public ArrayList doScan() {
-
- cancelled = false;
- openPortsFound.clear();
-
- ExecutorService executor = Executors.newFixedThreadPool(noThreads);
-
- for (int portNo : ports) {
- Runnable worker = new PortScanRunnable(address, portNo, timeOutMillis, method);
- executor.execute(worker);
- }
-
- // This will make the executor accept no new threads
- // and finish all existing threads in the queue
- executor.shutdown();
- // Wait until all threads are finish
- try {
- executor.awaitTermination(1, TimeUnit.HOURS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- Collections.sort(openPortsFound);
-
- return openPortsFound;
- }
-
- /**
- * Perform an asynchronous (non-blocking) port scan
- *
- * @param portListener - the listener to fire portscan results to.
- * @return - this object so we can cancel the scan if needed
- */
- public PortScan doScan(final PortListener portListener) {
-
- this.portListener = portListener;
- openPortsFound.clear();
- cancelled = false;
-
- new Thread(new Runnable() {
- @Override
- public void run() {
-
- ExecutorService executor = Executors.newFixedThreadPool(noThreads);
-
- for (int portNo : ports) {
- Runnable worker = new PortScanRunnable(address, portNo, timeOutMillis, method);
- executor.execute(worker);
- }
-
- // This will make the executor accept no new threads
- // and finish all existing threads in the queue
- executor.shutdown();
- // Wait until all threads are finish
- try {
- executor.awaitTermination(1, TimeUnit.HOURS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- if (portListener != null) {
- Collections.sort(openPortsFound);
- portListener.onFinished(openPortsFound);
- }
-
- }
- }).start();
-
- return this;
- }
-
- private synchronized void portScanned(int port, boolean open) {
- if (open) {
- openPortsFound.add(port);
- }
- if (portListener != null) {
- portListener.onResult(port, open);
- }
- }
-
- private class PortScanRunnable implements Runnable {
- private final InetAddress address;
- private final int portNo;
- private final int timeOutMillis;
- private final int method;
-
- PortScanRunnable(InetAddress address, int portNo, int timeOutMillis, int method) {
- this.address = address;
- this.portNo = portNo;
- this.timeOutMillis = timeOutMillis;
- this.method = method;
- }
-
- @Override
- public void run() {
- if (cancelled) return;
-
- switch (method) {
- case METHOD_UDP:
- portScanned(portNo, PortScanUDP.scanAddress(address, portNo, timeOutMillis));
- break;
- case METHOD_TCP:
- portScanned(portNo, PortScanTCP.scanAddress(address, portNo, timeOutMillis));
- break;
- default:
- throw new IllegalArgumentException("Invalid method");
- }
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/PortScan.kt b/library/src/main/java/com/stealthcopter/networktools/PortScan.kt
new file mode 100644
index 0000000..95e82dc
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/PortScan.kt
@@ -0,0 +1,358 @@
+package com.stealthcopter.networktools
+
+import com.stealthcopter.networktools.IPTools.isIpAddressLocalNetwork
+import com.stealthcopter.networktools.IPTools.isIpAddressLocalhost
+import com.stealthcopter.networktools.portscanning.PortScanTCP
+import com.stealthcopter.networktools.portscanning.PortScanUDP
+import java.net.InetAddress
+import java.net.UnknownHostException
+import java.util.*
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+
+class PortScan // This class is not to be instantiated
+private constructor() {
+ private var method = METHOD_TCP
+ private var noThreads = 50
+ private var address: InetAddress? = null
+ private var timeOutMillis = 1000
+ private var cancelled = false
+ private var ports = ArrayList()
+ private val openPortsFound = ArrayList()
+ private var portListener: PortListener? = null
+
+ interface PortListener {
+ fun onResult(portNo: Int, open: Boolean)
+ fun onFinished(openPorts: ArrayList?)
+ }
+
+ /**
+ * Sets the timeout for each port scanned
+ *
+ *
+ * If you raise the timeout you may want to consider increasing the thread count [.setNoThreads] to compensate.
+ * We can afford to have quite a high thread count as most of the time the thread is just sitting
+ * idle and waiting for the socket to timeout.
+ *
+ * @param timeOutMillis - the timeout for each ping in milliseconds
+ * Recommendations:
+ * Local host: 20 - 500 ms - can be very fast as request doesn't need to go over network
+ * Local network 500 - 2500 ms
+ * Remote Scan 2500+ ms
+ * @return this object to allow chaining
+ */
+ fun setTimeOutMillis(timeOutMillis: Int): PortScan {
+ require(timeOutMillis >= 0) { "Timeout cannot be less than 0" }
+ this.timeOutMillis = timeOutMillis
+ return this
+ }
+
+ /**
+ * Scan the ports to scan
+ *
+ * @param port - the port to scan
+ * @return this object to allow chaining
+ */
+ fun setPort(port: Int): PortScan {
+ ports.clear()
+ validatePort(port)
+ ports.add(port)
+ return this
+ }
+
+ /**
+ * Scan the ports to scan
+ *
+ * @param ports - the ports to scan
+ * @return this object to allow chaining
+ */
+ fun setPorts(ports: ArrayList): PortScan {
+
+ // Check all ports are valid
+ for (port in ports) {
+ validatePort(port)
+ }
+ this.ports = ports
+ return this
+ }
+
+ /**
+ * Scan the ports to scan
+ *
+ * @param portString - the ports to scan (comma separated, hyphen denotes a range). For example:
+ * "21-23,25,45,53,80"
+ * @return this object to allow chaining
+ */
+ fun setPorts(portString: String?): PortScan {
+ var portString = portString
+ ports.clear()
+ val ports = ArrayList()
+ requireNotNull(portString) { "Empty port string not allowed" }
+ portString = portString.substring(portString.indexOf(":") + 1, portString.length)
+ for (x in portString.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) {
+ if (x.contains("-")) {
+ val start = x.split("-".toRegex()).dropLastWhile { it.isEmpty() }
+ .toTypedArray()[0].toInt()
+ val end =
+ x.split("-".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1].toInt()
+ validatePort(start)
+ validatePort(end)
+ require(end > start) { "Start port cannot be greater than or equal to the end port" }
+ for (j in start..end) {
+ ports.add(j)
+ }
+ } else {
+ val start = x.toInt()
+ validatePort(start)
+ ports.add(start)
+ }
+ }
+ this.ports = ports
+ return this
+ }
+
+ /**
+ * Checks and throws exception if port is not valid
+ *
+ * @param port - the port to validate
+ */
+ private fun validatePort(port: Int) {
+ require(port >= 1) { "Start port cannot be less than 1" }
+ require(port <= 65535) { "Start cannot be greater than 65535" }
+ }
+
+ /**
+ * Scan all privileged ports
+ *
+ * @return this object to allow chaining
+ */
+ fun setPortsPrivileged(): PortScan {
+ ports.clear()
+ for (i in 1..1023) {
+ ports.add(i)
+ }
+ return this
+ }
+
+ /**
+ * Scan all ports
+ *
+ * @return this object to allow chaining
+ */
+ fun setPortsAll(): PortScan {
+ ports.clear()
+ for (i in 1..65535) {
+ ports.add(i)
+ }
+ return this
+ }
+
+ private fun setAddress(address: InetAddress) {
+ this.address = address
+ }
+
+ private fun setDefaultThreadsAndTimeouts() {
+ // Try and work out automatically what kind of host we are scanning
+ // local host (this device) / local network / remote
+ if (isIpAddressLocalhost(address)) {
+ // If we are scanning a the localhost set the timeout to be very short so we get faster results
+ // This will be overridden if user calls setTimeoutMillis manually.
+ timeOutMillis = TIMEOUT_LOCALHOST
+ noThreads = DEFAULT_THREADS_LOCALHOST
+ } else if (isIpAddressLocalNetwork(address)) {
+ // Assume local network (not infallible)
+ timeOutMillis = TIMEOUT_LOCALNETWORK
+ noThreads = DEFAULT_THREADS_LOCALNETWORK
+ } else {
+ // Assume remote network timeouts
+ timeOutMillis = TIMEOUT_REMOTE
+ noThreads = DEFAULT_THREADS_REMOTE
+ }
+ }
+
+ /**
+ * @param noThreads set the number of threads to work with, note we default to a large number
+ * as these requests are network heavy not cpu heavy.
+ * @return self
+ * @throws IllegalArgumentException - if no threads is less than 1
+ */
+ @Throws(IllegalArgumentException::class)
+ fun setNoThreads(noThreads: Int): PortScan {
+ require(noThreads >= 1) { "Cannot have less than 1 thread" }
+ this.noThreads = noThreads
+ return this
+ }
+
+ /**
+ * Set scan method, either TCP or UDP
+ *
+ * @param method - the transport method to use to scan, either PortScan.METHOD_UDP or PortScan.METHOD_TCP
+ * @return this object to allow chaining
+ * @throws IllegalArgumentException - if invalid method
+ */
+ private fun setMethod(method: Int): PortScan {
+ when (method) {
+ METHOD_UDP, METHOD_TCP -> this.method = method
+ else -> throw IllegalArgumentException("Invalid method type $method")
+ }
+ return this
+ }
+
+ /**
+ * Set scan method to UDP
+ *
+ * @return this object to allow chaining
+ */
+ fun setMethodUDP(): PortScan {
+ setMethod(METHOD_UDP)
+ return this
+ }
+
+ /**
+ * Set scan method to TCP
+ *
+ * @return this object to allow chaining
+ */
+ fun setMethodTCP(): PortScan {
+ setMethod(METHOD_TCP)
+ return this
+ }
+
+ /**
+ * Cancel a running ping
+ */
+ fun cancel() {
+ cancelled = true
+ }
+
+ /**
+ * Perform a synchronous (blocking) port scan and return a list of open ports
+ *
+ * @return - ping result
+ */
+ fun doScan(): ArrayList {
+ cancelled = false
+ openPortsFound.clear()
+ val executor = Executors.newFixedThreadPool(noThreads)
+ for (portNo in ports) {
+ val worker: Runnable = PortScanRunnable(address, portNo, timeOutMillis, method)
+ executor.execute(worker)
+ }
+
+ // This will make the executor accept no new threads
+ // and finish all existing threads in the queue
+ executor.shutdown()
+ // Wait until all threads are finish
+ try {
+ executor.awaitTermination(1, TimeUnit.HOURS)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ Collections.sort(openPortsFound)
+ return openPortsFound
+ }
+
+ /**
+ * Perform an asynchronous (non-blocking) port scan
+ *
+ * @param portListener - the listener to fire portscan results to.
+ * @return - this object so we can cancel the scan if needed
+ */
+ fun doScan(portListener: PortListener?): PortScan {
+ this.portListener = portListener
+ openPortsFound.clear()
+ cancelled = false
+ Thread {
+ val executor = Executors.newFixedThreadPool(noThreads)
+ for (portNo in ports) {
+ val worker: Runnable = PortScanRunnable(address, portNo, timeOutMillis, method)
+ executor.execute(worker)
+ }
+
+ // This will make the executor accept no new threads
+ // and finish all existing threads in the queue
+ executor.shutdown()
+ // Wait until all threads are finish
+ try {
+ executor.awaitTermination(1, TimeUnit.HOURS)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+ if (portListener != null) {
+ Collections.sort(openPortsFound)
+ portListener.onFinished(openPortsFound)
+ }
+ }.start()
+ return this
+ }
+
+ @Synchronized
+ private fun portScanned(port: Int, open: Boolean) {
+ if (open) {
+ openPortsFound.add(port)
+ }
+ if (portListener != null) {
+ portListener!!.onResult(port, open)
+ }
+ }
+
+ private inner class PortScanRunnable internal constructor(
+ private val address: InetAddress?,
+ private val portNo: Int,
+ private val timeOutMillis: Int,
+ private val method: Int
+ ) : Runnable {
+ override fun run() {
+ if (cancelled) return
+ when (method) {
+ METHOD_UDP -> portScanned(
+ portNo,
+ PortScanUDP.scanAddress(address, portNo, timeOutMillis)
+ )
+ METHOD_TCP -> portScanned(
+ portNo,
+ PortScanTCP.scanAddress(address, portNo, timeOutMillis)
+ )
+ else -> throw IllegalArgumentException("Invalid method")
+ }
+ }
+ }
+
+ companion object {
+ private const val TIMEOUT_LOCALHOST = 25
+ private const val TIMEOUT_LOCALNETWORK = 1000
+ private const val TIMEOUT_REMOTE = 2500
+ private const val DEFAULT_THREADS_LOCALHOST = 7
+ private const val DEFAULT_THREADS_LOCALNETWORK = 50
+ private const val DEFAULT_THREADS_REMOTE = 50
+ private const val METHOD_TCP = 0
+ private const val METHOD_UDP = 1
+
+ /**
+ * Set the address to ping
+ *
+ * @param address - Address to be pinged
+ * @return this object to allow chaining
+ * @throws UnknownHostException - if no IP address for the
+ * `host` could be found, or if a scope_id was specified
+ * for a global IPv6 address.
+ */
+ @Throws(UnknownHostException::class)
+ fun onAddress(address: String?): PortScan {
+ return onAddress(InetAddress.getByName(address))
+ }
+
+ /**
+ * Set the address to ping
+ *
+ * @param ia - Address to be pinged
+ * @return this object to allow chaining
+ */
+ fun onAddress(ia: InetAddress): PortScan {
+ val portScan = PortScan()
+ portScan.setAddress(ia)
+ portScan.setDefaultThreadsAndTimeouts()
+ return portScan
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.java b/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.java
deleted file mode 100644
index 471d0bb..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.java
+++ /dev/null
@@ -1,254 +0,0 @@
-package com.stealthcopter.networktools;
-
-import com.stealthcopter.networktools.ping.PingResult;
-import com.stealthcopter.networktools.subnet.Device;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-public class SubnetDevices {
- private int noThreads = 100;
-
- private ArrayList addresses;
- private ArrayList devicesFound;
- private OnSubnetDeviceFound listener;
- private int timeOutMillis = 2500;
- private boolean cancelled = false;
-
- private boolean disableProcNetMethod = false;
- private HashMap ipMacHashMap = null;
-
- // This class is not to be instantiated
- private SubnetDevices() {
- }
-
- public interface OnSubnetDeviceFound {
- void onDeviceFound(Device device);
-
- void onFinished(ArrayList devicesFound);
- }
-
- /**
- * Find devices on the subnet working from the local device ip address
- *
- * @return - this for chaining
- */
- public static SubnetDevices fromLocalAddress() {
- InetAddress ipv4 = IPTools.getLocalIPv4Address();
-
- if (ipv4 == null) {
- throw new IllegalAccessError("Could not access local ip address");
- }
-
- return fromIPAddress(ipv4.getHostAddress());
- }
-
- /**
- * @param inetAddress - an ip address in the subnet
- *
- * @return - this for chaining
- */
- public static SubnetDevices fromIPAddress(InetAddress inetAddress) {
- return fromIPAddress(inetAddress.getHostAddress());
- }
-
- /**
- * @param ipAddress - the ipAddress string of any device in the subnet i.e. "192.168.0.1"
- * the final part will be ignored
- *
- * @return - this for chaining
- */
- public static SubnetDevices fromIPAddress(final String ipAddress) {
-
- if (!IPTools.isIPv4Address(ipAddress)) {
- throw new IllegalArgumentException("Invalid IP Address");
- }
-
- String segment = ipAddress.substring(0, ipAddress.lastIndexOf(".") + 1);
-
- SubnetDevices subnetDevice = new SubnetDevices();
-
- subnetDevice.addresses = new ArrayList<>();
-
- // Get addresses from ARP Info first as they are likely to be reachable
- for(String ip : ARPInfo.getAllIPAddressesInARPCache()) {
- if (ip.startsWith(segment)) {
- subnetDevice.addresses.add(ip);
- }
- }
-
- // Add all missing addresses in subnet
- for (int j = 0; j < 255; j++) {
- if (!subnetDevice.addresses.contains(segment + j)) {
- subnetDevice.addresses.add(segment + j);
- }
- }
-
- return subnetDevice;
-
- }
-
-
- /**
- * @param ipAddresses - the ipAddresses of devices to be checked
- *
- * @return - this for chaining
- */
- public static SubnetDevices fromIPList(final List ipAddresses) {
-
- SubnetDevices subnetDevice = new SubnetDevices();
-
- subnetDevice.addresses = new ArrayList<>();
-
- subnetDevice.addresses.addAll(ipAddresses);
-
- return subnetDevice;
-
- }
-
- /**
- * @param noThreads set the number of threads to work with, note we default to a large number
- * as these requests are network heavy not cpu heavy.
- *
- * @throws IllegalArgumentException - if invalid number of threads requested
- *
- * @return - this for chaining
- */
- public SubnetDevices setNoThreads(int noThreads) throws IllegalArgumentException {
- if (noThreads < 1) throw new IllegalArgumentException("Cannot have less than 1 thread");
- this.noThreads = noThreads;
- return this;
- }
-
- /**
- * Sets the timeout for each address we try to ping
- *
- * @param timeOutMillis - timeout in milliseconds for each ping
- *
- * @return this object to allow chaining
- *
- * @throws IllegalArgumentException - if timeout is less than zero
- */
- public SubnetDevices setTimeOutMillis(int timeOutMillis) throws IllegalArgumentException {
- if (timeOutMillis < 0) throw new IllegalArgumentException("Timeout cannot be less than 0");
- this.timeOutMillis = timeOutMillis;
- return this;
- }
-
- /**
- *
- * @param disable if set to true we will not attempt to read from /proc/net/arp
- * directly. This avoids any Android 10 permissions logs appearing.
- */
- public void setDisableProcNetMethod(boolean disable) {
- this.disableProcNetMethod = disableProcNetMethod;
- }
-
- /**
- * Cancel a running scan
- */
- public void cancel() {
- this.cancelled = true;
- }
-
- /**
- * Starts the scan to find other devices on the subnet
- *
- * @param listener - to pass on the results
- * @return this object so we can call cancel on it if needed
- */
- public SubnetDevices findDevices(final OnSubnetDeviceFound listener) {
-
- this.listener = listener;
-
- cancelled = false;
- devicesFound = new ArrayList<>();
-
- new Thread(new Runnable() {
- @Override
- public void run() {
-
- // Load mac addresses into cache var (to avoid hammering the /proc/net/arp file when
- // lots of devices are found on the network.
- ipMacHashMap = disableProcNetMethod ? ARPInfo.getAllIPandMACAddressesFromIPSleigh() : ARPInfo.getAllIPAndMACAddressesInARPCache();
-
- ExecutorService executor = Executors.newFixedThreadPool(noThreads);
-
- for (final String add : addresses) {
- Runnable worker = new SubnetDeviceFinderRunnable(add);
- executor.execute(worker);
- }
-
- // This will make the executor accept no new threads
- // and finish all existing threads in the queue
- executor.shutdown();
- // Wait until all threads are finish
- try {
- executor.awaitTermination(1, TimeUnit.HOURS);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- // Loop over devices found and add in the MAC addresses if missing.
- // We do this after scanning for all devices as /proc/net/arp may add info
- // because of the scan.
- ipMacHashMap = disableProcNetMethod ? ARPInfo.getAllIPandMACAddressesFromIPSleigh() : ARPInfo.getAllIPAndMACAddressesInARPCache();
- for (Device device : devicesFound) {
- if (device.mac == null && ipMacHashMap.containsKey(device.ip)) {
- device.mac = ipMacHashMap.get(device.ip);
- }
- }
-
-
- listener.onFinished(devicesFound);
-
- }
- }).start();
-
- return this;
- }
-
- private synchronized void subnetDeviceFound(Device device) {
- devicesFound.add(device);
- listener.onDeviceFound(device);
- }
-
- public class SubnetDeviceFinderRunnable implements Runnable {
- private final String address;
-
- SubnetDeviceFinderRunnable(String address) {
- this.address = address;
- }
-
- @Override
- public void run() {
-
- if (cancelled) return;
-
- try {
- InetAddress ia = InetAddress.getByName(address);
- PingResult pingResult = Ping.onAddress(ia).setTimeOutMillis(timeOutMillis).doPing();
- if (pingResult.isReachable) {
- Device device = new Device(ia);
-
- // Add the device MAC address if it is in the cache
- if (ipMacHashMap.containsKey(ia.getHostAddress())) {
- device.mac = ipMacHashMap.get(ia.getHostAddress());
- }
-
- device.time = pingResult.timeTaken;
- subnetDeviceFound(device);
- }
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- }
- }
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.kt b/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.kt
new file mode 100644
index 0000000..fb4ec9a
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/SubnetDevices.kt
@@ -0,0 +1,213 @@
+package com.stealthcopter.networktools
+
+import com.stealthcopter.networktools.ARPInfo.allIPAddressesInARPCache
+import com.stealthcopter.networktools.ARPInfo.allIPAndMACAddressesInARPCache
+import com.stealthcopter.networktools.ARPInfo.allIPandMACAddressesFromIPSleigh
+import com.stealthcopter.networktools.IPTools.isIPv4Address
+import com.stealthcopter.networktools.IPTools.localIPv4Address
+import com.stealthcopter.networktools.Ping.Companion.onAddress
+import com.stealthcopter.networktools.subnet.Device
+import java.net.InetAddress
+import java.net.UnknownHostException
+import java.util.concurrent.Executors
+import java.util.concurrent.TimeUnit
+
+class SubnetDevices // This class is not to be instantiated
+private constructor() {
+ private var noThreads = 100
+ private var addresses: ArrayList? = null
+ private var devicesFound: ArrayList? = null
+ private var listener: OnSubnetDeviceFound? = null
+ private var timeOutMillis = 2500
+ private var cancelled = false
+ private var disableProcNetMethod = false
+ private var ipMacHashMap: HashMap? = null
+
+ interface OnSubnetDeviceFound {
+ fun onDeviceFound(device: Device?)
+ fun onFinished(devicesFound: ArrayList?)
+ }
+
+ /**
+ * @param noThreads set the number of threads to work with, note we default to a large number
+ * as these requests are network heavy not cpu heavy.
+ *
+ * @throws IllegalArgumentException - if invalid number of threads requested
+ *
+ * @return - this for chaining
+ */
+ @Throws(IllegalArgumentException::class)
+ fun setNoThreads(noThreads: Int): SubnetDevices {
+ require(noThreads >= 1) { "Cannot have less than 1 thread" }
+ this.noThreads = noThreads
+ return this
+ }
+
+ /**
+ * Sets the timeout for each address we try to ping
+ *
+ * @param timeOutMillis - timeout in milliseconds for each ping
+ *
+ * @return this object to allow chaining
+ *
+ * @throws IllegalArgumentException - if timeout is less than zero
+ */
+ @Throws(IllegalArgumentException::class)
+ fun setTimeOutMillis(timeOutMillis: Int): SubnetDevices {
+ require(timeOutMillis >= 0) { "Timeout cannot be less than 0" }
+ this.timeOutMillis = timeOutMillis
+ return this
+ }
+
+ /**
+ *
+ * @param disable if set to true we will not attempt to read from /proc/net/arp
+ * directly. This avoids any Android 10 permissions logs appearing.
+ */
+ fun setDisableProcNetMethod(disable: Boolean) {
+ disableProcNetMethod = disableProcNetMethod
+ }
+
+ /**
+ * Cancel a running scan
+ */
+ fun cancel() {
+ cancelled = true
+ }
+
+ /**
+ * Starts the scan to find other devices on the subnet
+ *
+ * @param listener - to pass on the results
+ * @return this object so we can call cancel on it if needed
+ */
+ fun findDevices(listener: OnSubnetDeviceFound): SubnetDevices {
+ this.listener = listener
+ cancelled = false
+ devicesFound = ArrayList()
+ Thread { // Load mac addresses into cache var (to avoid hammering the /proc/net/arp file when
+ // lots of devices are found on the network.
+ ipMacHashMap =
+ if (disableProcNetMethod) allIPandMACAddressesFromIPSleigh else allIPAndMACAddressesInARPCache
+ val executor = Executors.newFixedThreadPool(noThreads)
+ for (add in addresses!!) {
+ val worker: Runnable = SubnetDeviceFinderRunnable(add)
+ executor.execute(worker)
+ }
+
+ // This will make the executor accept no new threads
+ // and finish all existing threads in the queue
+ executor.shutdown()
+ // Wait until all threads are finish
+ try {
+ executor.awaitTermination(1, TimeUnit.HOURS)
+ } catch (e: InterruptedException) {
+ e.printStackTrace()
+ }
+
+ // Loop over devices found and add in the MAC addresses if missing.
+ // We do this after scanning for all devices as /proc/net/arp may add info
+ // because of the scan.
+ ipMacHashMap =
+ if (disableProcNetMethod) allIPandMACAddressesFromIPSleigh else allIPAndMACAddressesInARPCache
+ for (device in devicesFound!!) {
+ if (device.mac == null && ipMacHashMap!!.containsKey(device.ip)) {
+ device.mac = ipMacHashMap!![device.ip]
+ }
+ }
+ listener.onFinished(devicesFound)
+ }.start()
+ return this
+ }
+
+ @Synchronized
+ private fun subnetDeviceFound(device: Device) {
+ devicesFound!!.add(device)
+ listener!!.onDeviceFound(device)
+ }
+
+ inner class SubnetDeviceFinderRunnable internal constructor(private val address: String?) :
+ Runnable {
+ override fun run() {
+ if (cancelled) return
+ try {
+ val ia = InetAddress.getByName(address)
+ val pingResult = onAddress(ia).setTimeOutMillis(timeOutMillis).doPing()
+ if (pingResult.isReachable) {
+ val device = Device(ia)
+
+ // Add the device MAC address if it is in the cache
+ if (ipMacHashMap!!.containsKey(ia.hostAddress)) {
+ device.mac = ipMacHashMap!![ia.hostAddress]
+ }
+ device.time = pingResult.timeTaken
+ subnetDeviceFound(device)
+ }
+ } catch (e: UnknownHostException) {
+ e.printStackTrace()
+ }
+ }
+ }
+
+ companion object {
+ /**
+ * Find devices on the subnet working from the local device ip address
+ *
+ * @return - this for chaining
+ */
+ fun fromLocalAddress(): SubnetDevices {
+ val ipv4 = localIPv4Address
+ ?: throw IllegalAccessError("Could not access local ip address")
+ return fromIPAddress(ipv4.hostAddress)
+ }
+
+ /**
+ * @param inetAddress - an ip address in the subnet
+ *
+ * @return - this for chaining
+ */
+ fun fromIPAddress(inetAddress: InetAddress): SubnetDevices {
+ return fromIPAddress(inetAddress.hostAddress)
+ }
+
+ /**
+ * @param ipAddress - the ipAddress string of any device in the subnet i.e. "192.168.0.1"
+ * the final part will be ignored
+ *
+ * @return - this for chaining
+ */
+ fun fromIPAddress(ipAddress: String): SubnetDevices {
+ require(isIPv4Address(ipAddress)) { "Invalid IP Address" }
+ val segment = ipAddress.substring(0, ipAddress.lastIndexOf(".") + 1)
+ val subnetDevice = SubnetDevices()
+ subnetDevice.addresses = ArrayList()
+
+ // Get addresses from ARP Info first as they are likely to be reachable
+ for (ip in allIPAddressesInARPCache) {
+ if (ip.startsWith(segment)) {
+ subnetDevice.addresses!!.add(ip)
+ }
+ }
+
+ // Add all missing addresses in subnet
+ for (j in 0..254) {
+ if (!subnetDevice.addresses!!.contains(segment + j)) {
+ subnetDevice.addresses!!.add(segment + j)
+ }
+ }
+ return subnetDevice
+ }
+
+ /**
+ * @param ipAddresses - the ipAddresses of devices to be checked
+ *
+ * @return - this for chaining
+ */
+ fun fromIPList(ipAddresses: List?): SubnetDevices {
+ val subnetDevice = SubnetDevices()
+ subnetDevice.addresses = ArrayList()
+ subnetDevice.addresses!!.addAll(ipAddresses!!)
+ return subnetDevice
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.java b/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.java
deleted file mode 100644
index 92dc4d5..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.java
+++ /dev/null
@@ -1,237 +0,0 @@
-package com.stealthcopter.networktools;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-
-/**
- *
- * Tested this and it wakes my computer up :)
- *
- * Ref: http://www.jibble.org/wake-on-lan/
- */
-public class WakeOnLan {
-
- public static final int DEFAULT_PORT = 9;
- public static final int DEFAULT_TIMEOUT_MILLIS = 10000;
- public static final int DEFAULT_NO_PACKETS = 5;
-
- private String ipStr;
- private InetAddress inetAddress;
- private String macStr;
- private int port = DEFAULT_PORT;
- private int timeoutMillis = DEFAULT_TIMEOUT_MILLIS;
- private int noPackets = DEFAULT_NO_PACKETS;
-
- public interface WakeOnLanListener {
- void onSuccess();
-
- void onError(Exception e);
- }
-
- // This class is not to be instantiated
- private WakeOnLan() {
- }
-
- /**
- * Set the ip address to wake
- *
- * @param ipStr - IP Address to be woke
- * @return this object to allow chaining
- */
- public static WakeOnLan onIp(String ipStr) {
- WakeOnLan wakeOnLan = new WakeOnLan();
- wakeOnLan.ipStr = ipStr;
- return wakeOnLan;
- }
-
-
- /**
- * Set the address to wake
- *
- * @param inetAddress - InetAddress to be woke
- * @return this object to allow chaining
- */
- public static WakeOnLan onAddress(InetAddress inetAddress) {
- WakeOnLan wakeOnLan = new WakeOnLan();
- wakeOnLan.inetAddress = inetAddress;
- return wakeOnLan;
- }
-
-
- /**
- * Set the mac address of the device to wake
- *
- * @param macStr - The MAC address of the device to be woken (Required)
- * @return this object to allow chaining
- */
- public WakeOnLan withMACAddress(String macStr) {
- if (macStr == null) throw new NullPointerException("MAC Cannot be null");
- this.macStr = macStr;
- return this;
- }
-
-
- /**
- * Sets the port to send the packet to, default is 9
- *
- * @param port - the port for the wol packet
- * @return this object to allow chaining
- */
- public WakeOnLan setPort(int port) {
- if (port <= 0 || port > 65535) throw new IllegalArgumentException("Invalid port " + port);
- this.port = port;
- return this;
- }
-
-
- /**
- * Sets the number of packets to send, this is to overcome the flakiness of networks
- *
- * @param noPackets - the numbe of packets to send
- * @return this object to allow chaining
- */
- public WakeOnLan setNoPackets(int noPackets) {
- if (noPackets <= 0)
- throw new IllegalArgumentException("Invalid number of packets to send " + noPackets);
- this.noPackets = noPackets;
- return this;
- }
-
- /**
- * Sets the number milliseconds for the timeout on the socket send
- *
- * @param timeoutMillis - the timeout in milliseconds
- * @return this object to allow chaining
- */
- public WakeOnLan setTimeout(int timeoutMillis) {
- if (timeoutMillis <= 0)
- throw new IllegalArgumentException("Timeout cannot be less than zero");
- this.timeoutMillis = timeoutMillis;
- return this;
- }
-
-
- /**
- * Synchronous call of the wake method. Note that this is a network request and should not be
- * performed on the UI thread
- *
- * @throws IOException - Thrown from socket errors
- */
- public void wake() throws IOException {
-
- if (ipStr == null && inetAddress == null) {
- throw new IllegalArgumentException("You must declare ip address or supply an inetaddress");
- }
-
- if (macStr == null) {
- throw new NullPointerException("You did not supply a mac address with withMac(...)");
- }
-
- if (ipStr != null) {
- sendWakeOnLan(ipStr, macStr, port, timeoutMillis, noPackets);
- } else {
- sendWakeOnLan(inetAddress, macStr, port, timeoutMillis, noPackets);
- }
- }
-
-
- /**
- * Asynchronous call of the wake method. This will be performed on the background thread
- * and optionally fire a listener when complete, or when an error occurs
- *
- * @param wakeOnLanListener - listener to call on result
- */
- public void wake(final WakeOnLanListener wakeOnLanListener) {
-
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- wake();
- if (wakeOnLanListener != null) wakeOnLanListener.onSuccess();
- } catch (IOException e) {
- if (wakeOnLanListener != null) wakeOnLanListener.onError(e);
- }
-
- }
- });
-
- thread.start();
- }
-
- /**
- * Send a Wake-On-Lan packet to port 9 using default timeout of 10s
- *
- * @param ipStr - IP String to send to
- * @param macStr - MAC address to wake up
- *
- * @throws IllegalArgumentException - invalid ip or mac
- * @throws IOException - error sending packet
- */
- public static void sendWakeOnLan(String ipStr, String macStr) throws IllegalArgumentException, IOException {
- sendWakeOnLan(ipStr, macStr, DEFAULT_PORT, DEFAULT_TIMEOUT_MILLIS, DEFAULT_NO_PACKETS);
- }
-
- /**
- * Send a Wake-On-Lan packet
- *
- * @param ipStr - IP String to send wol packet to
- * @param macStr - MAC address to wake up
- * @param port - port to send packet to
- * @param timeoutMillis - timeout (millis)
- * @param packets - number of packets to send
- *
- * @throws IllegalArgumentException - invalid ip or mac
- * @throws IOException - error sending packet
- */
- public static void sendWakeOnLan(final String ipStr, final String macStr, final int port, final int timeoutMillis, final int packets) throws IllegalArgumentException, IOException {
- if (ipStr == null) throw new IllegalArgumentException("Address cannot be null");
- InetAddress address = InetAddress.getByName(ipStr);
- sendWakeOnLan(address, macStr, port, timeoutMillis, packets);
- }
-
- /**
- * Send a Wake-On-Lan packet
- *
- * @param address - InetAddress to send wol packet to
- * @param macStr - MAC address to wake up
- * @param port - port to send packet to
- * @param timeoutMillis - timeout (millis)
- * @param packets - number of packets to send
- *
- * @throws IllegalArgumentException - invalid ip or mac
- * @throws IOException - error sending packet
- */
- public static void sendWakeOnLan(final InetAddress address, final String macStr, final int port, final int timeoutMillis, final int packets) throws IllegalArgumentException, IOException {
- if (address == null) throw new IllegalArgumentException("Address cannot be null");
- if (macStr == null) throw new IllegalArgumentException("MAC Address cannot be null");
- if (port <= 0 || port > 65535) throw new IllegalArgumentException("Invalid port " + port);
- if (packets <= 0)
- throw new IllegalArgumentException("Invalid number of packets to send " + packets);
-
- byte[] macBytes = MACTools.getMacBytes(macStr);
- byte[] bytes = new byte[6 + 16 * macBytes.length];
- for (int i = 0; i < 6; i++) {
- bytes[i] = (byte) 0xff;
- }
- for (int i = 6; i < bytes.length; i += macBytes.length) {
- System.arraycopy(macBytes, 0, bytes, i, macBytes.length);
- }
-
- DatagramPacket packet = new DatagramPacket(bytes, bytes.length, address, port);
-
- // Wake on lan is unreliable so best to send the packet a few times
- for (int i = 0; i < packets; i++) {
- DatagramSocket socket = new DatagramSocket();
-
- socket.setSoTimeout(timeoutMillis);
-
- socket.send(packet);
- socket.close();
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.kt b/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.kt
new file mode 100644
index 0000000..5dda2d4
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/WakeOnLan.kt
@@ -0,0 +1,224 @@
+package com.stealthcopter.networktools
+
+import com.stealthcopter.networktools.MACTools.getMacBytes
+import java.io.IOException
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+
+/**
+ *
+ * Tested this and it wakes my computer up :)
+ *
+ * Ref: http://www.jibble.org/wake-on-lan/
+ */
+class WakeOnLan // This class is not to be instantiated
+private constructor() {
+ private var ipStr: String? = null
+ private var inetAddress: InetAddress? = null
+ private var macStr: String? = null
+ private var port = DEFAULT_PORT
+ private var timeoutMillis = DEFAULT_TIMEOUT_MILLIS
+ private var noPackets = DEFAULT_NO_PACKETS
+
+ interface WakeOnLanListener {
+ fun onSuccess()
+ fun onError(e: Exception?)
+ }
+
+ /**
+ * Set the mac address of the device to wake
+ *
+ * @param macStr - The MAC address of the device to be woken (Required)
+ * @return this object to allow chaining
+ */
+ fun withMACAddress(macStr: String?): WakeOnLan {
+ if (macStr == null) throw NullPointerException("MAC Cannot be null")
+ this.macStr = macStr
+ return this
+ }
+
+ /**
+ * Sets the port to send the packet to, default is 9
+ *
+ * @param port - the port for the wol packet
+ * @return this object to allow chaining
+ */
+ fun setPort(port: Int): WakeOnLan {
+ require(!(port <= 0 || port > 65535)) { "Invalid port $port" }
+ this.port = port
+ return this
+ }
+
+ /**
+ * Sets the number of packets to send, this is to overcome the flakiness of networks
+ *
+ * @param noPackets - the numbe of packets to send
+ * @return this object to allow chaining
+ */
+ fun setNoPackets(noPackets: Int): WakeOnLan {
+ require(noPackets > 0) { "Invalid number of packets to send $noPackets" }
+ this.noPackets = noPackets
+ return this
+ }
+
+ /**
+ * Sets the number milliseconds for the timeout on the socket send
+ *
+ * @param timeoutMillis - the timeout in milliseconds
+ * @return this object to allow chaining
+ */
+ fun setTimeout(timeoutMillis: Int): WakeOnLan {
+ require(timeoutMillis > 0) { "Timeout cannot be less than zero" }
+ this.timeoutMillis = timeoutMillis
+ return this
+ }
+
+ /**
+ * Synchronous call of the wake method. Note that this is a network request and should not be
+ * performed on the UI thread
+ *
+ * @throws IOException - Thrown from socket errors
+ */
+ @Throws(IOException::class)
+ fun wake() {
+ require(!(ipStr == null && inetAddress == null)) { "You must declare ip address or supply an inetaddress" }
+ if (macStr == null) {
+ throw NullPointerException("You did not supply a mac address with withMac(...)")
+ }
+ if (ipStr != null) {
+ sendWakeOnLan(ipStr, macStr, port, timeoutMillis, noPackets)
+ } else {
+ sendWakeOnLan(inetAddress, macStr, port, timeoutMillis, noPackets)
+ }
+ }
+
+ /**
+ * Asynchronous call of the wake method. This will be performed on the background thread
+ * and optionally fire a listener when complete, or when an error occurs
+ *
+ * @param wakeOnLanListener - listener to call on result
+ */
+ fun wake(wakeOnLanListener: WakeOnLanListener?) {
+ val thread = Thread {
+ try {
+ wake()
+ wakeOnLanListener?.onSuccess()
+ } catch (e: IOException) {
+ wakeOnLanListener?.onError(e)
+ }
+ }
+ thread.start()
+ }
+
+ companion object {
+ const val DEFAULT_PORT = 9
+ const val DEFAULT_TIMEOUT_MILLIS = 10000
+ const val DEFAULT_NO_PACKETS = 5
+
+ /**
+ * Set the ip address to wake
+ *
+ * @param ipStr - IP Address to be woke
+ * @return this object to allow chaining
+ */
+ fun onIp(ipStr: String?): WakeOnLan {
+ val wakeOnLan = WakeOnLan()
+ wakeOnLan.ipStr = ipStr
+ return wakeOnLan
+ }
+
+ /**
+ * Set the address to wake
+ *
+ * @param inetAddress - InetAddress to be woke
+ * @return this object to allow chaining
+ */
+ fun onAddress(inetAddress: InetAddress?): WakeOnLan {
+ val wakeOnLan = WakeOnLan()
+ wakeOnLan.inetAddress = inetAddress
+ return wakeOnLan
+ }
+ /**
+ * Send a Wake-On-Lan packet
+ *
+ * @param ipStr - IP String to send wol packet to
+ * @param macStr - MAC address to wake up
+ * @param port - port to send packet to
+ * @param timeoutMillis - timeout (millis)
+ * @param packets - number of packets to send
+ *
+ * @throws IllegalArgumentException - invalid ip or mac
+ * @throws IOException - error sending packet
+ */
+ /**
+ * Send a Wake-On-Lan packet to port 9 using default timeout of 10s
+ *
+ * @param ipStr - IP String to send to
+ * @param macStr - MAC address to wake up
+ *
+ * @throws IllegalArgumentException - invalid ip or mac
+ * @throws IOException - error sending packet
+ */
+ @JvmOverloads
+ @Throws(IllegalArgumentException::class, IOException::class)
+ fun sendWakeOnLan(
+ ipStr: String?,
+ macStr: String?,
+ port: Int = DEFAULT_PORT,
+ timeoutMillis: Int = DEFAULT_TIMEOUT_MILLIS,
+ packets: Int = DEFAULT_NO_PACKETS
+ ) {
+ requireNotNull(ipStr) { "Address cannot be null" }
+ val address = InetAddress.getByName(ipStr)
+ sendWakeOnLan(address, macStr, port, timeoutMillis, packets)
+ }
+
+ /**
+ * Send a Wake-On-Lan packet
+ *
+ * @param address - InetAddress to send wol packet to
+ * @param macStr - MAC address to wake up
+ * @param port - port to send packet to
+ * @param timeoutMillis - timeout (millis)
+ * @param packets - number of packets to send
+ *
+ * @throws IllegalArgumentException - invalid ip or mac
+ * @throws IOException - error sending packet
+ */
+ @Throws(IllegalArgumentException::class, IOException::class)
+ fun sendWakeOnLan(
+ address: InetAddress?,
+ macStr: String?,
+ port: Int,
+ timeoutMillis: Int,
+ packets: Int
+ ) {
+ requireNotNull(address) { "Address cannot be null" }
+ requireNotNull(macStr) { "MAC Address cannot be null" }
+ require(!(port <= 0 || port > 65535)) { "Invalid port $port" }
+ require(packets > 0) { "Invalid number of packets to send $packets" }
+ val macBytes = getMacBytes(macStr)
+ val bytes = ByteArray(6 + 16 * macBytes.size)
+ for (i in 0..5) {
+ bytes[i] = 0xff.toByte()
+ }
+ run {
+ var i = 6
+ while (i < bytes.size) {
+ System.arraycopy(macBytes, 0, bytes, i, macBytes.size)
+ i += macBytes.size
+ }
+ }
+ val packet = DatagramPacket(bytes, bytes.size, address, port)
+
+ // Wake on lan is unreliable so best to send the packet a few times
+ for (i in 0 until packets) {
+ val socket = DatagramSocket()
+ socket.soTimeout = timeoutMillis
+ socket.send(packet)
+ socket.close()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.java b/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.java
deleted file mode 100644
index c9163fd..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.stealthcopter.networktools.ping;
-
-import com.stealthcopter.networktools.IPTools;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.InetAddress;
-
-public class PingNative {
-
- // This class is not to be instantiated
- private PingNative() {
- }
-
- public static PingResult ping(InetAddress host, PingOptions pingOptions) throws IOException, InterruptedException {
- PingResult pingResult = new PingResult(host);
-
- if (host == null) {
- pingResult.isReachable = false;
- return pingResult;
- }
-
- StringBuilder echo = new StringBuilder();
- Runtime runtime = Runtime.getRuntime();
-
- int timeoutSeconds = Math.max(pingOptions.getTimeoutMillis() / 1000, 1);
- int ttl = Math.max(pingOptions.getTimeToLive(), 1);
-
- String address = host.getHostAddress();
- String pingCommand = "ping";
-
- if (address != null) {
- if (IPTools.isIPv6Address(address)) {
- // If we detect this is a ipv6 address, change the to the ping6 binary
- pingCommand = "ping6";
- } else if (!IPTools.isIPv4Address(address)) {
- // Address doesn't look to be ipv4 or ipv6, but we could be mistaken
-
- }
- } else {
- // Not sure if getHostAddress ever returns null, but if it does, use the hostname as a fallback
- address = host.getHostName();
- }
-
- Process proc = runtime.exec(pingCommand + " -c 1 -W " + timeoutSeconds + " -t " + ttl + " " + address);
- proc.waitFor();
- int exit = proc.exitValue();
- String pingError;
- switch (exit) {
- case 0:
- InputStreamReader reader = new InputStreamReader(proc.getInputStream());
- BufferedReader buffer = new BufferedReader(reader);
- String line;
- while ((line = buffer.readLine()) != null) {
- echo.append(line).append("\n");
- }
- return getPingStats(pingResult, echo.toString());
- case 1:
- pingError = "failed, exit = 1";
- break;
- default:
- pingError = "error, exit = 2";
- break;
- }
- pingResult.error = pingError;
- proc.destroy();
- return pingResult;
- }
-
- /**
- * getPingStats interprets the text result of a Linux activity_ping command
- *
- * Set pingError on error and return null
- *
- * http://en.wikipedia.org/wiki/Ping
- *
- * PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
- * 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.251 ms
- * 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.294 ms
- * 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.295 ms
- * 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.300 ms
- *
- * --- 127.0.0.1 activity_ping statistics ---
- * 4 packets transmitted, 4 received, 0% packet loss, time 0ms
- * rtt min/avg/max/mdev = 0.251/0.285/0.300/0.019 ms
- *
- * PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
- *
- * --- 192.168.0.2 activity_ping statistics ---
- * 1 packets transmitted, 0 received, 100% packet loss, time 0ms
- *
- * # activity_ping 321321.
- * activity_ping: unknown host 321321.
- *
- * 1. Check if output contains 0% packet loss : Branch to success - Get stats
- * 2. Check if output contains 100% packet loss : Branch to fail - No stats
- * 3. Check if output contains 25% packet loss : Branch to partial success - Get stats
- * 4. Check if output contains "unknown host"
- *
- * @param pingResult - the current ping result
- * @param s - result from ping command
- *
- * @return The ping result
- */
- public static PingResult getPingStats(PingResult pingResult, String s) {
- String pingError;
- if (s.contains("0% packet loss")) {
- int start = s.indexOf("/mdev = ");
- int end = s.indexOf(" ms\n", start);
- pingResult.fullString = s;
- if (start == -1 || end == -1) {
- pingError = "Error: " + s;
- } else {
- s = s.substring(start + 8, end);
- String stats[] = s.split("/");
- pingResult.isReachable = true;
- pingResult.result = s;
- pingResult.timeTaken = Float.parseFloat(stats[1]);
- return pingResult;
- }
- } else if (s.contains("100% packet loss")) {
- pingError = "100% packet loss";
- } else if (s.contains("% packet loss")) {
- pingError = "partial packet loss";
- } else if (s.contains("unknown host")) {
- pingError = "unknown host";
- } else {
- pingError = "unknown error in getPingStats";
- }
- pingResult.error = pingError;
- return pingResult;
- }
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.kt b/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.kt
new file mode 100644
index 0000000..9719e1c
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/ping/PingNative.kt
@@ -0,0 +1,122 @@
+package com.stealthcopter.networktools.ping
+
+import com.stealthcopter.networktools.IPTools
+import java.io.BufferedReader
+import java.io.IOException
+import java.io.InputStreamReader
+import java.net.InetAddress
+import kotlin.math.max
+
+object PingNative {
+ @JvmStatic
+ @Throws(IOException::class, InterruptedException::class)
+ fun ping(host: InetAddress?, pingOptions: PingOptions): PingResult {
+ val pingResult = host?.let { PingResult(it) }
+ if (host == null) {
+ pingResult?.isReachable = false
+ return pingResult!!
+ }
+ val echo = StringBuilder()
+ val runtime = Runtime.getRuntime()
+ val timeoutSeconds = max(pingOptions.getTimeoutMillis() / 1000, 1)
+ val ttl = max(pingOptions.getTimeToLive(), 1)
+ var address = host.hostAddress
+ var pingCommand = "ping"
+ if (address != null) {
+ if (IPTools.isIPv6Address(address)) {
+ // If we detect this is a ipv6 address, change the to the ping6 binary
+ pingCommand = "ping6"
+ } else if (!IPTools.isIPv4Address(address)) {
+ // Address doesn't look to be ipv4 or ipv6, but we could be mistaken
+ }
+ } else {
+ // Not sure if getHostAddress ever returns null, but if it does, use the hostname as a fallback
+ address = host.hostName
+ }
+ val proc = runtime.exec("$pingCommand -c 1 -W $timeoutSeconds -t $ttl $address")
+ proc.waitFor()
+ val exit = proc.exitValue()
+ val pingError: String
+ when (exit) {
+ 0 -> {
+ val reader = InputStreamReader(proc.inputStream)
+ val buffer = BufferedReader(reader)
+ var line: String?
+ while (buffer.readLine().also { line = it } != null) {
+ echo.append(line).append("\n")
+ }
+ return pingResult?.let { getPingStats(it, echo.toString()) }!!
+ }
+ 1 -> pingError = "failed, exit = 1"
+ else -> pingError = "error, exit = 2"
+ }
+ pingResult?.error = pingError
+ proc.destroy()
+ return pingResult!!
+ }
+
+ /**
+ * getPingStats interprets the text result of a Linux activity_ping command
+ *
+ * Set pingError on error and return null
+ *
+ * http://en.wikipedia.org/wiki/Ping
+ *
+ * PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
+ * 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.251 ms
+ * 64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.294 ms
+ * 64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.295 ms
+ * 64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.300 ms
+ *
+ * --- 127.0.0.1 activity_ping statistics ---
+ * 4 packets transmitted, 4 received, 0% packet loss, time 0ms
+ * rtt min/avg/max/mdev = 0.251/0.285/0.300/0.019 ms
+ *
+ * PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
+ *
+ * --- 192.168.0.2 activity_ping statistics ---
+ * 1 packets transmitted, 0 received, 100% packet loss, time 0ms
+ *
+ * # activity_ping 321321.
+ * activity_ping: unknown host 321321.
+ *
+ * 1. Check if output contains 0% packet loss : Branch to success - Get stats
+ * 2. Check if output contains 100% packet loss : Branch to fail - No stats
+ * 3. Check if output contains 25% packet loss : Branch to partial success - Get stats
+ * 4. Check if output contains "unknown host"
+ *
+ * @param pingResult - the current ping result
+ * @param s - result from ping command
+ *
+ * @return The ping result
+ */
+ fun getPingStats(pingResult: PingResult, s: String): PingResult {
+ var s = s
+ val pingError: String
+ if (s.contains("0% packet loss")) {
+ val start = s.indexOf("/mdev = ")
+ val end = s.indexOf(" ms\n", start)
+ pingResult.fullString = s
+ if (start == -1 || end == -1) {
+ pingError = "Error: $s"
+ } else {
+ s = s.substring(start + 8, end)
+ val stats = s.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
+ pingResult.isReachable = true
+ pingResult.result = s
+ pingResult.timeTaken = stats[1].toFloat()
+ return pingResult
+ }
+ } else if (s.contains("100% packet loss")) {
+ pingError = "100% packet loss"
+ } else if (s.contains("% packet loss")) {
+ pingError = "partial packet loss"
+ } else if (s.contains("unknown host")) {
+ pingError = "unknown host"
+ } else {
+ pingError = "unknown error in getPingStats"
+ }
+ pingResult.error = pingError
+ return pingResult
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.java b/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.java
deleted file mode 100644
index 1051b40..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.stealthcopter.networktools.ping;
-
-public class PingOptions {
- private int timeoutMillis;
- private int timeToLive;
-
- public PingOptions() {
- timeToLive = 128;
- timeoutMillis = 1000;
- }
-
- public int getTimeoutMillis() {
- return timeoutMillis;
- }
-
- public void setTimeoutMillis(int timeoutMillis) {
- this.timeoutMillis = Math.max(timeoutMillis, 1000);
- }
-
- public int getTimeToLive() {
- return timeToLive;
- }
-
- public void setTimeToLive(int timeToLive) {
- this.timeToLive = Math.max(timeToLive, 1);
- }
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.kt b/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.kt
new file mode 100644
index 0000000..56035b5
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/ping/PingOptions.kt
@@ -0,0 +1,21 @@
+package com.stealthcopter.networktools.ping
+
+class PingOptions {
+ private var timeoutMillis = 1000
+ private var timeToLive = 128
+ fun getTimeoutMillis(): Int {
+ return timeoutMillis
+ }
+
+ fun setTimeoutMillis(timeoutMillis: Int) {
+ this.timeoutMillis = Math.max(timeoutMillis, 1000)
+ }
+
+ fun getTimeToLive(): Int {
+ return timeToLive
+ }
+
+ fun setTimeToLive(timeToLive: Int) {
+ this.timeToLive = Math.max(timeToLive, 1)
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.java b/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.java
deleted file mode 100644
index 673e7a2..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.stealthcopter.networktools.ping;
-
-import java.net.InetAddress;
-
-public class PingResult {
- public final InetAddress ia;
- public boolean isReachable;
- public String error = null;
- public float timeTaken;
- public String fullString;
- public String result;
-
- public PingResult(InetAddress ia) {
- this.ia = ia;
- }
-
- public boolean isReachable() {
- return isReachable;
- }
-
- public boolean hasError() {
- return error != null;
- }
-
- public float getTimeTaken() {
- return timeTaken;
- }
-
- public String getError() {
- return error;
- }
-
- public InetAddress getAddress() {
- return ia;
- }
-
- @Override
- public String toString() {
- return "PingResult{" +
- "ia=" + ia +
- ", isReachable=" + isReachable +
- ", error='" + error + '\'' +
- ", timeTaken=" + timeTaken +
- ", fullString='" + fullString + '\'' +
- ", result='" + result + '\'' +
- '}';
- }
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.kt b/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.kt
new file mode 100644
index 0000000..63a3d37
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/ping/PingResult.kt
@@ -0,0 +1,25 @@
+package com.stealthcopter.networktools.ping
+
+import java.net.InetAddress
+
+class PingResult(val address: InetAddress) {
+ var isReachable = false
+ var error: String? = null
+ var timeTaken = 0f
+ var fullString: String? = null
+ var result: String? = null
+ fun hasError(): Boolean {
+ return error != null
+ }
+
+ override fun toString(): String {
+ return "PingResult{" +
+ "ia=" + address +
+ ", isReachable=" + isReachable +
+ ", error='" + error + '\'' +
+ ", timeTaken=" + timeTaken +
+ ", fullString='" + fullString + '\'' +
+ ", result='" + result + '\'' +
+ '}'
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.java b/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.java
deleted file mode 100644
index e6d0978..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.stealthcopter.networktools.ping;
-
-import java.net.InetAddress;
-
-public class PingStats {
- private final InetAddress ia;
- private final long noPings;
- private final long packetsLost;
- private final float averageTimeTaken;
- private final float minTimeTaken;
- private final float maxTimeTaken;
- private final boolean isReachable;
-
- public PingStats(InetAddress ia, long noPings, long packetsLost, float totalTimeTaken, float minTimeTaken, float maxTimeTaken) {
- this.ia = ia;
- this.noPings = noPings;
- this.packetsLost = packetsLost;
- this.averageTimeTaken = totalTimeTaken / noPings;
- this.minTimeTaken = minTimeTaken;
- this.maxTimeTaken = maxTimeTaken;
- this.isReachable = noPings - packetsLost > 0;
- }
-
- public InetAddress getAddress() {
- return ia;
- }
-
- public long getNoPings() {
- return noPings;
- }
-
- public long getPacketsLost() {
- return packetsLost;
- }
-
- public float getAverageTimeTaken() {
- return averageTimeTaken;
- }
-
- public float getMinTimeTaken() {
- return minTimeTaken;
- }
-
- public float getMaxTimeTaken() {
- return maxTimeTaken;
- }
-
- public boolean isReachable() {
- return isReachable;
- }
-
- public long getAverageTimeTakenMillis() {
- return (long) (averageTimeTaken * 1000);
- }
-
- public long getMinTimeTakenMillis() {
- return (long) (minTimeTaken * 1000);
- }
-
- public long getMaxTimeTakenMillis() {
- return (long) (maxTimeTaken * 1000);
- }
-
- @Override
- public String toString() {
- return "PingStats{" +
- "ia=" + ia +
- ", noPings=" + noPings +
- ", packetsLost=" + packetsLost +
- ", averageTimeTaken=" + averageTimeTaken +
- ", minTimeTaken=" + minTimeTaken +
- ", maxTimeTaken=" + maxTimeTaken +
- '}';
- }
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.kt b/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.kt
new file mode 100644
index 0000000..fb60241
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/ping/PingStats.kt
@@ -0,0 +1,42 @@
+package com.stealthcopter.networktools.ping
+
+import java.net.InetAddress
+
+class PingStats(
+ val address: InetAddress,
+ val noPings: Long,
+ val packetsLost: Long,
+ totalTimeTaken: Float,
+ minTimeTaken: Float,
+ maxTimeTaken: Float
+) {
+ val averageTimeTaken: Float
+ val minTimeTaken: Float
+ val maxTimeTaken: Float
+ val isReachable: Boolean
+
+ init {
+ averageTimeTaken = totalTimeTaken / noPings
+ this.minTimeTaken = minTimeTaken
+ this.maxTimeTaken = maxTimeTaken
+ isReachable = noPings - packetsLost > 0
+ }
+
+ val averageTimeTakenMillis: Long
+ get() = (averageTimeTaken * 1000).toLong()
+ val minTimeTakenMillis: Long
+ get() = (minTimeTaken * 1000).toLong()
+ val maxTimeTakenMillis: Long
+ get() = (maxTimeTaken * 1000).toLong()
+
+ override fun toString(): String {
+ return "PingStats{" +
+ "ia=" + address +
+ ", noPings=" + noPings +
+ ", packetsLost=" + packetsLost +
+ ", averageTimeTaken=" + averageTimeTaken +
+ ", minTimeTaken=" + minTimeTaken +
+ ", maxTimeTaken=" + maxTimeTaken +
+ '}'
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.java b/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.java
deleted file mode 100644
index 4aeb800..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.stealthcopter.networktools.ping;
-
-import java.io.IOException;
-import java.net.InetAddress;
-
-public class PingTools {
-
- // This class is not to be instantiated
- private PingTools() {
- }
-
-
- /**
- * Perform a ping using the native ping tool and fall back to using java echo request
- * on failure.
- *
- * @param ia - address to ping
- * @param pingOptions - ping command options
- * @return - the ping results
- */
- public static PingResult doPing(InetAddress ia, PingOptions pingOptions) {
-
- // Try native ping first
- try {
- return PingTools.doNativePing(ia, pingOptions);
- } catch (InterruptedException e) {
- PingResult pingResult = new PingResult(ia);
- pingResult.isReachable = false;
- pingResult.error = "Interrupted";
- return pingResult;
- } catch (Exception ignored) {
- }
-
- // Fallback to java based ping
- return PingTools.doJavaPing(ia, pingOptions);
- }
-
-
- /**
- * Perform a ping using the native ping binary
- *
- * @param ia - address to ping
- * @param pingOptions - ping command options
- * @return - the ping results
- * @throws IOException - IO error running ping command
- * @throws InterruptedException - thread interrupt
- */
- public static PingResult doNativePing(InetAddress ia, PingOptions pingOptions) throws IOException, InterruptedException {
- return PingNative.ping(ia, pingOptions);
- }
-
- /**
- * Tries to reach this {@code InetAddress}. This method first tries to use
- * ICMP (ICMP ECHO REQUEST), falling back to a TCP connection
- * on port 7 (Echo) of the remote host.
- *
- * @param ia - address to ping
- * @param pingOptions - ping command options
- * @return - the ping results
- */
- public static PingResult doJavaPing(InetAddress ia, PingOptions pingOptions) {
- PingResult pingResult = new PingResult(ia);
-
- if (ia == null) {
- pingResult.isReachable = false;
- return pingResult;
- }
-
- try {
- long startTime = System.nanoTime();
- final boolean reached = ia.isReachable(null, pingOptions.getTimeToLive(), pingOptions.getTimeoutMillis());
- pingResult.timeTaken = (System.nanoTime() - startTime) / 1e6f;
- pingResult.isReachable = reached;
- if (!reached) pingResult.error = "Timed Out";
- } catch (IOException e) {
- pingResult.isReachable = false;
- pingResult.error = "IOException: " + e.getMessage();
- }
- return pingResult;
- }
-
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.kt b/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.kt
new file mode 100644
index 0000000..c24a780
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/ping/PingTools.kt
@@ -0,0 +1,76 @@
+package com.stealthcopter.networktools.ping
+
+import com.stealthcopter.networktools.ping.PingNative.ping
+import java.io.IOException
+import java.net.InetAddress
+
+object PingTools {
+ /**
+ * Perform a ping using the native ping tool and fall back to using java echo request
+ * on failure.
+ *
+ * @param ia - address to ping
+ * @param pingOptions - ping command options
+ * @return - the ping results
+ */
+ @JvmStatic
+ fun doPing(ia: InetAddress?, pingOptions: PingOptions): PingResult {
+
+ // Try native ping first
+ try {
+ return doNativePing(ia, pingOptions)
+ } catch (e: InterruptedException) {
+ val pingResult = PingResult(ia!!)
+ pingResult.isReachable = false
+ pingResult.error = "Interrupted"
+ return pingResult
+ } catch (ignored: Exception) {
+ }
+
+ // Fallback to java based ping
+ return doJavaPing(ia, pingOptions)
+ }
+
+ /**
+ * Perform a ping using the native ping binary
+ *
+ * @param ia - address to ping
+ * @param pingOptions - ping command options
+ * @return - the ping results
+ * @throws IOException - IO error running ping command
+ * @throws InterruptedException - thread interrupt
+ */
+ @Throws(IOException::class, InterruptedException::class)
+ fun doNativePing(ia: InetAddress?, pingOptions: PingOptions?): PingResult {
+ return ping(ia, pingOptions!!)
+ }
+
+ /**
+ * Tries to reach this `InetAddress`. This method first tries to use
+ * ICMP *(ICMP ECHO REQUEST)*, falling back to a TCP connection
+ * on port 7 (Echo) of the remote host.
+ *
+ * @param ia - address to ping
+ * @param pingOptions - ping command options
+ * @return - the ping results
+ */
+ fun doJavaPing(ia: InetAddress?, pingOptions: PingOptions): PingResult {
+ val pingResult = PingResult(ia!!)
+ if (ia == null) {
+ pingResult.isReachable = false
+ return pingResult
+ }
+ try {
+ val startTime = System.nanoTime()
+ val reached =
+ ia.isReachable(null, pingOptions.getTimeToLive(), pingOptions.getTimeoutMillis())
+ pingResult.timeTaken = (System.nanoTime() - startTime) / 1e6f
+ pingResult.isReachable = reached
+ if (!reached) pingResult.error = "Timed Out"
+ } catch (e: IOException) {
+ pingResult.isReachable = false
+ pingResult.error = "IOException: " + e.message
+ }
+ return pingResult
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.java b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.java
deleted file mode 100644
index f487c5c..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.stealthcopter.networktools.portscanning;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-
-public class PortScanTCP {
-
- // This class is not to be instantiated
- private PortScanTCP() {
- }
-
- /**
- * Check if a port is open with TCP
- *
- * @param ia - address to scan
- * @param portNo - port to scan
- * @param timeoutMillis - timeout
- * @return - true if port is open, false if not or unknown
- */
- public static boolean scanAddress(InetAddress ia, int portNo, int timeoutMillis) {
-
- Socket s = null;
- try {
- s = new Socket();
- s.connect(new InetSocketAddress(ia, portNo), timeoutMillis);
- return true;
- } catch (IOException e) {
- // Don't log anything as we are expecting a lot of these from closed ports.
- } finally {
- if (s != null) {
- try {
- s.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return false;
- }
-
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.kt b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.kt
new file mode 100644
index 0000000..87a92c2
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanTCP.kt
@@ -0,0 +1,36 @@
+package com.stealthcopter.networktools.portscanning
+
+import java.io.IOException
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.net.Socket
+
+object PortScanTCP {
+ /**
+ * Check if a port is open with TCP
+ *
+ * @param ia - address to scan
+ * @param portNo - port to scan
+ * @param timeoutMillis - timeout
+ * @return - true if port is open, false if not or unknown
+ */
+ fun scanAddress(ia: InetAddress?, portNo: Int, timeoutMillis: Int): Boolean {
+ var s: Socket? = null
+ try {
+ s = Socket()
+ s.connect(InetSocketAddress(ia, portNo), timeoutMillis)
+ return true
+ } catch (e: IOException) {
+ // Don't log anything as we are expecting a lot of these from closed ports.
+ } finally {
+ if (s != null) {
+ try {
+ s.close()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }
+ }
+ return false
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.java b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.java
deleted file mode 100644
index 1236832..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.stealthcopter.networktools.portscanning;
-
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.SocketTimeoutException;
-
-public class PortScanUDP {
-
- // This class is not to be instantiated
- private PortScanUDP() {
- }
-
- /**
- * Check if a port is open with UDP, note that this isn't reliable
- * as UDP will does not send ACKs
- *
- * @param ia - address to scan
- * @param portNo - port to scan
- * @param timeoutMillis - timeout
- * @return - true if port is open, false if not or unknown
- */
- public static boolean scanAddress(InetAddress ia, int portNo, int timeoutMillis) {
-
- try {
- byte[] bytes = new byte[128];
- DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
-
- DatagramSocket ds = new DatagramSocket();
- ds.setSoTimeout(timeoutMillis);
- ds.connect(ia, portNo);
- ds.send(dp);
- ds.isConnected();
- ds.receive(dp);
- ds.close();
-
- } catch (SocketTimeoutException e) {
- return true;
- } catch (Exception ignore) {
-
- }
-
- return false;
- }
-
-}
diff --git a/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.kt b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.kt
new file mode 100644
index 0000000..7bbfbf7
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/portscanning/PortScanUDP.kt
@@ -0,0 +1,35 @@
+package com.stealthcopter.networktools.portscanning
+
+import java.net.DatagramPacket
+import java.net.DatagramSocket
+import java.net.InetAddress
+import java.net.SocketTimeoutException
+
+object PortScanUDP {
+ /**
+ * Check if a port is open with UDP, note that this isn't reliable
+ * as UDP will does not send ACKs
+ *
+ * @param ia - address to scan
+ * @param portNo - port to scan
+ * @param timeoutMillis - timeout
+ * @return - true if port is open, false if not or unknown
+ */
+ fun scanAddress(ia: InetAddress?, portNo: Int, timeoutMillis: Int): Boolean {
+ try {
+ val bytes = ByteArray(128)
+ val dp = DatagramPacket(bytes, bytes.size)
+ val ds = DatagramSocket()
+ ds.soTimeout = timeoutMillis
+ ds.connect(ia, portNo)
+ ds.send(dp)
+ ds.isConnected
+ ds.receive(dp)
+ ds.close()
+ } catch (e: SocketTimeoutException) {
+ return true
+ } catch (ignore: Exception) {
+ }
+ return false
+ }
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/stealthcopter/networktools/subnet/Device.java b/library/src/main/java/com/stealthcopter/networktools/subnet/Device.java
deleted file mode 100644
index 98538db..0000000
--- a/library/src/main/java/com/stealthcopter/networktools/subnet/Device.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.stealthcopter.networktools.subnet;
-
-import java.net.InetAddress;
-
-public class Device {
- public String ip;
- public String hostname;
- public String mac;
- public float time = 0;
-
- public Device(InetAddress ip) {
- this.ip = ip.getHostAddress();
- this.hostname = ip.getCanonicalHostName();
- }
-
- @Override
- public String toString() {
- return "Device{" +
- "ip='" + ip + '\'' +
- ", hostname='" + hostname + '\'' +
- ", mac='" + mac + '\'' +
- ", time=" + time +
- '}';
- }
-}
-
diff --git a/library/src/main/java/com/stealthcopter/networktools/subnet/Device.kt b/library/src/main/java/com/stealthcopter/networktools/subnet/Device.kt
new file mode 100644
index 0000000..7f73f46
--- /dev/null
+++ b/library/src/main/java/com/stealthcopter/networktools/subnet/Device.kt
@@ -0,0 +1,27 @@
+package com.stealthcopter.networktools.subnet
+
+import java.net.InetAddress
+
+class Device(ip: InetAddress) {
+ @JvmField
+ var ip: String
+ var hostname: String
+ @JvmField
+ var mac: String? = null
+ @JvmField
+ var time = 0f
+
+ init {
+ this.ip = ip.hostAddress
+ hostname = ip.canonicalHostName
+ }
+
+ override fun toString(): String {
+ return "Device{" +
+ "ip='" + ip + '\'' +
+ ", hostname='" + hostname + '\'' +
+ ", mac='" + mac + '\'' +
+ ", time=" + time +
+ '}'
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.java b/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.java
deleted file mode 100644
index 7a31128..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.stealthcopter.networktools;
-
-import org.junit.Test;
-
-import static junit.framework.Assert.assertNull;
-
-/**
- * To work on unit tests, switch the Test Artifact in the Build Variants view.
- */
-public class ARPInfoTest {
-
- @Test
- public void nullIPsandMacsReturnNull() {
- assertNull(ARPInfo.getMACFromIPAddress(null));
- assertNull(ARPInfo.getIPAddressFromMAC(null));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidMACaddress() {
- ARPInfo.getIPAddressFromMAC("00:00:00:xx");
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.kt b/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.kt
new file mode 100644
index 0000000..efad747
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/ARPInfoTest.kt
@@ -0,0 +1,20 @@
+package com.stealthcopter.networktools
+
+import junit.framework.Assert
+import org.junit.Test
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+class ARPInfoTest {
+ @Test
+ fun nullIPsandMacsReturnNull() {
+ Assert.assertNull(ARPInfo.getMACFromIPAddress(null))
+ Assert.assertNull(ARPInfo.getIPAddressFromMAC(null))
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testIllegalArgumentThrownOnInvalidMACaddress() {
+ ARPInfo.getIPAddressFromMAC("00:00:00:xx")
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.java b/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.java
deleted file mode 100644
index 5200065..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.stealthcopter.networktools;
-
-import static org.hamcrest.CoreMatchers.is;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.List;
-
-import static org.junit.Assert.*;
-
-/**
- * Created by matthew on 03/11/17.
- */
-
-public class IPToolsTest {
-
-
- String[] getInvalidIpAddresses() {
- return new String[]{null, "beepbeep", "nope", "hello"};
- }
-
- String[] getIPv4Addresses() {
- return new String[]{"192.168.0.1", "127.0.0.1", "10.0.0.1",};
- }
-
- String[] getIPv6Addresses() {
- return new String[]{"2001:0db8:85a3:0000:0000:8a2e:0370:7334"};
- }
-
- String[] getIPv6AddressesHexCompresed() {
- return new String[]{"2001:db8:85a3::8a2e:370:7334", "2001::8a2e:370:7334", "2001:", "2001::2001"};
- }
-
- @Test
- public void testIsIPv4Address() {
- assertIPv4Address(getIPv4Addresses(), true);
- assertIPv4Address(getIPv6Addresses(), false);
- assertIPv4Address(getInvalidIpAddresses(), false);
- }
-
-
-
- @Test
- public void testIsIPv6Address() {
- assertIPv6Address(getIPv4Addresses(), false);
- assertIPv6Address(getIPv6Addresses(), true);
- assertIPv6Address(getInvalidIpAddresses(), false);
- }
-
- @Test
- public void testIsIPv6AddressesStandard() {
- assertIPv6StdAddress(getIPv4Addresses(), false);
- assertIPv6StdAddress(getIPv6Addresses(), true);
- assertIPv6StdAddress(getInvalidIpAddresses(), false);
- }
-
- @Test
- @Ignore // Recheck this, either test is broken or regex is wrong
- public void testIPv6HexCompressedAddress() {
- for (String address : getIPv6AddressesHexCompresed()) {
- assertTrue(IPTools.isIPv6HexCompressedAddress(address));
- }
- }
-
- @Test
- public void testGetLocalAddressReturnsLocalIP() {
- InetAddress test = IPTools.getLocalIPv4Address();
-
- assertNotNull(test);
-
- assertTrue(IPTools.isIpAddressLocalhost(test));
- assertTrue(IPTools.isIpAddressLocalNetwork(test));
- }
-
-
- @Test
- public void testGetAllLocalAddressReturnsLocalIP() {
- List test = IPTools.getLocalIPv4Addresses();
-
- for (InetAddress address : test) {
- System.out.println(address);
- assertNotNull(address);
-
- assertTrue(IPTools.isIpAddressLocalhost(address));
- assertTrue(IPTools.isIpAddressLocalNetwork(address));
- }
- }
-
- @Test
- public void testLocalAddresses() throws UnknownHostException {
- assertTrue(IPTools.isIpAddressLocalhost(InetAddress.getByName("127.0.0.1")));
- assertFalse(IPTools.isIpAddressLocalhost(InetAddress.getByName("8.8.8.8")));
- }
-
- @Test
- public void testLocalAddressesNetwork() throws UnknownHostException {
- assertFalse(IPTools.isIpAddressLocalNetwork(InetAddress.getByName("8.8.8.8")));
- }
-
- private void assertIPv4Address(String[] ips, boolean isIPv4Address) {
- for (String address : ips) {
- assertThat(IPTools.isIPv4Address(address), is(isIPv4Address));
- }
- }
-
- private void assertIPv6Address(String[] ips, boolean isIPv6Address) {
- for (String address : ips) {
- assertThat(IPTools.isIPv6Address(address), is(isIPv6Address));
- }
- }
-
- private void assertIPv6StdAddress(String[] ips, boolean isIPv6StdAddress) {
- for (String address : ips) {
- assertThat(IPTools.isIPv6StdAddress(address), is(isIPv6StdAddress));
- }
- }
-
-}
diff --git a/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.kt b/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.kt
new file mode 100644
index 0000000..c4fda6f
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/IPToolsTest.kt
@@ -0,0 +1,109 @@
+package com.stealthcopter.networktools
+
+import org.hamcrest.CoreMatchers
+import org.junit.Assert
+import org.junit.Ignore
+import org.junit.Test
+import java.net.InetAddress
+import java.net.UnknownHostException
+
+/**
+ * Created by matthew on 03/11/17.
+ */
+class IPToolsTest {
+ val invalidIpAddresses: Array
+ get() = arrayOf(null, "beepbeep", "nope", "hello")
+ val iPv4Addresses: Array
+ get() = arrayOf("192.168.0.1", "127.0.0.1", "10.0.0.1")
+ val iPv6Addresses: Array
+ get() = arrayOf("2001:0db8:85a3:0000:0000:8a2e:0370:7334")
+ val iPv6AddressesHexCompresed: Array
+ get() = arrayOf(
+ "2001:db8:85a3::8a2e:370:7334",
+ "2001::8a2e:370:7334",
+ "2001:",
+ "2001::2001"
+ )
+
+ @Test
+ fun testIsIPv4Address() {
+ assertIPv4Address(iPv4Addresses, true)
+ assertIPv4Address(iPv6Addresses, false)
+ assertIPv4Address(invalidIpAddresses, false)
+ }
+
+ @Test
+ fun testIsIPv6Address() {
+ assertIPv6Address(iPv4Addresses, false)
+ assertIPv6Address(iPv6Addresses, true)
+ assertIPv6Address(invalidIpAddresses, false)
+ }
+
+ @Test
+ fun testIsIPv6AddressesStandard() {
+ assertIPv6StdAddress(iPv4Addresses, false)
+ assertIPv6StdAddress(iPv6Addresses, true)
+ assertIPv6StdAddress(invalidIpAddresses, false)
+ }
+
+ @Test
+ @Ignore // Recheck this, either test is broken or regex is wrong
+ fun testIPv6HexCompressedAddress() {
+ for (address in iPv6AddressesHexCompresed) {
+ Assert.assertTrue(IPTools.isIPv6HexCompressedAddress(address))
+ }
+ }
+
+ @Test
+ fun testGetLocalAddressReturnsLocalIP() {
+ val test = IPTools.localIPv4Address
+ Assert.assertNotNull(test)
+ Assert.assertTrue(IPTools.isIpAddressLocalhost(test))
+ Assert.assertTrue(IPTools.isIpAddressLocalNetwork(test))
+ }
+
+ @Test
+ fun testGetAllLocalAddressReturnsLocalIP() {
+ val test: List = IPTools.localIPv4Addresses
+ for (address in test) {
+ println(address)
+ Assert.assertNotNull(address)
+ Assert.assertTrue(IPTools.isIpAddressLocalhost(address))
+ Assert.assertTrue(IPTools.isIpAddressLocalNetwork(address))
+ }
+ }
+
+ @Test
+ @Throws(UnknownHostException::class)
+ fun testLocalAddresses() {
+ Assert.assertTrue(IPTools.isIpAddressLocalhost(InetAddress.getByName("127.0.0.1")))
+ Assert.assertFalse(IPTools.isIpAddressLocalhost(InetAddress.getByName("8.8.8.8")))
+ }
+
+ @Test
+ @Throws(UnknownHostException::class)
+ fun testLocalAddressesNetwork() {
+ Assert.assertFalse(IPTools.isIpAddressLocalNetwork(InetAddress.getByName("8.8.8.8")))
+ }
+
+ private fun assertIPv4Address(ips: Array, isIPv4Address: Boolean) {
+ for (address in ips) {
+ Assert.assertThat(IPTools.isIPv4Address(address), CoreMatchers.`is`(isIPv4Address))
+ }
+ }
+
+ private fun assertIPv6Address(ips: Array, isIPv6Address: Boolean) {
+ for (address in ips) {
+ Assert.assertThat(IPTools.isIPv6Address(address), CoreMatchers.`is`(isIPv6Address))
+ }
+ }
+
+ private fun assertIPv6StdAddress(ips: Array, isIPv6StdAddress: Boolean) {
+ for (address in ips) {
+ Assert.assertThat(
+ IPTools.isIPv6StdAddress(address),
+ CoreMatchers.`is`(isIPv6StdAddress)
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.java b/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.java
deleted file mode 100644
index 8ebaa47..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.stealthcopter.networktools;
-
-import org.junit.Test;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-/**
- * Created by matthew on 03/11/17.
- */
-
-public class MACToolsTest {
-
- String[] getInvalidMACAddresses(){
- return new String[]{null, "beepbeep", "nope", "hello", "00-15-E9-2B-99+3C", "0G-15-E9-2B-99-3C"};
- }
-
- String[] getValidMACAddresses(){
- return new String[]{"00:00:00:00:00:00", "00-15-E9-2B-99-3C", "00:15:E9:2B:99:3C", "00-15-e9-2b-99-3c"};
- }
-
- @Test
- public void testValidMACAddresses() {
- for (String macAddress : getValidMACAddresses()) {
- assertTrue(MACTools.isValidMACAddress(macAddress));
- }
- }
-
- @Test
- public void testInvalidMACAddresses() {
- for (String macAddress: getInvalidMACAddresses()) {
- assertFalse(MACTools.isValidMACAddress(macAddress));
- }
- }
-
-}
diff --git a/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.kt b/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.kt
new file mode 100644
index 0000000..bf956af
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/MACToolsTest.kt
@@ -0,0 +1,33 @@
+package com.stealthcopter.networktools
+
+import org.junit.Assert
+import org.junit.Test
+
+/**
+ * Created by matthew on 03/11/17.
+ */
+class MACToolsTest {
+ val invalidMACAddresses: Array
+ get() = arrayOf(null, "beepbeep", "nope", "hello", "00-15-E9-2B-99+3C", "0G-15-E9-2B-99-3C")
+ val validMACAddresses: Array
+ get() = arrayOf(
+ "00:00:00:00:00:00",
+ "00-15-E9-2B-99-3C",
+ "00:15:E9:2B:99:3C",
+ "00-15-e9-2b-99-3c"
+ )
+
+ @Test
+ fun testValidMACAddresses() {
+ for (macAddress in validMACAddresses) {
+ Assert.assertTrue(MACTools.isValidMACAddress(macAddress))
+ }
+ }
+
+ @Test
+ fun testInvalidMACAddresses() {
+ for (macAddress in invalidMACAddresses) {
+ Assert.assertFalse(MACTools.isValidMACAddress(macAddress))
+ }
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/PingTest.java b/library/src/test/java/com/stealthcopter/networktools/PingTest.java
deleted file mode 100644
index 99aa505..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/PingTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.stealthcopter.networktools;
-
-import org.junit.Test;
-
-/**
- * Created by matthew on 03/11/17.
- */
-
-public class PingTest {
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidDelay() throws Exception {
- Ping.onAddress("127.0.0.1").setDelayMillis(-1);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidTimeout() throws Exception {
- Ping.onAddress("127.0.0.1").setTimeOutMillis(-1);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidTimes() throws Exception {
- Ping.onAddress("127.0.0.1").setTimes(-1);
- }
-
-}
diff --git a/library/src/test/java/com/stealthcopter/networktools/PingTest.kt b/library/src/test/java/com/stealthcopter/networktools/PingTest.kt
new file mode 100644
index 0000000..f602251
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/PingTest.kt
@@ -0,0 +1,26 @@
+package com.stealthcopter.networktools
+
+import org.junit.Test
+
+/**
+ * Created by matthew on 03/11/17.
+ */
+class PingTest {
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidDelay() {
+ Ping.onAddress("127.0.0.1").setDelayMillis(-1)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidTimeout() {
+ Ping.onAddress("127.0.0.1").setTimeOutMillis(-1)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidTimes() {
+ Ping.onAddress("127.0.0.1").setTimes(-1)
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/PortScanTest.java b/library/src/test/java/com/stealthcopter/networktools/PortScanTest.java
deleted file mode 100644
index 994fb2e..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/PortScanTest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.stealthcopter.networktools;
-
-import org.junit.Test;
-
-/**
- * To work on unit tests, switch the Test Artifact in the Build Variants view.
- */
-public class PortScanTest {
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidTimout() throws Exception {
- PortScan.onAddress("127.0.0.1").setTimeOutMillis(-1);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidPortLow() throws Exception {
- PortScan.onAddress("127.0.0.1").setPort(0);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidPortHigh() throws Exception {
- PortScan.onAddress("127.0.0.1").setPort(65536);
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/PortScanTest.kt b/library/src/test/java/com/stealthcopter/networktools/PortScanTest.kt
new file mode 100644
index 0000000..322aeee
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/PortScanTest.kt
@@ -0,0 +1,26 @@
+package com.stealthcopter.networktools
+
+import org.junit.Test
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+class PortScanTest {
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidTimout() {
+ PortScan.onAddress("127.0.0.1").setTimeOutMillis(-1)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidPortLow() {
+ PortScan.onAddress("127.0.0.1").setPort(0)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidPortHigh() {
+ PortScan.onAddress("127.0.0.1").setPort(65536)
+ }
+}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.java b/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.java
deleted file mode 100644
index a81af63..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.stealthcopter.networktools;
-
-public class SubnetDevicesTest {
-}
diff --git a/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.kt b/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.kt
new file mode 100644
index 0000000..b1db9ec
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/SubnetDevicesTest.kt
@@ -0,0 +1,3 @@
+package com.stealthcopter.networktools
+
+class SubnetDevicesTest
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.java b/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.java
deleted file mode 100644
index 1682738..0000000
--- a/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.stealthcopter.networktools;
-
-import org.junit.Test;
-
-import java.net.InetAddress;
-
-/**
- * To work on unit tests, switch the Test Artifact in the Build Variants view.
- */
-public class WakeOnLanTest {
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidIPaddressStr() throws Exception {
- WakeOnLan.sendWakeOnLan((String)null, "00:04:20:06:55:1a", 9, 10000, 5);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidIPaddress() throws Exception {
- WakeOnLan.sendWakeOnLan((InetAddress) null, "00:04:20:06:55:1a", 9, 10000, 5);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidMACaddress() throws Exception {
- WakeOnLan.sendWakeOnLan("192.168.0.1", null, 9, 10000, 5);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidPortLow() throws Exception {
- WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", -1, 10000, 5);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidPortHigh() throws Exception {
- WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", 65536, 10000, 5);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testIllegalArgumentThrownOnInvalidPackets() throws Exception {
- WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", 9, 10000, 0);
- }
-}
\ No newline at end of file
diff --git a/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.kt b/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.kt
new file mode 100644
index 0000000..d806d5c
--- /dev/null
+++ b/library/src/test/java/com/stealthcopter/networktools/WakeOnLanTest.kt
@@ -0,0 +1,45 @@
+package com.stealthcopter.networktools
+
+import org.junit.Test
+import java.net.InetAddress
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+class WakeOnLanTest {
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidIPaddressStr() {
+ WakeOnLan.sendWakeOnLan(null as String?, "00:04:20:06:55:1a", 9, 10000, 5)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidIPaddress() {
+ WakeOnLan.sendWakeOnLan(null as InetAddress?, "00:04:20:06:55:1a", 9, 10000, 5)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidMACaddress() {
+ WakeOnLan.sendWakeOnLan("192.168.0.1", null, 9, 10000, 5)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidPortLow() {
+ WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", -1, 10000, 5)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidPortHigh() {
+ WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", 65536, 10000, 5)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ @Throws(Exception::class)
+ fun testIllegalArgumentThrownOnInvalidPackets() {
+ WakeOnLan.sendWakeOnLan("192.168.0.1", "00:04:20:06:55:1a", 9, 10000, 0)
+ }
+}
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 44cee5d..f1902b7 100644
--- a/readme.md
+++ b/readme.md
@@ -48,7 +48,7 @@ then add a library dependency. **Remember** to check for latest release [here](h
```groovy
dependencies {
- compile 'com.github.stealthcopter:AndroidNetworkTools:0.4.5.3'
+ compile 'com.github.stealthcopter:AndroidNetworkTools:0.4.6'
}
```