66import java .net .DatagramPacket ;
77import java .net .DatagramSocket ;
88import java .net .InetAddress ;
9+ import java .net .InterfaceAddress ;
10+ import java .net .NetworkInterface ;
11+ import java .net .SocketException ;
12+ import java .nio .ByteBuffer ;
913import java .util .ArrayList ;
1014import java .util .Collection ;
15+ import java .util .Enumeration ;
1116import java .util .Iterator ;
1217
1318import oly .netpowerctrl .R ;
@@ -31,25 +36,30 @@ public class DeviceQuery {
3136 public void run () {
3237 for (DeviceInfo di : devices_to_observe )
3338 target .onDeviceTimeout (di );
34- freeSelf ();
39+ target .onDeviceQueryFinished (devices_to_observe .size ());
40+ NetpowerctrlApplication .instance .removeUpdateDeviceState (DeviceQuery .this );
3541 }
3642 };
3743
38- public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target , DeviceInfo device_to_observe ) {
44+ public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target , DeviceInfo device_to_observe , boolean rangeCheck ) {
3945 this .target = target ;
4046 this .devices_to_observe = new ArrayList <DeviceInfo >();
4147 devices_to_observe .add (device_to_observe );
4248
4349 // Register on main application object to receive device updates
4450 NetpowerctrlApplication .instance .addUpdateDeviceState (this );
4551
46- timeoutHandler . postDelayed ( timeoutRunnable , 1200 );
52+
4753 // 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 );
4959 }
5060
5161 public DeviceQuery (Context context , DeviceUpdateStateOrTimeout target ,
52- Collection <DeviceInfo > devices_to_observe , boolean queryForNewDevices ) {
62+ Collection <DeviceInfo > devices_to_observe , boolean queryForNewDevices , boolean rangeCheck ) {
5363 this .target = target ;
5464 this .devices_to_observe = new ArrayList <DeviceInfo >(devices_to_observe );
5565
@@ -63,10 +73,16 @@ public DeviceQuery(Context context, DeviceUpdateStateOrTimeout target,
6373 sendBroadcastQuery (context );
6474 else
6575 for (DeviceInfo di : devices_to_observe )
66- sendQuery (context , di .HostName , di .SendPort );
76+ sendQuery (context , di .HostName , di .SendPort , rangeCheck );
6777 }
6878
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 ) {
7086 Iterator <DeviceInfo > it = devices_to_observe .iterator ();
7187 while (it .hasNext ()) {
7288 DeviceInfo device_to_observe = it .next ();
@@ -77,13 +93,10 @@ public void notifyAndRemove(DeviceInfo received_data) {
7793 }
7894 if (devices_to_observe .isEmpty ()) {
7995 timeoutHandler .removeCallbacks (timeoutRunnable );
80- freeSelf ();
96+ target .onDeviceQueryFinished (devices_to_observe .size ());
97+ return true ;
8198 }
82- }
83-
84- private void freeSelf () {
85- target .onDeviceQueryFinished (devices_to_observe .size ());
86- NetpowerctrlApplication .instance .removeUpdateDeviceState (this );
99+ return false ;
87100 }
88101
89102 /**
@@ -94,10 +107,21 @@ private void freeSelf() {
94107 * @param device_command
95108 */
96109 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 );
98111 }
99112
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+ }
101125 new Thread (new Runnable () {
102126 public void run () {
103127 try {
@@ -115,10 +139,35 @@ public void run() {
115139 }
116140 }
117141 }).start ();
142+ return true ;
118143 }
119144
120145 private static void sendBroadcastQuery (final Context context ) {
121146 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 ;
123172 }
124173}
0 commit comments