6
6
import java .net .DatagramPacket ;
7
7
import java .net .DatagramSocket ;
8
8
import java .net .InetAddress ;
9
+ import java .net .InterfaceAddress ;
10
+ import java .net .NetworkInterface ;
11
+ import java .net .SocketException ;
12
+ import java .nio .ByteBuffer ;
9
13
import java .util .ArrayList ;
10
14
import java .util .Collection ;
15
+ import java .util .Enumeration ;
11
16
import java .util .Iterator ;
12
17
13
18
import oly .netpowerctrl .R ;
@@ -31,25 +36,30 @@ public class DeviceQuery {
31
36
public void run () {
32
37
for (DeviceInfo di : devices_to_observe )
33
38
target .onDeviceTimeout (di );
34
- freeSelf ();
39
+ target .onDeviceQueryFinished (devices_to_observe .size ());
40
+ NetpowerctrlApplication .instance .removeUpdateDeviceState (DeviceQuery .this );
35
41
}
36
42
};
37
43
38
- public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target , DeviceInfo device_to_observe ) {
44
+ public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target , DeviceInfo device_to_observe , boolean rangeCheck ) {
39
45
this .target = target ;
40
46
this .devices_to_observe = new ArrayList <DeviceInfo >();
41
47
devices_to_observe .add (device_to_observe );
42
48
43
49
// Register on main application object to receive device updates
44
50
NetpowerctrlApplication .instance .addUpdateDeviceState (this );
45
51
46
- timeoutHandler . postDelayed ( timeoutRunnable , 1200 );
52
+
47
53
// Send out broadcast
48
- sendQuery (context , device_to_observe .HostName , device_to_observe .SendPort );
54
+ if (!sendQuery (context , device_to_observe .HostName , device_to_observe .SendPort , rangeCheck )) {
55
+ // Device not in range, immediately timeout
56
+ timeoutHandler .postDelayed (timeoutRunnable , 0 );
57
+ } else
58
+ timeoutHandler .postDelayed (timeoutRunnable , 1200 );
49
59
}
50
60
51
61
public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target ,
52
- Collection <DeviceInfo > devices_to_observe , boolean queryForNewDevices ) {
62
+ Collection <DeviceInfo > devices_to_observe , boolean queryForNewDevices , boolean rangeCheck ) {
53
63
this .target = target ;
54
64
this .devices_to_observe = new ArrayList <DeviceInfo >(devices_to_observe );
55
65
@@ -63,10 +73,16 @@ public DeviceQuery(Context context, DeviceUpdateStateOrTimeout target,
63
73
sendBroadcastQuery (context );
64
74
else
65
75
for (DeviceInfo di : devices_to_observe )
66
- sendQuery (context , di .HostName , di .SendPort );
76
+ sendQuery (context , di .HostName , di .SendPort , rangeCheck );
67
77
}
68
78
69
- public void notifyAndRemove (DeviceInfo received_data ) {
79
+ /**
80
+ * Return true if all devices responded and this DeviceQuery object
81
+ * have to be removed.
82
+ *
83
+ * @param received_data
84
+ */
85
+ public boolean notifyObservers (DeviceInfo received_data ) {
70
86
Iterator <DeviceInfo > it = devices_to_observe .iterator ();
71
87
while (it .hasNext ()) {
72
88
DeviceInfo device_to_observe = it .next ();
@@ -77,13 +93,10 @@ public void notifyAndRemove(DeviceInfo received_data) {
77
93
}
78
94
if (devices_to_observe .isEmpty ()) {
79
95
timeoutHandler .removeCallbacks (timeoutRunnable );
80
- freeSelf ();
96
+ target .onDeviceQueryFinished (devices_to_observe .size ());
97
+ return true ;
81
98
}
82
- }
83
-
84
- private void freeSelf () {
85
- target .onDeviceQueryFinished (devices_to_observe .size ());
86
- NetpowerctrlApplication .instance .removeUpdateDeviceState (this );
99
+ return false ;
87
100
}
88
101
89
102
/**
@@ -94,10 +107,21 @@ private void freeSelf() {
94
107
* @param device_command
95
108
*/
96
109
static void sendQuery (final Context context , DeviceCommand device_command ) {
97
- sendQuery (context , device_command .dest .getHostAddress (), device_command .port );
110
+ sendQuery (context , device_command .dest .getHostAddress (), device_command .port , false );
98
111
}
99
112
100
- private static void sendQuery (final Context context , final String hostname , final int port ) {
113
+ private static boolean sendQuery (final Context context , final String hostname , final int port , boolean rangeCheck ) {
114
+ if (rangeCheck ) {
115
+ try {
116
+ if (!isIPinNetworkAddressPool (InetAddress .getByName (hostname ))) {
117
+ ShowToast .FromOtherThread (context , context .getResources ().getString (R .string .error_not_in_range ) + ": " + hostname );
118
+ return false ;
119
+ }
120
+ } catch (final Exception e ) {
121
+ ShowToast .FromOtherThread (context , context .getResources ().getString (R .string .error_not_in_range ) + ": " + hostname );
122
+ return false ;
123
+ }
124
+ }
101
125
new Thread (new Runnable () {
102
126
public void run () {
103
127
try {
@@ -115,10 +139,35 @@ public void run() {
115
139
}
116
140
}
117
141
}).start ();
142
+ return true ;
118
143
}
119
144
120
145
private static void sendBroadcastQuery (final Context context ) {
121
146
for (int port : NetpowerctrlApplication .instance .getAllSendPorts ())
122
- sendQuery (context , "255.255.255.255" , port );
147
+ sendQuery (context , "255.255.255.255" , port , false );
148
+ }
149
+
150
+ static private boolean isIPinNetworkAddressPool (InetAddress ip ) throws SocketException {
151
+ byte [] ipAddressBytes = ip .getAddress ();
152
+ // Iterate all NICs (network interface cards)...
153
+ for (Enumeration networkInterfaceEnumerator = NetworkInterface .getNetworkInterfaces (); networkInterfaceEnumerator .hasMoreElements (); ) {
154
+ NetworkInterface networkInterface = (NetworkInterface ) networkInterfaceEnumerator .nextElement ();
155
+ for (InterfaceAddress interfaceAddress : networkInterface .getInterfaceAddresses ()) {
156
+ InetAddress interfaceIPAddress = interfaceAddress .getAddress ();
157
+ byte [] interfaceIPBytes = interfaceIPAddress .getAddress ();
158
+ if (ipAddressBytes .length != interfaceIPBytes .length )
159
+ continue ; // different ip versions
160
+
161
+ byte [] subNetMaskBytes = ByteBuffer .allocate (4 ).putInt (interfaceAddress .getNetworkPrefixLength ()).array ();
162
+ // check each byte of both addresses while applying the subNet mask
163
+ for (int i = 0 ; i < interfaceIPBytes .length ; ++i ) {
164
+ if ((ipAddressBytes [i ] & subNetMaskBytes [i ]) !=
165
+ (interfaceIPBytes [i ] & subNetMaskBytes [i ]))
166
+ continue ; // byte not identical, the ip is not for this network interface
167
+ }
168
+ return true ;
169
+ }
170
+ }
171
+ return false ;
123
172
}
124
173
}
0 commit comments