Added new websocket files.
diff --git a/js/testing/test-encode-decode-ContentObject-bis.html b/js/testing/test-encode-decode-ContentObject-bis.html
index 4a8ee43..4bbebe4 100644
--- a/js/testing/test-encode-decode-ContentObject-bis.html
+++ b/js/testing/test-encode-decode-ContentObject-bis.html
@@ -36,6 +36,9 @@
 	

 	<script type="text/javascript" src="../encoding/DataUtils.js"></script>

 	

+	<script type="text/javascript" src="../encoding/EncodingUtils.js"></script>

+

+	

 	<script language="JavaScript" type="text/javascript" src="../security/KeyManager.js"></script>

 	

 	<script language="JavaScript" type="text/javascript" src="../securityLib/jsbn.js"></script>

@@ -58,7 +61,7 @@
 	<script type="text/javascript">

 	

 		function encode(){

-			var contentname = new Name( createNameArray(document.getElementById('contentname').value) );

+			var contentname = new Name( Name.createNameArray(document.getElementById('contentname').value) );

 			

 			var content = document.getElementById('content').value;

 			

@@ -119,21 +122,21 @@
 					output+= "<br />";

 				}

 				if(co.content !=null){

-					output += "CONTENT(hex): "+ toHex(co.content);

+					output += "CONTENT(hex): "+ DataUtils.toHex(co.content);

 					

 					output+= "<br />";

 					output+= "<br />";

 				}

 				if(co.signature !=null && co.signature.signature!=null){

 					

-					output += "SIGNATURE(hex): "+ toHex(co.signature.signature);

+					output += "SIGNATURE(hex): "+ DataUtils.toHex(co.signature.signature);

 					

 					output+= "<br />";

 					output+= "<br />";

 				}

 				if(co.signedInfo !=null && co.signedInfo.publisher!=null && co.signedInfo.publisher.publisherPublicKeyDigest!=null){

 					

-					output += "Publisher Public Key Digest(hex): "+ toHex(co.signedInfo.publisher.publisherPublicKeyDigest);

+					output += "Publisher Public Key Digest(hex): "+ DataUtils.toHex(co.signedInfo.publisher.publisherPublicKeyDigest);

 					

 					output+= "<br />";

 					output+= "<br />";

@@ -148,10 +151,10 @@
 				if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.publicKey!=null){

 					

 					var publickey = rstr2b64(toString(co.signedInfo.locator.publicKey));

-					var publickeyHex = toHex(co.signedInfo.locator.publicKey).toLowerCase();

+					var publickeyHex = DataUtils.toHex(co.signedInfo.locator.publicKey).toLowerCase();

 					var publickeyString = toString(co.signedInfo.locator.publicKey);

 					

-					var signature = toHex(co.signature.signature).toLowerCase();

+					var signature = DataUtils.toHex(co.signature.signature).toLowerCase();

 					

 					

 					var input = toString(co.rawSignatureData);

diff --git a/js/testing/test-get-async.html b/js/testing/test-get-async.html
new file mode 100644
index 0000000..fc7d84a
--- /dev/null
+++ b/js/testing/test-get-async.html
@@ -0,0 +1,56 @@
+<?xml version = "1.0" encoding="utf-8" ?>

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

+"DTD/xhtml1-strict.dtd">

+<html xmlns = "http://www.w3.org/1999/xhtml">

+<meta charset="UTF-8">

+

+<head>

+	<title>NDN Get via WebSocket</title>

+	

+	<script type="text/javascript" src="../Helper.js"></script>

+

+	<script type="text/javascript">

+		var ndn = new NDN();

+        ndn.connectWebSocket();

+        

+        var AsyncGetClosure = function AsyncGetClosure() {

+        	// Inherit from Closure.

+			Closure.call(this);

+		};

+		

+		AsyncGetClosure.prototype.upcall = function(kind, upcallInfo) {

+			if (kind == Closure.UPCALL_FINAL) {

+				// Do nothing.

+			} else if (kind == Closure.UPCALL_CONTENT) {

+				console.log("Closure.upcall() executed.");

+				var content = upcallInfo.contentObject;

+				nameStr = escape(content.name.getName());

+				console.log("In callback, nameStr: " + nameStr);

+				console.log("In callback, content: ");

+				console.log(content);

+				document.getElementById('content').innerHTML = contentObjectToHtml(content);

+			}

+			return Closure.RESULT_OK;

+		};

+		

+		

+		function run() {

+			ndn.expressInterestWS(document.getElementById('interest').value, new AsyncGetClosure(), null);

+		}

+		

+	</script>

+	

+</head>

+<body >

+

+	<form>

+		Please Enter an Interest:<br />

+		<input id="interest" type="text" name="INTEREST" size="50" value="/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY" /> 

+	</form>

+

+	<button onclick="run()">Fetch Content</button>

+	

+	<p id="content">Content: <br/></p>

+

+</body>

+</html>

diff --git a/js/testing/test-put-async.html b/js/testing/test-put-async.html
new file mode 100644
index 0000000..f94d2b6
--- /dev/null
+++ b/js/testing/test-put-async.html
@@ -0,0 +1,92 @@
+<?xml version = "1.0" encoding="utf-8" ?>

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

+"DTD/xhtml1-strict.dtd">

+<html xmlns = "http://www.w3.org/1999/xhtml">

+<meta charset="UTF-8">

+

+

+<head>

+	<title>NDN Put via WebSocket</title>

+	

+	<script type="text/javascript" src="../Helper.js"></script>	

+	

+	<script type="text/javascript">

+		var ndn = new NDN();

+        ndn.connectWebSocket();

+        

+        var AsyncPutClosure = function AsyncPutClosure() {

+        	// Inherit from Closure.

+			Closure.call(this);

+		};

+		

+		AsyncPutClosure.prototype.upcall = function(kind, upcallInfo) {

+			if (kind == Closure.UPCALL_FINAL) {

+				// Do nothing.

+			} else if (kind == Closure.UPCALL_INTEREST) {

+				// Extract the Name from the Interest. var name = upcallInfo.Interest.name;Íž

+				// Check that we want to respond to upcallInfo.interest. If yes, construct a ContentObject

+				// response, put it to the NDN and return Closure.RESULT_INTEREST_CONSUMED. Else fall 

+				// through to return Content.RESULT_OK.

+				// See linemaker.py for more details.

+				console.log('AsyncPutClosure.upcall() called.');

+				var content = document.getElementById('content').value;

+				var interest = upcallInfo.interest;

+				nameStr = escape(interest.name.getName());

+				

+				var si = new SignedInfo();

+				si.setFields();

+				

+				var answer = DataUtils.toNumbersFromString(content);

+				

+				var co = new ContentObject(new Name(nameStr), si, answer, new Signature()); 

+				co.sign();

+				var hex = encodeToHexContentObject(co);

+				

+				var bytearray = new Uint8Array(hex.length / 2);

+	    		for (var i = 0; i < hex.length; i = i + 2) {

+	        		bytearray[i / 2] = '0x' + hex.substr(i, 2);

+	    		}

+	    		

+	    		upcallInfo.ndn.ws.send(bytearray.buffer);

+	    		console.log('ws.send() finised.');

+	    		

+	    		return Closure.RESULT_INTEREST_CONSUMED;

+			}

+			return Closure.RESULT_OK;

+		};

+        

+		

+		function run() {

+			var contentName = document.getElementById('contentname').value;		

+			

+			result = ndn.registerPrefixWS(contentName, new AsyncPutClosure(), null);

+			

+			document.getElementById('result').innerHTML = 'Content name \'' + contentName 

+					+'\' published. Result: ' + result;

+		}

+	

+		</script>

+	

+</head>

+<body >

+	<form>

+	<div>

+		<p>Please Enter a Content Name:</p>

+		

+		<input id="contentname" type="text" name="CONTENTNAME" value="/wentao.shang/regtest001" /> 

+		

+                <p>Please Enter the Content:</p>

+		

+		<textarea id="content" cols="40" rows="5" name="CONTENT" >This works!</textarea> 

+		

+		<br />

+		</div>

+	</form>

+	<div>

+		<button onclick="run()">Publish Content</button>

+	</div>

+	

+	<p id="result"></p>

+

+</body>

+</html>
\ No newline at end of file
diff --git a/js/testing/test-websocket.html b/js/testing/test-websocket.html
new file mode 100644
index 0000000..d6530cb
--- /dev/null
+++ b/js/testing/test-websocket.html
@@ -0,0 +1,51 @@
+<?xml version = "1.0" encoding="utf-8" ?>

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

+"DTD/xhtml1-strict.dtd">

+<html xmlns = "http://www.w3.org/1999/xhtml">

+

+<head>

+	<title>Test WebSocket Support</title>

+

+	<script type="text/javascript">

+	

+		function test(){

+			var output = "";

+			

+			if ('WebSocket' in window) {

+				output += "This browser support WebSocket.";

+			} else {

+				output += "No WebSocket support.";

+			}

+			

+			document.getElementById('result').innerHTML += output;

+			

+			console.log("starting websocket...");

+			if ("WebSocket" in window) {

+			    var ws = new WebSocket("ws://localhost:9696");

+			    

+			    ws.onopen = function() {

+			        console.log("WebSockets connection opened");

+			        ws.send("Hello Server (from client).");

+			    }

+			    ws.onmessage = function(e) {

+			        console.log("Got from server: " + e.data);

+			    }

+			    ws.onclose = function() {

+			        console.log("WebSockets connection closed");

+			    }

+			} else {

+			    alert("No WebSockets support");

+			}

+

+		}

+

+	</script>

+

+</head>

+<body >

+	<button onclick="test()">Test Now!</button>

+	

+	<p id="result">Result here: </p>

+

+</body>

+</html>

diff --git a/wsproxy/README.md b/wsproxy/README.md
new file mode 100644
index 0000000..eb0cdc0
--- /dev/null
+++ b/wsproxy/README.md
@@ -0,0 +1,10 @@
+ws-ndn-js
+=========
+
+WebSocket proxy server between NDN javascript stack and ccnd
+
+This proxy runs on top of 'node.js'. 'ws' package is required. It listens for WebSocket connection request on port number 9696. Once it receives a incoming connection, it issues a TCP connection to the specified 'ccnd' router (port number 9695). It then translates packet frames from WebSocket to pure TCP byte streams and vice versa.
+
+To run the proxy, simply use the command 'node ws-ndn.js'.
+
+Acknowledgement: this code is extended from Junxiao's WebSocket proxy implementation (https://gist.github.com/3835425).
\ No newline at end of file
diff --git a/wsproxy/ws-ndn.js b/wsproxy/ws-ndn.js
new file mode 100644
index 0000000..2b67e0d
--- /dev/null
+++ b/wsproxy/ws-ndn.js
@@ -0,0 +1,80 @@
+var WebSocketServer = require('ws').Server;
+var net = require('net');
+
+var wss = new WebSocketServer({port:9696, host:'0.0.0.0'});
+
+var MaxNumOfClients = 2;
+
+wss.on('connection', function(ws) {
+	console.log('WebSocket client connection received.');
+	console.log('Number of clients now is ' + wss.clients.length);
+	
+	if (wss.clients.length > MaxNumOfClients) {
+		console.log('Max num of clients exceeded. Close WS connection now.');
+		ws.terminate();
+		return;
+	}
+	
+	var sock_ready = false;
+	var send_queue = [];
+	var sock = net.createConnection(9695);
+	
+	ws.on('message', function(message) {
+		if (typeof message == 'string')
+			console.log("Message from clinet: " + message);
+		else if (typeof message == 'object') {
+			var bytesView = new Uint8Array(message);
+
+			var logMsg = 'Byte array from client: ';
+			for (var i = 0; i < bytesView.length; i++)
+				logMsg += String.fromCharCode(bytesView[i]);
+			console.log(logMsg);
+			
+			if (sock_ready) {
+				sock.write(bytesView.buffer);
+				console.log('sock.write() returned.');
+			} else {
+				send_queue.push(message);
+			}
+		}
+	});
+	
+	ws.on('close', function() {
+		console.log('WebSocket connection closed.');
+		sock.end();
+	});
+	
+	sock.on('connect', function() {
+		while (send_queue.length > 0) {
+			var message = send_queue.shift();
+			sock.write(message);
+		}
+		sock_ready = true;
+		console.log('ccnd socket connection ready.');
+	});
+	
+	sock.on('data', function(data) {
+		if (typeof data == 'object') {
+			var bytesView = new Uint8Array(data);
+			
+			console.log('Byte array from server: ');
+			var logMsg = "";
+			for (var i = 0; i < bytesView.length; i++)
+				logMsg += String.fromCharCode(bytesView[i]);
+			console.log(logMsg);
+			
+			ws.send(bytesView.buffer, {binary: true, mask: false});
+			console.log('ws.send() returned.');
+		}
+	});
+	
+	sock.on('end', function() {
+		console.log('TCP connection terminated by ccnd. Shut down WS connection to client.');
+		ws.terminate();
+	});
+	
+	sock.on('error', function() {
+		console.log('Error on TCP connection to ccnd. Shut down WS connection to client.');
+		ws.terminate();
+	});
+});
diff --git a/wsproxy/wsproxy-udp.js b/wsproxy/wsproxy-udp.js
new file mode 100644
index 0000000..bec9421
--- /dev/null
+++ b/wsproxy/wsproxy-udp.js
@@ -0,0 +1,110 @@
+var WebSocketServer = require('ws').Server;
+var dgram = require('dgram');
+
+var ccndhost = 'localhost';
+
+var wss = new WebSocketServer({port:9696, host:ccndhost});
+
+var MaxNumOfClients = 2;
+
+wss.on('connection', function(ws) {
+	console.log('wss.onconnection: WebSocket client connection received.');
+	console.log('wss.onconnection: Number of clients now is ' + wss.clients.length);
+	
+	if (wss.clients.length > MaxNumOfClients) {
+		console.log('wss.onconnection: Max num of clients exceeded. Close WS connection now.');
+		ws.terminate();
+		return;
+	}
+	
+	var udp = dgram.createSocket("udp4");
+	
+	/*
+	 * According to the email discussion with Michael, when we use
+	 * UDP to connect to ccnd, we MUST first send a 'heartbeat' 
+	 * UDP packet with 1-byte payload (content of this byte can 
+	 * be random). The purpose of this packet is to let ccnd 
+	 * mark the incoming FACE as 'friendly' (with CCN_FACE_GG 
+	 * flag set). We also need to periodically send this 'heartbeat' 
+	 * packet every few seconds to keep ccnd from recycling the UDP 
+	 * face. Michael recomended 8 seconds interval. 
+	 *      --Wentao
+	 */
+	// Send 'heartbeat' packet now
+	var heartbeat = new Buffer(1);
+	heartbeat[0] = 0x21;
+	udp.send(heartbeat, 0, 1, 9695, ccndhost, null);
+	
+	// Schedule a timer to send 'heartbeat' periodically
+	var timerID = setInterval(function() {
+		if (udp == null || udp == undefined)
+			return;
+		
+		var hb = new Buffer(1);
+		hb[0] = 0x21;
+		udp.send(hb, 0, 1, 9695, ccndhost, null);
+		//console.log('UDP heartbeat fired at ccnd.');
+	}, 
+	8000 // 8000 ms delay
+	);
+	
+	ws.on('message', function(message) {
+		if (typeof message == 'string')
+			console.log("ws.onmessage: Message from clinet: " + message);
+		else if (typeof message == 'object') {
+			// From JS array to Buffer
+			var buffer = new Buffer(message);
+
+			var logMsg = 'ws.onmessage: Byte array from client: ';
+			for (var i = 0; i < buffer.length; i++)
+				logMsg += String.fromCharCode(buffer[i]);
+			console.log(logMsg);
+			
+			udp.send(buffer, 0, buffer.length, 9695, ccndhost, null);
+			console.log('ws.onmessage: udp.send() returned.');
+		}
+	});
+	
+	ws.on('close', function() {
+		console.log('ws.onclose: WebSocket connection closed. Close UDP connection to ccnd and stop "heartbeat" timer.');
+		clearInterval(timerID);
+		udp.close();
+		udp = null;
+	});
+	
+	udp.on('message', function(msg, rinfo) {
+		if (typeof msg == 'object') {
+			// From Buffer to ArrayBuffer
+			var bytesView = new Uint8Array(msg);
+			
+			console.log('udp.onmessage: Byte array from server: ');
+			console.log('udp.onmessage: bytesView.length ' + bytesView.length);
+			var logMsg = "";
+			for (var i = 0; i < bytesView.length; i++)
+				logMsg += String.fromCharCode(bytesView[i]);
+			console.log(logMsg);
+			
+			ws.send(bytesView.buffer, {binary: true, mask: false});
+			console.log('udp.onmessage: ws.send() returned.');
+		}
+	});
+	
+	// Actually the socket close by ccnd will not cause the 'close' event to raise.
+	// So this event handle is only called when the client browser shuts down the WS
+	// connection, causing ws 'close' event to raise. In that event handle, we explicitly 
+	// call udp.close(). So in this function we can do nothing. Anyway, here we clear the 
+	// timer and terminate ws for a second time since that will not throw exception. 'ws'
+	// will check the 'readyState' before closing, therefore avoids 'close' event loop.
+	//     --Wentao
+	udp.on('close', function() {
+		console.log('udp.onclose: UDP connection to ccnd terminated. Shut down WS connection to client and stop "heartbeat" timer.');
+		clearInterval(timerID);
+		ws.terminate();
+	});
+	
+	udp.on('error', function() {
+		console.log('udp.onerror: Error on UDP connection to ccnd. Shut down WS connection to client and stop "heartbeat" timer.');
+		clearInterval(timerID);
+		ws.terminate();
+	});
+});