11package oly .netpowerctrl .anelservice ;
22
33import android .content .Context ;
4+ import android .util .Log ;
5+ import android .widget .Toast ;
46
57import java .net .DatagramPacket ;
68import java .net .DatagramSocket ;
911import java .net .NetworkInterface ;
1012import java .net .SocketException ;
1113import java .net .UnknownHostException ;
12- import java .nio . ByteBuffer ;
14+ import java .util . ArrayList ;
1315import java .util .Collection ;
1416import java .util .Enumeration ;
17+ import java .util .Iterator ;
1518import java .util .Locale ;
19+ import java .util .Set ;
1620import java .util .concurrent .LinkedBlockingQueue ;
1721
1822import oly .netpowerctrl .R ;
1923import oly .netpowerctrl .datastructure .DeviceCommand ;
24+ import oly .netpowerctrl .datastructure .DeviceInfo ;
2025import oly .netpowerctrl .datastructure .OutletInfo ;
2126import oly .netpowerctrl .main .NetpowerctrlApplication ;
2227import oly .netpowerctrl .utils .ShowToast ;
2732 */
2833public class DeviceSend {
2934 private static final int INQUERY_REQUEST = 0 ;
35+ private static final int INQUERY_BROADCAST_REQUEST = 1 ;
36+ private static final int NETWORK_UNREACHABLE = 2 ;
37+
3038 // Singleton
3139 static DeviceSend mInstance = new DeviceSend ();
3240
@@ -45,7 +53,7 @@ public void interrupt() {
4553 public void addSendJob (String hostname , int port , byte [] message , boolean broadcast , int errorID ) throws UnknownHostException {
4654 if (!sendThread .isAlive ())
4755 sendThread .start ();
48- q .add (new SendJob (InetAddress . getByName ( hostname ) , port , message , broadcast , errorID ));
56+ q .add (new SendJob (hostname , port , message , broadcast , errorID ));
4957 }
5058
5159 public void addSendJob (InetAddress ip , int port , byte [] message , boolean broadcast , int errorID ) {
@@ -111,7 +119,8 @@ void process() {
111119 }
112120
113121 class SendJob extends Job {
114- InetAddress ip ;
122+ InetAddress ip = null ;
123+ String hostname ;
115124 int port ;
116125 byte [] message ;
117126 boolean broadcast ;
@@ -125,23 +134,51 @@ class SendJob extends Job {
125134 this .errorID = errorID ;
126135 }
127136
137+ SendJob (String hostname , int port , byte [] message , boolean broadcast , int errorID ) {
138+ this .hostname = hostname ;
139+ this .message = message ;
140+ this .port = port ;
141+ this .broadcast = broadcast ;
142+ this .errorID = errorID ;
143+ }
144+
128145 @ Override
129146 void process () {
130147 try {
148+ if (hostname != null && hostname .length () > 0 ) {
149+ ip = InetAddress .getByName (hostname );
150+ hostname = "" ;
151+ }
131152 datagramSocket .setBroadcast (broadcast );
132153 datagramSocket .send (new DatagramPacket (message , message .length , ip , port ));
154+ } catch (final SocketException e ) {
155+ if (e .getMessage ().contains ("ENETUNREACH" ))
156+ onError (NETWORK_UNREACHABLE , ip , port , e );
157+ else {
158+ e .printStackTrace ();
159+ onError (errorID , ip , port , e );
160+ }
133161 } catch (final Exception e ) {
134- onError (errorID , e );
162+ e .printStackTrace ();
163+ onError (errorID , ip , port , e );
135164 }
136165 }
137166 }
138167
139- private void onError (int errorID , Exception e ) {
168+ private void onError (int errorID , InetAddress ip , int port , Exception e ) {
140169 Context context = NetpowerctrlApplication .instance ;
141170 switch (errorID ) {
142171 case INQUERY_REQUEST :
143172 ShowToast .FromOtherThread (context ,
144- context .getResources ().getString (R .string .error_sending_inquiry ) + ": " + e .getMessage ());
173+ context .getResources ().getString (R .string .error_sending_inquiry , ip .getHostAddress ()) + ": " + e .getMessage ());
174+ break ;
175+ case INQUERY_BROADCAST_REQUEST :
176+ ShowToast .FromOtherThread (context ,
177+ context .getResources ().getString (R .string .error_sending_broadcast_inquiry , port ) + ": " + e .getMessage ());
178+ break ;
179+ case NETWORK_UNREACHABLE :
180+ ShowToast .FromOtherThread (context ,
181+ context .getResources ().getString (R .string .error_not_in_range , ip .getHostAddress ()));
145182 break ;
146183 }
147184 }
@@ -155,18 +192,65 @@ private byte[] generateAllOutletsDatagramBytes(final DeviceCommand device) {
155192 return data ;
156193 }
157194
158- boolean sendQuery (final Context context , final String hostname , final int port , boolean rangeCheck ) {
159- if (rangeCheck ) {
160- try {
161- if (!isIPinNetworkAddressPool (InetAddress .getByName (hostname ))) {
162- ShowToast .FromOtherThread (context , context .getResources ().getString (R .string .error_not_in_range ) + ": " + hostname );
163- return false ;
195+ void sendBroadcastQuery () {
196+ Set <Integer > ports = NetpowerctrlApplication .instance .getAllSendPorts ();
197+ boolean foundBroadcastAddresses = false ;
198+
199+ Enumeration list ;
200+ try {
201+ list = NetworkInterface .getNetworkInterfaces ();
202+
203+ while (list .hasMoreElements ()) {
204+ NetworkInterface iface = (NetworkInterface ) list .nextElement ();
205+
206+ if (iface == null ) continue ;
207+
208+ if (!iface .isLoopback () && iface .isUp ()) {
209+
210+ Iterator it = iface .getInterfaceAddresses ().iterator ();
211+ while (it .hasNext ()) {
212+ InterfaceAddress address = (InterfaceAddress ) it .next ();
213+ //System.out.println("Found address: " + address);
214+ if (address == null ) continue ;
215+ InetAddress broadcast = address .getBroadcast ();
216+ if (broadcast == null ) continue ;
217+ for (int port : ports )
218+ addSendJob (broadcast , port , "wer da?\r \n " .getBytes (), true , INQUERY_BROADCAST_REQUEST );
219+ foundBroadcastAddresses = true ;
220+ }
164221 }
165- } catch (final Exception e ) {
166- ShowToast .FromOtherThread (context , context .getResources ().getString (R .string .error_not_in_range ) + ": " + hostname );
167- return false ;
222+ }
223+ } catch (SocketException ex ) {
224+ Log .w ("sendBroadcastQuery" , "Error while getting network interfaces" );
225+ ex .printStackTrace ();
226+ }
227+
228+ if (!foundBroadcastAddresses ) {
229+ // Broadcast not allowed on this network. Show hint to user
230+ Toast .makeText (NetpowerctrlApplication .instance ,
231+ NetpowerctrlApplication .instance .getString (R .string .devices_no_new_on_network ),
232+ Toast .LENGTH_SHORT ).show ();
233+
234+ // Query all existing devices directly
235+ ArrayList <DeviceInfo > devices = NetpowerctrlApplication .instance .configuredDevices ;
236+ for (DeviceInfo di : devices ) {
237+ sendQuery (di .HostName , di .SendPort , false );
168238 }
169239 }
240+ }
241+
242+ boolean sendQuery (final String hostname , final int port , boolean rangeCheck ) {
243+ if (rangeCheck ) {
244+ // try {
245+ // if (!isIPinNetworkAddressPool(InetAddress.getByName(hostname))) {
246+ // ShowToast.FromOtherThread(context, context.getResources().getString(R.string.error_not_in_range) + ": " + hostname);
247+ // return false;
248+ // }
249+ // } catch (final SocketException e) {
250+ // ShowToast.FromOtherThread(context, context.getResources().getString(R.string.error_not_in_range) + ": " + hostname+" "+e.getMessage());
251+ // return false;
252+ // }
253+ }
170254 try {
171255 addSendJob (hostname , port , "wer da?\r \n " .getBytes (), true , INQUERY_REQUEST );
172256 } catch (UnknownHostException e ) {
@@ -218,28 +302,28 @@ public void sendOutlets(final Collection<DeviceCommand> device_commands, final b
218302 }
219303 }
220304 }
221-
222- static private boolean isIPinNetworkAddressPool (InetAddress ip ) throws SocketException {
223- byte [] ipAddressBytes = ip .getAddress ();
224- // Iterate all NICs (network interface cards)...
225- for (Enumeration networkInterfaceEnumerator = NetworkInterface .getNetworkInterfaces (); networkInterfaceEnumerator .hasMoreElements (); ) {
226- NetworkInterface networkInterface = (NetworkInterface ) networkInterfaceEnumerator .nextElement ();
227- for (InterfaceAddress interfaceAddress : networkInterface .getInterfaceAddresses ()) {
228- InetAddress interfaceIPAddress = interfaceAddress .getAddress ();
229- byte [] interfaceIPBytes = interfaceIPAddress .getAddress ();
230- if (ipAddressBytes .length != interfaceIPBytes .length )
231- continue ; // different ip versions
232-
233- byte [] subNetMaskBytes = ByteBuffer .allocate (4 ).putInt (interfaceAddress .getNetworkPrefixLength ()).array ();
234- // check each byte of both addresses while applying the subNet mask
235- for (int i = 0 ; i < interfaceIPBytes .length ; ++i ) {
236- if ((ipAddressBytes [i ] & subNetMaskBytes [i ]) !=
237- (interfaceIPBytes [i ] & subNetMaskBytes [i ]))
238- continue ; // byte not identical, the ip is not for this network interface
239- }
240- return true ;
241- }
242- }
243- return false ;
244- }
305+ //
306+ // static private boolean isIPinNetworkAddressPool(InetAddress ip) throws SocketException {
307+ // byte[] ipAddressBytes = ip.getAddress();
308+ // // Iterate all NICs (network interface cards)...
309+ // for (Enumeration networkInterfaceEnumerator = NetworkInterface.getNetworkInterfaces(); networkInterfaceEnumerator.hasMoreElements(); ) {
310+ // NetworkInterface networkInterface = (NetworkInterface) networkInterfaceEnumerator.nextElement();
311+ // for (InterfaceAddress interfaceAddress : networkInterface.getInterfaceAddresses()) {
312+ // InetAddress interfaceIPAddress = interfaceAddress.getAddress();
313+ // byte[] interfaceIPBytes = interfaceIPAddress.getAddress();
314+ // if (ipAddressBytes.length != interfaceIPBytes.length)
315+ // continue; // different ip versions
316+ //
317+ // byte[] subNetMaskBytes = ByteBuffer.allocate(4).putInt(interfaceAddress.getNetworkPrefixLength()).array();
318+ // // check each byte of both addresses while applying the subNet mask
319+ // for (int i = 0; i < interfaceIPBytes.length; ++i) {
320+ // if ((ipAddressBytes[i] & subNetMaskBytes[i]) !=
321+ // (interfaceIPBytes[i] & subNetMaskBytes[i]))
322+ // continue; // byte not identical, the ip is not for this network interface
323+ // }
324+ // return true;
325+ // }
326+ // }
327+ // return false;
328+ // }
245329}
0 commit comments