import java.io.File;
import java.io.FileOutputStream;
import javaforce.JF;
import javaforce.JFLog;
import javaforce.ShellProcess;
import javaforce.ShellProcessListener;
/** Wireless Access Point (WAP)
*
* @author pquiring
*
*/
class WAPConnection extends Thread implements ShellProcessListener {
public String pack;
public String dev;
public String ssid;
public String encType;
public String key;
private volatile boolean wpa_success = false;
private volatile boolean wpa_failed = false;
private volatile boolean wpa_retry = false;
private volatile Object wpa_lock = new Object();
private ShellProcess wpa_supplicant;
private ShellProcess wpa_log;
public void run() {
ShellProcess sp = new ShellProcess();
JFLog.log("connectWAP:dev=" + dev + ",ssid=" + ssid);
Interface iface = Server.This.getInterface(dev);
if (!iface.wireless) {
JFLog.log("WAP:dev is not wireless:" + dev);
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
iface.pack = pack;
if (iface.link) {
//already has a link???
sp.run(new String[]{"iwconfig", dev, "essid", "any"}, false);
if (sp.getErrorLevel() != 0) {
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
int cnt = 0;
while (iface.link) {
JF.sleep(500);
cnt++;
if (cnt == 10) {
JFLog.log("WAP:Unable to drop current link");
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
}
}
sp.run(new String[]{"iwconfig", dev, "essid", ssid}, false);
if (sp.getErrorLevel() != 0) {
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
/*
sp.run(new String[]{"iwconfig", dev, "ap", "any"}, true);
if (sp.getErrorLevel() != 0) {
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
*/
if (!encType.equals("OPEN")) {
if (encType.equals("WEP")) {
if (key.length() > 0) {
sp.run(new String[]{"iwconfig", dev, "enc", key}, true);
if (sp.getErrorLevel() != 0) {
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
}
} else {
//WPA 1/2
sp.run(new String[]{"iwconfig", dev, "enc", "off"}, true); //disable WEP first
try {
FileOutputStream fos = new FileOutputStream("/root/" + dev + ".conf");
StringBuilder str = new StringBuilder();
str.append("network={\n");
str.append(" ssid=\"" + ssid + "\"\n");
str.append(" psk=\"" + key + "\"\n");
str.append("}\n");
fos.write(str.toString().getBytes());
fos.close();
File log = new File("/root/" + dev + ".log");
do {
log.delete();
log.createNewFile();
wpa_retry = false;
//wpa_supplicant doesn't output directly to stdout so I need to use it's log file instead
new Thread() {
public void run() {
JFLog.log("Starting wpa_logger");
wpa_log = new ShellProcess();
wpa_log.addListener(WAPConnection.this);
wpa_log.keepOutput(false);
wpa_log.run(new String[]{"tail", "-f", "/root/" + dev + ".log"}, true);
}
}.start();
new Thread() {
public void run() {
JFLog.log("Starting wpa_supplicant");
wpa_supplicant = new ShellProcess();
wpa_supplicant.addListener(WAPConnection.this);
wpa_supplicant.keepOutput(false);
wpa_supplicant.run(new String[]{"wpa_supplicant", "-i" + dev, "-c/root/" + dev + ".conf", "-f/root/" + dev + ".log"}, true);
}
}.start();
//wait for success or failure
synchronized (wpa_lock) {
wpa_lock.wait();
}
if (!wpa_success) {
if (wpa_log != null) {
wpa_log.destroy();
wpa_log = null;
}
if (wpa_supplicant != null) {
wpa_supplicant.destroy();
wpa_supplicant = null;
JF.sleep(250);
sp.run(new String[]{"ifconfig", dev, "up"}, true); //wpa_supplicant forces wlan down when terminated
}
}
} while (wpa_retry);
if ((!wpa_success) || (wpa_failed)) {
if (wpa_log != null) {
wpa_log.destroy();
wpa_log = null;
}
if (wpa_supplicant != null) {
wpa_supplicant.destroy();
wpa_supplicant = null;
JF.sleep(250);
sp.run(new String[]{"ifconfig", dev, "up"}, true); //wpa_supplicant forces iface down when terminated
}
Server.This.jbusClient.call(pack, "wapFailed", "");
Server.This.pendingWAP = null;
return;
}
} catch (Exception e) {
JFLog.log(e);
}
}
} else {
sp.run(new String[]{"iwconfig", dev, "enc", "off"}, true);
}
//NetLinkMonitor will setup the card if/when the link is active
}
public void init(String pack, String dev, String ssid, String encType, String key) {
this.pack = pack;
this.dev = dev;
this.ssid = ssid;
this.encType = encType;
this.key = key;
}
public void close() {
ShellProcess sp = new ShellProcess();
if (wpa_log != null) {
wpa_log.destroy();
wpa_log = null;
}
if (wpa_supplicant != null) {
wpa_supplicant.destroy();
wpa_supplicant = null;
JF.sleep(250);
sp.run(new String[]{"ifconfig", dev, "up"}, true); //wpa_supplicant forces wlan down when terminated
wpa_failed = true;
synchronized (wpa_lock) {
wpa_lock.notify();
}
}
sp.run(new String[]{"ifconfig", dev, "0.0.0.0"}, true); //remove IP
}
public void shellProcessOutput(String string) {
String[] lns = string.split("\n");
// JFLog.log(string); //test
for (int a = 0; a < lns.length; a++) {
if (lns[a].startsWith("CTRL-EVENT-DISCONNECTED")) {
wpa_failed = true;
synchronized (wpa_lock) {
wpa_lock.notify();
}
continue;
}
if (lns[a].startsWith("CTRL-EVENT-CONNECTED")) {
wpa_success = true;
synchronized (wpa_lock) {
wpa_lock.notify();
}
continue;
}
if (lns[a].endsWith("Device or resource busy")) {
JFLog.log("wpa_supplicant busy : retrying");
wpa_retry = true;
synchronized (wpa_lock) {
wpa_lock.notify();
}
continue;
}
if (lns[a].endsWith("Network is down")) {
ShellProcess sp = new ShellProcess();
sp.run(new String[]{"ifconfig", dev, "up"}, true); //wpa_supplicant forces wlan down when terminated
}
}
}
}