10
10
import java .net .DatagramPacket ;
11
11
import java .net .DatagramSocket ;
12
12
import java .net .InetAddress ;
13
+ import java .net .NetworkInterface ;
13
14
import java .net .SocketException ;
15
+ import java .net .SocketTimeoutException ;
14
16
import java .net .UnknownHostException ;
17
+ import java .util .Enumeration ;
15
18
16
19
import javax .imageio .ImageIO ;
17
20
@@ -39,6 +42,8 @@ public class UDPStreamViewerExtension extends StaticWidget {
39
42
private DatagramSocket socket ;
40
43
private final byte [] buffer = new byte [100000 ];
41
44
45
+ private final int RECEIVE_TIMEOUT = 1000 ;
46
+
42
47
public class BGThread extends Thread {
43
48
44
49
boolean destroyed = false ;
@@ -54,15 +59,16 @@ public void run() {
54
59
while (!destroyed ) {
55
60
try {
56
61
DatagramPacket packet = new DatagramPacket (buffer , buffer .length );
57
- socket .receive (packet );
62
+ try {
63
+ socket .receive (packet );
64
+ } catch (SocketTimeoutException t ) {
65
+ updateIP ();
66
+ }
58
67
59
68
fpsCounter ++;
60
69
long currTime = System .currentTimeMillis ();
61
70
long elapsedTime = currTime - lastFPSCheck ;
62
71
if (elapsedTime > 500 ) {
63
- if (elapsedTime > 2000 ) {
64
- updateIP ();
65
- }
66
72
lastFPSCheck = currTime ;
67
73
lastFPS = fpsCounter * 2 ;
68
74
fpsCounter = 0 ;
@@ -108,16 +114,21 @@ public UDPStreamViewerExtension() {
108
114
109
115
private void updateIP () {
110
116
try {
111
- VisionParameters .setStreamIP (InetAddress . getLocalHost ().getHostAddress ());
117
+ VisionParameters .setStreamIP (getLocalHostLANAddress ().getHostAddress ());
112
118
} catch (UnknownHostException e ) {
113
119
System .out .println (e );
114
120
}
115
121
}
116
-
122
+
117
123
@ Override
118
124
public void init () {
119
125
setPreferredSize (new Dimension (320 , 240 ));
120
126
propertyChanged (rotateProperty );
127
+ try {
128
+ socket .setSoTimeout (RECEIVE_TIMEOUT );
129
+ } catch (SocketException e ) {
130
+ System .err .println ("Could not set socket timeout: " + e );
131
+ }
121
132
bgThread .start ();
122
133
updateIP ();
123
134
revalidate ();
@@ -162,8 +173,10 @@ protected void paintComponent(Graphics g) {
162
173
double panelHeight = getBounds ().height ;
163
174
double panelCenterX = panelWidth / 2.0 ;
164
175
double panelCenterY = panelHeight / 2.0 ;
165
- double rotatedImageWidth = origImageWidth * Math .abs (Math .cos (rotateAngleRad )) + origImageHeight * Math .abs (Math .sin (rotateAngleRad ));
166
- double rotatedImageHeight = origImageWidth * Math .abs (Math .sin (rotateAngleRad )) + origImageHeight * Math .abs (Math .cos (rotateAngleRad ));
176
+ double rotatedImageWidth = origImageWidth * Math .abs (Math .cos (rotateAngleRad ))
177
+ + origImageHeight * Math .abs (Math .sin (rotateAngleRad ));
178
+ double rotatedImageHeight = origImageWidth * Math .abs (Math .sin (rotateAngleRad ))
179
+ + origImageHeight * Math .abs (Math .cos (rotateAngleRad ));
167
180
168
181
// compute scaling needed
169
182
double scale = Math .min (panelWidth / rotatedImageWidth , panelHeight / rotatedImageHeight );
@@ -197,4 +210,91 @@ protected void paintComponent(Graphics g) {
197
210
198
211
public void imageUpdated (BufferedImage image ) {
199
212
}
213
+
214
+ /**
215
+ * Returns an <code>InetAddress</code> object encapsulating what is most
216
+ * likely the machine's LAN IP address.
217
+ * <p/>
218
+ * This method is intended for use as a replacement of JDK method
219
+ * <code>InetAddress.getLocalHost</code>, because that method is ambiguous
220
+ * on Linux systems. Linux systems enumerate the loopback network interface
221
+ * the same way as regular LAN network interfaces, but the JDK
222
+ * <code>InetAddress.getLocalHost</code> method does not specify the
223
+ * algorithm used to select the address returned under such circumstances,
224
+ * and will often return the loopback address, which is not valid for
225
+ * network communication. Details
226
+ * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here
227
+ * </a>.
228
+ * <p/>
229
+ * This method will scan all IP addresses on all network interfaces on the
230
+ * host machine to determine the IP address most likely to be the machine's
231
+ * LAN address. If the machine has multiple IP addresses, this method will
232
+ * prefer a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually
233
+ * IPv4) if the machine has one (and will return the first site-local
234
+ * address if the machine has more than one), but if the machine does not
235
+ * hold a site-local address, this method will return simply the first
236
+ * non-loopback address found (IPv4 or IPv6).
237
+ * <p/>
238
+ * If this method cannot find a non-loopback address using this selection
239
+ * algorithm, it will fall back to calling and returning the result of JDK
240
+ * method <code>InetAddress.getLocalHost</code>.
241
+ * <p/>
242
+ *
243
+ * @throws UnknownHostException If the LAN address of the machine cannot be
244
+ * found.
245
+ */
246
+ private static InetAddress getLocalHostLANAddress () throws UnknownHostException {
247
+ try {
248
+ InetAddress candidateAddress = null ;
249
+ // Iterate all NICs (network interface cards)...
250
+ for (Enumeration <NetworkInterface > ifaces = NetworkInterface .getNetworkInterfaces (); ifaces
251
+ .hasMoreElements ();) {
252
+ NetworkInterface iface = ifaces .nextElement ();
253
+ // Iterate all IP addresses assigned to each card...
254
+ for (Enumeration <InetAddress > inetAddrs = iface .getInetAddresses (); inetAddrs .hasMoreElements ();) {
255
+ InetAddress inetAddr = inetAddrs .nextElement ();
256
+ if (!inetAddr .isLoopbackAddress ()) {
257
+
258
+ if (inetAddr .isSiteLocalAddress ()) {
259
+ // Found non-loopback site-local address. Return it
260
+ // immediately...
261
+ return inetAddr ;
262
+ } else if (candidateAddress == null ) {
263
+ // Found non-loopback address, but not necessarily
264
+ // site-local.
265
+ // Store it as a candidate to be returned if
266
+ // site-local address is not subsequently found...
267
+ candidateAddress = inetAddr ;
268
+ // Note that we don't repeatedly assign non-loopback
269
+ // non-site-local addresses as candidates,
270
+ // only the first. For subsequent iterations,
271
+ // candidate will be non-null.
272
+ }
273
+ }
274
+ }
275
+ }
276
+ if (candidateAddress != null ) {
277
+ // We did not find a site-local address, but we found some other
278
+ // non-loopback address.
279
+ // Server might have a non-site-local address assigned to its
280
+ // NIC (or it might be running
281
+ // IPv6 which deprecates the "site-local" concept).
282
+ // Return this non-loopback candidate address...
283
+ return candidateAddress ;
284
+ }
285
+ // At this point, we did not find a non-loopback address.
286
+ // Fall back to returning whatever InetAddress.getLocalHost()
287
+ // returns...
288
+ InetAddress jdkSuppliedAddress = InetAddress .getLocalHost ();
289
+ if (jdkSuppliedAddress == null ) {
290
+ throw new UnknownHostException ("The JDK InetAddress.getLocalHost() method unexpectedly returned null." );
291
+ }
292
+ return jdkSuppliedAddress ;
293
+ } catch (Exception e ) {
294
+ UnknownHostException unknownHostException =
295
+ new UnknownHostException ("Failed to determine LAN address: " + e );
296
+ unknownHostException .initCause (e );
297
+ throw unknownHostException ;
298
+ }
299
+ }
200
300
}
0 commit comments