package org.myrobotlab.net;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.SocketTimeoutException;
import java.util.Enumeration;
import java.util.List;
import org.myrobotlab.framework.Message;
import org.myrobotlab.framework.Service;
import org.myrobotlab.logging.LoggerFactory;
import org.slf4j.Logger;
public class Scanner extends Thread {
public final static Logger log = LoggerFactory.getLogger(Scanner.class);
boolean isScanning = false;
Service myService;
public Scanner(Service service) {
super(String.format("%s.scanner", service.getName()));
this.myService = service;
}
@Override
public void run() {
// Find the server using UDP broadcast
isScanning = true;
while (isScanning && myService.isRunning()) {
try {
// Open a random port to send the package
DatagramSocket dsocket = new DatagramSocket();
dsocket.setBroadcast(true);
// byte[] sendData =
// "DISCOVER_FUIFSERVER_REQUEST".getBytes();
//
Message msg = myService.createMessage(null, "getConnections", null);
byte[] msgBuf = org.myrobotlab.codec.CodecUtils.getBytes(msg);
DatagramPacket sendPacket;
// Try the 255.255.255.255 first
/*
* try { sendPacket = new DatagramPacket(msgBuf, msgBuf.length,
* InetAddress.getByName("255.255.255.255"), 6767);
* dsocket.send(sendPacket); myService.info(
* ">>> Request packet sent to: 255.255.255.255 (DEFAULT)"); } catch
* (Exception e) { Logging.logException(e); }
*/
// NEEDED ?? WE ALREADY DID BROADCAST // Broadcast the
// message over all the network interfaces
// -------------- BEGIN ---------------------
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = interfaces.nextElement();
// myService.info("examining interface %s %s",
// ni.getName(), ni.getInetAddresses().toString());
log.info(String.format("examining interface %s %s", ni.getName(), ni.getDisplayName()));
// if (ni.isLoopback() || !ni.isUp()) {
if (!ni.isUp()) {
log.info(String.format("skipping %s", ni.getDisplayName()));
continue; // Don't want tobroadcast to the loopback
// // interface
}
for (InterfaceAddress interfaceAddress : ni.getInterfaceAddresses()) {
InetAddress broadcast = interfaceAddress.getBroadcast();
// short x = interfaceAddress.getNetworkPrefixLength();
log.info("" + interfaceAddress.getAddress());
if (ni.getName().equals("net4")) {
log.info("net4");
}
if (broadcast == null) {
continue;
}
// Send the broadcast package!
try {
log.info(String.format("sending to %s %s %s", ni.getName(), broadcast.getHostAddress(), ni.getDisplayName()));
if (interfaceAddress.getNetworkPrefixLength() == -1) {
log.warn("jdk bug for interface %s network prefix length == -1", interfaceAddress.getAddress().getHostAddress());
String pre = interfaceAddress.getAddress().getHostAddress();
String b = pre.substring(0, pre.lastIndexOf(".")) + ".255";
log.warn("creating new broadcast address of %s", broadcast);
broadcast = InetAddress.getByName(b);
}
sendPacket = new DatagramPacket(msgBuf, msgBuf.length, broadcast, 6767);
// sendPacket = new DatagramPacket(msgBuf,
// msgBuf.length,
// InetAddress.getByName("192.168.0.255"),
// 6767);
dsocket.send(sendPacket);
myService.info(">>> Request packet sent to: " + broadcast.getHostAddress() + "; Interface: " + ni.getDisplayName());
} catch (Exception e) {
myService.error(e);
}
}
}
// -------------- END ---------------------
myService.info(">>> Done looping over all network interfaces. Now waiting for a reply!");
// multiple replies
boolean listening = true;
// wait and read replies - put them on the message queue
// time out and will be done
try {
while (listening) {
// Wait for a response
byte[] recvBuf = new byte[15000];
DatagramPacket receivePacket = new DatagramPacket(recvBuf, recvBuf.length);
// how long we will wait for replies
dsocket.setSoTimeout(2000);
dsocket.receive(receivePacket);
// We have a response
myService.info(String.format("response from : %s", receivePacket.getAddress().getHostAddress()));
// Check if the message is correct - JSON ?
ObjectInputStream inBytes = new ObjectInputStream(new ByteArrayInputStream(receivePacket.getData()));
Message retMsg = (Message) inBytes.readObject();
myService.info("response from instance %s", retMsg);
if (!retMsg.method.equals("publishConnection")) {
myService.error("not an publishConnection message");
continue;
} else {
List<Connection> conns = (List<Connection>) retMsg.data[0];
for (int i = 0; i < conns.size(); ++i) {
myService.invoke("publishConnection", conns.get(i));
}
}
/*
* String message = new String(receivePacket.getData()).trim(); if
* (message.equals("DISCOVER_FUIFSERVER_RESPONSE")) { // DO
* SOMETHING WITH THE SERVER'S IP (for example, store it in //
* your controller) // Controller_Base
* .setServerIp(receivePacket.getAddress()); log.info(
* String.format( "+++++++++++++FOUND MRL INSTANCE++++++++++++ %s"
* , receivePacket.getAddress())); }
*/
}
} catch (SocketTimeoutException se) {
myService.info("done listening for replies");
} finally {
dsocket.close();
}
} catch (Exception e) {
myService.error(e);
}
} // while (isScanning)
}
public void stopScanning() {
isScanning = false;
}
}