Skip to content

Commit f0d9be6

Browse files
committed
Made wake-on-lan chainable in a very human readable format and gave it an async method to avoid network on main thread issues
1 parent b5e77aa commit f0d9be6

File tree

4 files changed

+296
-64
lines changed

4 files changed

+296
-64
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.stealthcopter.networktools;
2+
3+
import android.support.annotation.NonNull;
4+
5+
import java.util.regex.Pattern;
6+
7+
public class MACTools {
8+
9+
private static final Pattern PATTERN_MAC =
10+
Pattern.compile(
11+
"^([0-9A-Fa-f]{2}[\\.:-]){5}([0-9A-Fa-f]{2})$");
12+
13+
// This class is not to be instantiated
14+
private MACTools() {
15+
}
16+
17+
18+
/**
19+
* Validates a provided MAC address
20+
*
21+
* @param macAddress - the MAC address to check
22+
*
23+
* @return - true if it is valid MAC address in IEEE802 format (either hyphen or colon seperated)
24+
* eg: "01:23:45:67:89:AB:CD:EF" or "01-23-45-67-89-AB-CD-EF"
25+
*/
26+
public static boolean isValidMACAddress(final String macAddress) {
27+
return PATTERN_MAC.matcher(macAddress).matches();
28+
}
29+
30+
31+
/**
32+
* Convert a MAC string to bytes
33+
*
34+
* @param macStr - MAC string in IEEE802 format (either hyphen or colon seperated)
35+
* eg: "01:23:45:67:89:AB:CD:EF" or "01-23-45-67-89-AB-CD-EF"
36+
*
37+
* @return - MAC formatted in bytes
38+
* @throws IllegalArgumentException - if mac address is invalid
39+
*/
40+
public static byte[] getMacBytes(@NonNull String macStr) throws IllegalArgumentException {
41+
42+
if (macStr == null) throw new IllegalArgumentException("Mac Address cannot be null");
43+
44+
byte[] bytes = new byte[6];
45+
String[] hex = macStr.split("(\\:|\\-)");
46+
if (hex.length != 6) {
47+
throw new IllegalArgumentException("Invalid MAC address.");
48+
}
49+
try {
50+
for (int i = 0; i < 6; i++) {
51+
bytes[i] = (byte) Integer.parseInt(hex[i], 16);
52+
}
53+
} catch (NumberFormatException e) {
54+
throw new IllegalArgumentException("Invalid hex digit in MAC address.");
55+
}
56+
return bytes;
57+
}
58+
59+
}

library/src/main/java/com/stealthcopter/networktools/Ping.java

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ private Ping() {
2121
public interface PingListener{
2222
void onResult(PingResult pingResult);
2323
void onFinished(PingStats pingStats);
24+
void onError(Exception e);
2425
}
2526

27+
private String addressString = null;
2628
private InetAddress address;
2729
private int timeOutMillis = 1000;
2830
private int delayBetweenScansMillis = 0;
@@ -31,14 +33,16 @@ public interface PingListener{
3133

3234
/**
3335
* Set the address to ping
36+
*
37+
* Note that a lookup is not performed here so that we do not accidentally perform a network
38+
* request on the UI thread.
39+
*
3440
* @param address - Address to be pinged
3541
* @return this object to allow chaining
36-
* @throws UnknownHostException
3742
*/
38-
public static Ping onAddress(@NonNull String address) throws UnknownHostException {
43+
public static Ping onAddress(@NonNull String address) {
3944
Ping ping = new Ping();
40-
InetAddress ia = InetAddress.getByName(address);
41-
ping.setAddress(ia);
45+
ping.setAddressString(address);
4246
return ping;
4347
}
4448

@@ -90,6 +94,25 @@ private void setAddress(InetAddress address) {
9094
this.address = address;
9195
}
9296

97+
/**
98+
* Set the address string which will be resolved to an address by resolveAddressString()
99+
* @param addressString - String of the address to be pinged
100+
*/
101+
private void setAddressString(String addressString) {
102+
this.addressString = addressString;
103+
}
104+
105+
/**
106+
* Parses the addressString to an address
107+
*
108+
* @throws UnknownHostException - if host cannot be found
109+
*/
110+
private void resolveAddressString() throws UnknownHostException {
111+
if (address == null && addressString !=null){
112+
address = InetAddress.getByName(addressString);
113+
}
114+
}
115+
93116
/**
94117
* Cancel a running ping
95118
*/
@@ -99,10 +122,14 @@ public void cancel() {
99122

100123
/**
101124
* Perform a synchronous ping and return a result, will ignore number of times.
125+
*
126+
* Note that this should be performed on a background thread as it will perform a network
127+
* request
102128
* @return - ping result
103129
*/
104-
public PingResult doPing(){
130+
public PingResult doPing() throws UnknownHostException {
105131
cancelled = false;
132+
resolveAddressString();
106133
return PingTools.doPing(address, timeOutMillis);
107134
}
108135

@@ -117,6 +144,18 @@ public Ping doPing(final PingListener pingListener){
117144
@Override
118145
public void run() {
119146

147+
try {
148+
resolveAddressString();
149+
} catch (UnknownHostException e) {
150+
pingListener.onError(e);
151+
return;
152+
}
153+
154+
if (address == null){
155+
pingListener.onError(new NullPointerException("Address is null"));
156+
return;
157+
}
158+
120159
long pingsCompleted = 0;
121160
long noLostPackets = 0;
122161
float totalPingTime = 0;

library/src/main/java/com/stealthcopter/networktools/PortScan.java

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -66,26 +66,7 @@ public static PortScan onAddress(@NonNull String address) throws UnknownHostExce
6666
public static PortScan onAddress(@NonNull InetAddress ia) {
6767
PortScan portScan = new PortScan();
6868
portScan.setAddress(ia);
69-
70-
// Try and work out automatically what kind of host we are scanning
71-
// local host (this device) / local network / remote
72-
if (IPTools.isIpAddressLocalhost(ia)){
73-
// If we are scanning a the localhost set the timeout to be very short so we get faster results
74-
// This will be overridden if user calls setTimeoutMillis manually.
75-
portScan.timeOutMillis = TIMEOUT_LOCALHOST;
76-
portScan.noThreads = DEFAULT_THREADS_LOCALHOST;
77-
}
78-
else if (IPTools.isIpAddressLocalNetwork(ia)){
79-
// Assume local network (not infallible)
80-
portScan.timeOutMillis = TIMEOUT_LOCALNETWORK;
81-
portScan.noThreads = DEFAULT_THREADS_LOCALNETWORK;
82-
}
83-
else{
84-
// Assume remote network timeouts
85-
portScan.timeOutMillis = TIMEOUT_REMOTE;
86-
portScan.noThreads = DEFAULT_THREADS_REMOTE;
87-
}
88-
69+
portScan.setDefaultThreadsAndTimeouts();
8970
return portScan;
9071
}
9172

@@ -218,6 +199,26 @@ private void setAddress(InetAddress address) {
218199
this.address = address;
219200
}
220201

202+
private void setDefaultThreadsAndTimeouts(){
203+
// Try and work out automatically what kind of host we are scanning
204+
// local host (this device) / local network / remote
205+
if (IPTools.isIpAddressLocalhost(address)){
206+
// If we are scanning a the localhost set the timeout to be very short so we get faster results
207+
// This will be overridden if user calls setTimeoutMillis manually.
208+
timeOutMillis = TIMEOUT_LOCALHOST;
209+
noThreads = DEFAULT_THREADS_LOCALHOST;
210+
}
211+
else if (IPTools.isIpAddressLocalNetwork(address)){
212+
// Assume local network (not infallible)
213+
timeOutMillis = TIMEOUT_LOCALNETWORK;
214+
noThreads = DEFAULT_THREADS_LOCALNETWORK;
215+
}
216+
else{
217+
// Assume remote network timeouts
218+
timeOutMillis = TIMEOUT_REMOTE;
219+
noThreads = DEFAULT_THREADS_REMOTE;
220+
}
221+
}
221222

222223
/**
223224
*
@@ -226,7 +227,7 @@ private void setAddress(InetAddress address) {
226227
* @return self
227228
* @throws IllegalAccessException - if no threads is less than 1
228229
*/
229-
public PortScan setNoThreads(int noThreads) throws IllegalAccessException {
230+
public PortScan setNoThreads(int noThreads) throws IllegalArgumentException {
230231
if (noThreads < 1) throw new IllegalArgumentException("Cannot have less than 1 thread");
231232
this.noThreads = noThreads;
232233
return this;

0 commit comments

Comments
 (0)