commit 5ce2a651ef83501d3d3a2d964bc84582973f1c9a Author: Dan Date: Tue Dec 21 18:11:43 2010 -0500 Initial import of Cortex code from my cs416 class at UBC diff --git a/ConnHandler.java b/ConnHandler.java new file mode 100644 index 0000000..912ab2f --- /dev/null +++ b/ConnHandler.java @@ -0,0 +1,399 @@ +import java.applet.*; +//import java.awt.*; +import java.awt.event.*; +import javax.swing.Timer; +import java.awt.image.*; +import java.net.InetSocketAddress; +import java.net.InetAddress; + +import java.lang.*; +import java.io.*; +import java.net.*; +import java.util.Date; +import java.text.SimpleDateFormat; +import java.util.Scanner; +import java.util.HashMap; +import javax.swing.JOptionPane.*; + +import java.util.Enumeration; +import java.util.List; +import java.util.ArrayList; + +class ConnHandler implements Runnable { + Socket sock; + ResManager res; + + final int TYPE_GET = 0; + final int TYPE_POST = 1; + + public ConnHandler(Socket s, ResManager r) { + sock = s; + res = r; + } + + /* parseAjax + * Ajax content is in form of + * (key=value\n)*\n\n + * returns a string:string hashmap of key value pairs + */ + HashMap parseAjax(BufferedReader sin) { + HashMap req = new HashMap(); + Scanner scan = new Scanner(sin); + scan.useDelimiter("\n\n"); + String all = scan.next(); + req.put("req", all); + for ( String line : all.split("\n")) { + String kv[] = line.split("="); + req.put(kv[0], kv[1]); + } + return req; + } + + String ajaxCall(String dest, BufferedReader sin) { + Socket client = null; + PrintWriter out = null; + BufferedReader in = null; + // Get Ajax call + Scanner scan = new Scanner(sin); + scan.useDelimiter("\n\n"); + String all = scan.next(); + //res.log("Sending to " + dest + ": '" + all +"'"); + // clean up dest + + // Connect to dest + try { + //res.alert(dest); + String[] d = dest.split(":"); + //res.alert(Integer.toString( d.length)); + String p = "2600"; + if (d.length > 1) + p = d[1]; + client = new Socket(d[0], Integer.parseInt(p)); + //InetAddress addr = new InetSocketAddress("127.0.0.1"); + if (!client.isConnected()) + res.error("failed to connect!!!!!!!"); + //"127.0.0.1", 2600); //dest, res.PORT); + //client.connect(addr, 2600); + out = new PrintWriter(client.getOutputStream(), true); + in = new BufferedReader(new InputStreamReader(client.getInputStream())); + } catch (Exception e) { + res.log( "ERROR> Exception in ajaxCall (Connecting): " + e.toString()); + return ""; + } + //res.alert("Established connection"); + // HTTP / AJAX Header + call + out.print("POST / HTTP/1.1\r\n" + + "Host: " + dest + "\r\n" + + "User-Agent: Cortex\r\n" + + "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" + + "Accept-Language: en-us,en;q=0.5\r\n"+ + "Accept-Encoding: gzip,deflate\r\n" + + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" + + "Keep-Alive: 300\r\n" + + "Connection: keep-alive\r\n" + + "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n" + + "Referer: http://localhost:2600/client.html\r\n" + + "Content-Length: " + (all.length()+2) + "\r\n" + + "Pragma: no-cache\r\n" + + "Cache-Control: no-cache\r\n" + + "\r\n"); + out.print(all + "\n\n"); + out.flush(); + //res.log("sent message"); + //out.close(); + + //res.alert("printed request, trying to read"); + + // Read response + String resp = ""; + + // read http header + //res.log("Reading resp header"); + try { + String header = in.readLine(); + while (header.length() >= 3) { + //res.log("header: " + header); + header = in.readLine(); + } + } catch (Exception e) { + res.error("Exception in ajaxCall (reading HTTP response header): " + e.toString()); + return ""; + } + //res.log("Reading response body"); + //res.alert("done reading resp header"); + // read actual response + scan = new Scanner(in); + scan.useDelimiter("\n\n"); + resp = scan.next(); + //res.alert("done reading resp"); + //res.log("Closing ajaxCall"); + try { + in.close(); + out.close(); + client.close(); + } catch (Exception e) { + res.error( "Exception in ajaxCall (Closing Connection): " + e.toString()); + } + //res.alert("closed connections"); + //res.log("ajaxCall returning response to js caller: '" + resp + "'"); + return resp; + } + + // Function to enumerate all IP addresses of a computer + // and then try and select the web facing one + private String getIPAddress() { + ArrayList ips = new ArrayList(); + try { + Enumeration e = NetworkInterface.getNetworkInterfaces(); + + while(e.hasMoreElements()) { + NetworkInterface ni = (NetworkInterface) e.nextElement(); + Enumeration e2 = ni.getInetAddresses(); + InetAddress ip=null; + String istr = null; + while (e2.hasMoreElements()){ + ip = (InetAddress) e2.nextElement(); + istr = ip.toString(); + if (istr.substring(0,1).equals("/")) + istr = istr.substring(1); + if (istr.charAt(0) >= '0' && istr.charAt(0) <= '9' && istr.indexOf(':') == -1) { + //res.log("adding: '" + istr +"'"); + ips.add(istr); + } + + //ip = (InetAddress) e2.nextElement(); + } + /*if (ip == null) + continue; + istr = ip.toString(); + if (istr.substring(0,1).equals("/")) + istr = istr.substring(1); + ips.add(istr);*/ + } + } catch (Exception e) { + res.error( "Exception in ConnHandler.getIPAddress(): " + e.toString()); + } + // Now we have a list of IPs associated with this machine. Lets pick the best one + if (ips.size() == 0) + return ""; + else if (ips.size() == 1) + return ips.get(0); + else { + ips.remove("127.0.0.1"); + /*for (int i=0; i< ips.size(); i++) { + if(ips.size() ==1) + break; + + String ip = ips.get(i); + if ( + */ + // Many IPs so weed out baddies + for (int i=0; i < ips.size(); i++) { + + if (ips.size() == 1) + break; + + String ip = ips.get(i); + // remove local private subnets + if(ip.substring(0, 7).equals("192.168")) { + ips.remove(i); + i--; + } else if (ip.substring(0, 3).equals("10.")) { + ips.remove(i); + i--; + } + } + + return ips.get(0); + } + + } + + + /* handleAjax + * handle the various ajax commands appropriately + */ + private String handleAjax(HashMap req) { + String response = ""; + String cmd = req.get("cmd"); + //res.log("AJAX " + cmd); + if (cmd.equals("ping")) { + response = "pong"; + //res.log("PING pong"); + } else if (cmd.equals("greet")) { + response = getIPAddress() + ":" + res.PORT + " " + res.getNodeData("originURL") ; + } else if (cmd.equals("getLog")) { + ArrayList l = res.getLog(); + response = ""; + for (int i = l.size()-1; i >= 0; i--) { + response += l.get(i) + "\n"; + } + // response += " "; + } else if (cmd.equals("reloadHTML")) { + res.log("Reloading HTML from src..."); + res.reloadSite(); + } else if (cmd.equals("sendMsg")) { + //res.log("sendMsg: query=" + req.get("query")); + res.queueMsg(req.get("req")); + response = "received on " + res.PORT; + } else if (cmd.equals("getMsgs")) { + ArrayList mq = res.getMsgs(); + for(int i =0; i < mq.size(); i++) { + response += mq.get(i) + "\n\n"; + } + //res.log("getMsgs: '" + response + "'"); + //response = ""; + } else if (cmd.equals("kill")) { + res.killSwitch = true; + } else { + response = "Unknown cmd: " + cmd; + res.log("Unknown cmd: " + cmd); + } + return response; + } + + + + /* Handle GET requests + * A GET request is a generic browser request, + * meaning not an AJAX request, so we serve the main + * interface html file. + */ + private byte[] handleGet(String req) { + //javax.swing.JOptionPane.showMessageDialog(null, "GET: " + req); + int end = req.indexOf(' '); + req = req.substring(1, end); + //res.alert("'" + req + "'"); + if (req.equals("")) + req = "shell.html"; + byte[] r = res.getSite(req); + if (r == null) { + //javax.swing.JOptionPane.showMessageDialog(null, "Error: file not found: " + req); + return new byte[0]; + } else + return r; + } + + /* run + * Handle a HTTP connection + * Read the HTTP request and handle accordingly + * GET requests all get the main html file + * AJAX requests are managed accordingly + */ + public void run() { + /*try { + Thread.currentThread().sleep(10000); + } catch (Exception e) { + res.alert("EXCEPTION : " + e.toString()); + } + res.alert("Done waiting");*/ + try { + // READ HTTP / AJAX call + BufferedReader sin = new BufferedReader(new InputStreamReader(sock.getInputStream())); + String header= ""; + + int i = 0; + int type = TYPE_POST; + String reqLine = ""; + int contentLength = 0; + + header = sin.readLine(); + if (header == null) { + // no header, not a valid HTTP conn + res.log("Invalid connection"); + return; + } + String userAgent = "agent"; + while (header != null && header.length() >= 3) { + if ( header.substring(0, 3).equals("GET")) { + type = TYPE_GET; + reqLine = header; + + } else if (header.length() > 4 && header.substring(0, 4).equals("POST")) { + reqLine = header; + reqLine = reqLine.substring(5); + int end = reqLine.indexOf(' '); + reqLine = reqLine.substring(0, end); + if (reqLine.charAt(0) == '/') + reqLine = reqLine.substring(1); + + } else if (header.length() > 14 && header.substring(0, 14).toLowerCase().equals("content-length")) { + contentLength = Integer.parseInt(header.substring(16)); + } else if (header.length() > 10 && header.substring(0, 10).equals("User-Agent")) { + //javax.swing.JOptionPane.showMessageDialog(null, header); + userAgent = header; + + } + System.out.println(i + ": '" + header + "'"); + i++; + header = sin.readLine(); + } + //res.alert("Done reading header"); + + + + // Figure out response + String ajax_resp=""; + byte[] get_resp= null; + String CODE = "200 OK"; + int resp_length = 0; + if (type == TYPE_GET) { + reqLine = reqLine.substring(4); + res.log("GET " + reqLine); + get_resp = handleGet(reqLine); + if (get_resp.length == 0) { + CODE = "404 Not Found"; + } + resp_length = get_resp.length; + } else { + // No forward + if (reqLine.equals("")) { + //res.alert("no forward, parse ajax"); + HashMap req = parseAjax(sin); + //res.alert("handleAjax"); + ajax_resp = handleAjax(req); + //res.alert("ajax resp: " + ajax_resp); + } else { // Forward request to node + //res.log("AJAX forward to '" + reqLine + "'"); + + ajax_resp = reqLine; + ajax_resp = ajaxCall(reqLine, sin); + + } + resp_length = ajax_resp.length(); + } + + // HTTP Response + PrintWriter sout = new PrintWriter(sock.getOutputStream(), true); + Date now = new java.util.Date(); + SimpleDateFormat formater = new SimpleDateFormat("E, d M y H:m:s z"); + sout.print("HTTP/1.1 " + CODE + "\r\n"+ + "Date: " + formater.format(now) + "\r\n" + + "Content-Type: text/html; charset=UTF-8\r\n" + + "Server: Cortex @ " + Integer.toString(res.PORT) + "\r\n"); + + // Print response + + sout.print("Content-Length: " + resp_length + "\r\n" + + "\r\n"); + sout.flush(); + if (type == TYPE_GET) { + //sout.write(get_resp); + sock.getOutputStream().write(get_resp); + } else { + sout.print(ajax_resp); + //res.alert("ajax returning: " + ajax_resp); + } + sout.flush(); + sin.close(); + sout.close(); + sock.close(); + } catch (IOException e) { + res.error( "IOException in ConnHandler.run(): " + e.toString()); + System.out.println("IOException in ConnHandler.run()"); + } + System.out.println("DONE run()"); + } + + } + diff --git a/Cortex.java b/Cortex.java new file mode 100644 index 0000000..11c43df --- /dev/null +++ b/Cortex.java @@ -0,0 +1,88 @@ +import java.applet.*; +//import java.awt.*; +import java.awt.event.*; +import javax.swing.Timer; +import java.awt.image.*; + +import java.lang.*; +import java.io.*; +import java.net.*; +import java.util.Date; +import java.text.SimpleDateFormat; + +import java.util.HashMap; + +import java.util.List; + +import javax.swing.JOptionPane.*; + + +public class Cortex extends Applet { + //private final int PORT = 2600; // in ResManager now + private ServerSocket server; + + private ResManager res = new ResManager(); + + + /*URL getCodeBase() throws Exception { + return new URL("file:///home/dan/src/school/cpsc416/cortex/"); + }*/ + + /* main + * Main HTTP server. Accepts connections on PORT and passes them to threads + * in the form of ConnHandlers to deal with + */ + public void init() { + //javax.swing.JOptionPane.showMessageDialog(null, "APPLET STARTING!!!!"); + //res.alert("Starting..."); + res.putNodeData("originURL", getCodeBase().toString()); + res.reloadSite(); + + //res.alert("Loaded site"); + + boolean bound = false; + while(!bound) + { + try { + server = new ServerSocket(res.PORT); + bound = true; + } catch (IOException e) { + res.PORT++; + } + } + + + /* + try { + server = new ServerSocket(res.PORT); + } catch (IOException e) { + res.error( "It appears another Cortex Node is already running on this computer, making this one superfulous.\nShutting down..."); + }*/ + + /*try { + JSObject win = JSObject.getWindow(this); + win.eval("load();"); + } catch(Exception e) { + res.error(e.toString()); + }*/ + + try { + //res.alert("running server"); + while (!res.killSwitch) { + Socket sock = server.accept(); + //res.alert("ACCEPTED!"); + + new Thread(new ConnHandler(sock, res)).start(); + + //handler.run(); + //res.alert("RESTARTING LOOP"); + } + server.close(); + } catch (IOException e) { + System.out.println("IOException in init(): " + e.toString()); + res.error( "IOException in init(): " + e.toString()); + } + + //res.error("QUITING!"); + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..822a4f2 --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +Cortex.jar: Cortex.class ConnHandler.class ResManager.class + jar cvf Cortex.jar Cortex.class ConnHandler.class ResManager.class + jarsigner Cortex.jar cortex_cert + +ResManager.class: ResManager.java + javac ResManager.java + +ConnHandler.class: ConnHandler.java + javac ConnHandler.java + +Cortex.class: Cortex.java + javac Cortex.java + +clean: + rm -f *.class *.jar diff --git a/ResManager.java b/ResManager.java new file mode 100644 index 0000000..7ee476c --- /dev/null +++ b/ResManager.java @@ -0,0 +1,179 @@ +import java.util.HashMap; +import javax.swing.JOptionPane.*; +import java.util.ArrayList; +import java.util.Date; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import javax.swing.JOptionPane.*; +import java.lang.*; +import java.io.*; +import java.net.*; + +class ResManager { + public /*final*/ int PORT = 2600; + + private HashMap site = new HashMap(); + private HashMap nodeData = new HashMap(); + + private ArrayList log = new ArrayList(); + private boolean logLock = false; + private DateFormat logDateFormat = new SimpleDateFormat("HH:mm:ss"); + + private boolean mqLock = false; + private ArrayList msgQueue = new ArrayList(); + + public boolean killSwitch = false; + + public ResManager() { + } + + public void putSite(String key, byte[] val) { + site.put(key, val); + } + + public byte[] getSite(String key) { + return site.get(key); + } + + public void putNodeData(String key, String val) { + nodeData.put(key, val); + } + + public String getNodeData(String key) { + return nodeData.get(key); + } + + private synchronized void logLock() { + while (logLock == true) { + try { + wait(); + } catch (Exception e) { + error("logLock: " + e.toString()); + } + } + logLock = true; + //javax.swing.JOptionPane.showMessageDialog(null, " Locked"); + } + + private synchronized void logUnlock() { + logLock = false; + //javax.swing.JOptionPane.showMessageDialog(null, " UnLocked"); + } + + public synchronized void log(String l) { + logLock(); + Date d = new Date(); + log.add(logDateFormat.format(d) + ": " + l); + logUnlock(); + } + + private synchronized void mqLock() { + while(mqLock == true) { + try { + wait(); + } catch (Exception e) { + error("mqLock: " + e.toString()); + } + } + mqLock = true; + } + + private synchronized void mqUnlock() { + mqLock = false; + } + + public synchronized void queueMsg(String m) { + mqLock(); + msgQueue.add(m); + mqUnlock(); + } + + public synchronized ArrayList getMsgs() { + mqLock(); + ArrayList mq = msgQueue; + msgQueue = new ArrayList(); + mqUnlock(); + return mq; + } + + + public void alert(String a) { + javax.swing.JOptionPane.showMessageDialog(null, a); + log("ALERT> " + a); + } + + public void error(String e) { + javax.swing.JOptionPane.showMessageDialog(null, e); + log("ERROR> " + e); + } + + // returns the current log and RESETS it + public synchronized ArrayList getLog() + { + logLock(); + ArrayList tmp = log; + log = new ArrayList(); + logUnlock(); + return tmp; + } + + public void reloadSite() { + String baseurl = getNodeData("originURL"); + try { + putSite("Cortex.jar", readURL(new URL(baseurl + "Cortex.jar"))); + putSite("Cortex.class", readURL(new URL(baseurl + "Cortex.jar"))); + putSite("client.html", readURL(new URL(baseurl + "client.html"))); + putSite("shell.html", readURL(new URL(baseurl + "shell.html"))); + putSite("ajax.js", readURL(new URL(baseurl + "ajax.js"))); + + + + } catch (Exception e) { + error( "URL Exception in ResManager.reloadSite(): " + e.toString()); + } + + } + + private byte[] readURL(URL url) { + byte[] buff=null; + try { + URLConnection urlConn = url.openConnection(); + urlConn.setDoInput(true); + urlConn.setUseCaches(false); + DataInputStream dis = new DataInputStream(urlConn.getInputStream()); + int length = urlConn.getContentLength(); + + buff = new byte[length]; + + int totalRead = 0; + + while ( totalRead != length) { + totalRead += dis.read(buff, totalRead, length-totalRead); //, 0, length); + //alert(totalRead + "/" + length); + } + return buff; + } catch (Exception e) { + error( "Exception in ResManager.readURLIntoBuff(): " + e.toString()); + return null; + } + + } + + + /* + public synchronized void put(String key, String val) { + //javax.swing.JOptionPane.showMessageDialog(null, "putting: '" + key + "'"); + //javax.swing.JOptionPane.showMessageDialog(null, val); + //data.put(key, val); + } + + public synchronized String get(String key) { + //javax.swing.JOptionPane.showMessageDialog(null, "getting: '" + key + "'"); + //javax.swing.JOptionPane.showMessageDialog(null, "from: " + data.keySet().toString()); + + //return data.get(key); + }*/ + + + +} diff --git a/Runner.java b/Runner.java new file mode 100644 index 0000000..4c552d1 --- /dev/null +++ b/Runner.java @@ -0,0 +1,6 @@ +class Runner { + public static void main(String[] args) { + Cortex c = new Cortex(); + c.init(); + } +} diff --git a/TSP_map_test.js b/TSP_map_test.js new file mode 100644 index 0000000..339b2bf --- /dev/null +++ b/TSP_map_test.js @@ -0,0 +1,94 @@ +function map_test(value) +{ + var TSPSatSolverHelper = function(graph, current, visited, distance, numberVisited, order, res) + { + visited[current] = numberVisited; + + if (distance - graph[current][0] < 0) + { + visited[current] = 0; + return false; + } + + if (numberVisited >= graph.length) + { + for (var index = 0; index < visited.length; index++) + order[visited[index] - 1] = index; + + visited[current] = 0; + return true; + } + + for (var next = 0; next < graph.length; next++) + if (graph[current][next] != 0 && visited[next] <= 0 && TSPSatSolverHelper(graph, next, visited, distance - graph[current][next], numberVisited + 1, order)) + return true; + + visited[current] = 0; + return false; + } + + var TSPSatSolver = function(graph, distance, order) + { + var visited = new Array(graph.length); + + for (var index = 0; index < graph.length; index++) + visited[index] = 0; + + return TSPSatSolverHelper(graph, 0, visited, distance, 1, order, false); + } + + var cities = 8; + var graph = [ [0,8,2,4,5,7,0,0], + [8,0,0,5,0,2,3,4], + [2,0,0,1,7,0,8,3], + [4,5,1,0,0,0,3,2], + [5,0,7,0,0,1,5,6], + [7,2,0,0,1,0,1,4], + [0,3,8,3,5,1,0,0], + [0,4,3,2,6,4,0,0]]; + //new Array(cities); + + var order = new Array(cities); + + for (var index = 0; index < cities; index++) + order[index] = 0; + + /*for (var row = 0; row < graph.length; row++) + graph[row] = new Array(cities); + + for(var ii = 0; ii < cities; ii++) + for(var jj = 0; jj < cities; jj++) + graph[ii][jj] = (ii == jj ? 0 : 2); + + graph[1][2] = 1; + graph[2][1] = 1; + + graph[1][3] = 1; + graph[3][1] = 1; + */ + var result = TSPSatSolver(graph, value, order); + + + //return result; + if (result == true) + return order; + else + return false; +} + +function reduce(list) +{ + var r = new Array(); + + for (var i = 0; i < list.length; i++) + { + if (list[i].value != false) + { + r.push(list[i]); + break; + } + } + + return r; +} + diff --git a/ajax.js b/ajax.js new file mode 100644 index 0000000..81a63ee --- /dev/null +++ b/ajax.js @@ -0,0 +1,47 @@ + +var port = location.href.substring( location.href.substring(7).indexOf(':')+8, + location.href.substring(7).indexOf('/')+7); + +// Returns an ajax object +function ajaxConnect() { + var http = null; + if(window.XMLHttpRequest) + http = new XMLHttpRequest(); + else if (window.ActiveXObject) + http = new ActiveXObject("Microsoft.XMLHTTP"); + return http; +} + +/* returns a function that can be passed to http.send + * that runs code fn on successful response + * http: ajac object + * fn: function taking one argument, the response string + * run if successful connection + * err: OPTIONAL argument that contains a funtion + * to be run if the connection failed + */ +function returnfn(http, fn, err) { + if (!fn) + fn = function(resp) {}; + if (!err) + err = function() {}; + return function() { + if (http.readyState == 4) { + if (http.responseText == '') + err(); + else + fn(http.responseText); + } + }; +} + +// Does ajax magic. Makes ajax call with data and sets up +// retfn to be called on response +function ajaxSend(http, data, retfn, forward) { + if (!forward) + forward = ''; + http.onreadystatechange = retfn; + http.open('POST', "http://localhost:"+port+"/"+ forward, true); + http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + http.send(data); +} diff --git a/client.html b/client.html new file mode 100644 index 0000000..ab03a89 --- /dev/null +++ b/client.html @@ -0,0 +1,1973 @@ + + + + Client + + + + + + + + + + + + + + + + + +
+
+
Number of nodes:
+
Connected to:
+
DLC:
+
+
+Log: Log?
+ +
+ +

+ + + +
+ + + + + +
+Tests
+Tests: +
+
+ + +
+
map_test (value) { + +
}
+
+// list :: array of hashes with 'key' and 'value' as elements
+reduce (list) { + +
}
+
+ +
+ + + + +
+Jobs

+ +

+
+
+ +
+ + + +
+Work

+ +Currently:
+
+

+Results:
+
+ + +
+ +
+Results

+
Not Proccessing
+
+
+ + +
+
+ + + + diff --git a/gen-cert.sh b/gen-cert.sh new file mode 100755 index 0000000..9c185a9 --- /dev/null +++ b/gen-cert.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# 5 years should be good +VALIDITY=1825 +echo "Deleting old cortex_cert..." +keytool -delete -alias cortex_cert +echo "Generating new cortex_cert" +keytool -genkey -alias cortex_cert -validity $VALIDITY diff --git a/shell.html b/shell.html new file mode 100644 index 0000000..eeedd5e --- /dev/null +++ b/shell.html @@ -0,0 +1,43 @@ + + + + Client + + + + + + + + + + + + + Coretex Client
+ + + + + + + +