/**
* Copyright 2010 Eric Taix
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.bigpupdev.synodroid.wizard;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;
import com.bigpupdev.synodroid.Synodroid;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.MulticastLock;
import android.os.Message;
import android.util.Log;
/**
* A thread which try to discover NAS on the local network (use the ZeroConf protocol).
*
* @author Eric Taix (eric.taix at gmail.com)
*/
public class DiscoveringThread extends Thread {
// The current context in which this thread is running
private Context context;
// The message handler
private AddHandler handler;
private boolean DEBUG;
/**
* The constructor
*
* @param ctxP
* @param hdlP
*/
public DiscoveringThread(Context ctxP, AddHandler hdlP, boolean debug) {
context = ctxP;
handler = hdlP;
DEBUG = debug;
}
/*
* (non-Javadoc)
*
* @see java.lang.Thread#run()
*/
@Override
public void run() {
JmDNS jmdns = null;
WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("fliing_lock");
lock.setReferenceCounted(true);
try {
lock.acquire();
InetAddress addr = getLocalIpAddress(DEBUG);
jmdns = JmDNS.create(addr);
ServiceInfo[] infos = jmdns.list("_http._tcp.local.");
Message msg = new Message();
msg.what = AddHandler.MSG_SERVER_FOUND;
msg.obj = infos;
handler.sendMessage(msg);
} catch (IllegalArgumentException iae){
// JMDNS failed parsing the results it received. Fake no server found...
ServiceInfo[] infos = new ServiceInfo[0];
Message msg = new Message();
msg.what = AddHandler.MSG_SERVER_FOUND;
msg.obj = infos;
handler.sendMessage(msg);
if (DEBUG) {
Log.e(Synodroid.DS_TAG, "Failed parsing JMDNS results.");
Log.e(Synodroid.DS_TAG, iae.toString());
}
} catch (SecurityException se) {
// Could not acquire lock. Fake no server found...
ServiceInfo[] infos = new ServiceInfo[0];
Message msg = new Message();
msg.what = AddHandler.MSG_SERVER_FOUND;
msg.obj = infos;
handler.sendMessage(msg);
if (DEBUG) {
Log.e(Synodroid.DS_TAG, "Could not acquire networking lock.");
Log.e(Synodroid.DS_TAG, se.toString());
}
} catch (IOException e) {
// Networking exception caught. Fake no server found...
ServiceInfo[] infos = new ServiceInfo[0];
Message msg = new Message();
msg.what = AddHandler.MSG_SERVER_FOUND;
msg.obj = infos;
handler.sendMessage(msg);
if (DEBUG) {
Log.e(Synodroid.DS_TAG, "Networking exception caught.");
Log.e(Synodroid.DS_TAG, e.toString());
}
} finally {
if (jmdns != null)
jmdns.close();
if (lock != null) {
if (lock.isHeld())
lock.release();
}
}
}
/**
* Return local IP adress. This method iterates to each network interface and try to find something different that loopback address
*
* @return
*/
private static InetAddress getLocalIpAddress(boolean debug) {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
return inetAddress;
}
}
}
} catch (SocketException ex) {
if (debug) Log.e(Synodroid.DS_TAG, ex.toString());
}
return null;
}
}