Merge branch 'master' of https://github.com/remap/ndn-js
diff --git a/.DS_Store b/.DS_Store
index e6cf14d..5d54f89 100644
--- a/.DS_Store
+++ b/.DS_Store
Binary files differ
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e43b0f9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+.DS_Store
diff --git a/js/.DS_Store b/js/.DS_Store
index 3aa25a9..80e2e80 100644
--- a/js/.DS_Store
+++ b/js/.DS_Store
Binary files differ
diff --git a/js/WebSocketTransport.js b/js/WebSocketTransport.js
index 49c09a4..83f53d9 100644
--- a/js/WebSocketTransport.js
+++ b/js/WebSocketTransport.js
@@ -161,7 +161,6 @@
bytes.set(hex);
self.ws.send(bytes.buffer);
- console.log('ws.onopen: ws.send() returned.');
}
this.ws.onerror = function(ev) {
@@ -236,6 +235,13 @@
interest.scope = 1;
//var hex = encodeToHexInterest(int);
var binaryInterest = encodeToBinaryInterest(interest);
+ // If we directly use binaryInterest.buffer to feed ws.send(),
+ // WebSocket will end up sending a packet with 10000 bytes of data.
+ // That is, WebSocket will flush the entire buffer in BinaryXMLEncoder
+ // regardless of the offset of the Uint8Array. So we have to create
+ // a new Uint8Array buffer with just the right size and copy the
+ // content from binaryInterest to the new buffer.
+ // ---Wentao
var bytearray = new Uint8Array(binaryInterest.length);
bytearray.set(binaryInterest);
console.log('Send Interest registration packet.');
@@ -244,7 +250,6 @@
CSTable.push(csEntry);
this.ws.send(bytearray.buffer);
- console.log('ws.send() returned.');
return 0;
} else {
diff --git a/js/testing/.DS_Store b/js/testing/.DS_Store
index c13445d..3f0e7ef 100644
--- a/js/testing/.DS_Store
+++ b/js/testing/.DS_Store
Binary files differ
diff --git a/js/testing/test-get-async.html b/js/testing/test-get-async.html
index f93db6c..cd19c9c 100644
--- a/js/testing/test-get-async.html
+++ b/js/testing/test-get-async.html
@@ -10,7 +10,7 @@
<script type="text/javascript" src="../Helper.js"></script>
<script type="text/javascript">
- var ndn = new NDN();
+ var ndn = new NDN({port:9696});
ndn.transport.connectWebSocket(ndn);
var AsyncGetClosure = function AsyncGetClosure() {
diff --git a/js/testing/test-put-async.html b/js/testing/test-put-async.html
index 315dec8..cece056 100644
--- a/js/testing/test-put-async.html
+++ b/js/testing/test-put-async.html
@@ -23,11 +23,6 @@
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;
@@ -40,17 +35,21 @@
var co = new ContentObject(new Name(nameStr), si, answer, new Signature());
co.sign();
- var hex = encodeToHexContentObject(co);
+ var coBinary = encodeToBinaryContentObject(co);
+ // If we directly use coBinary.buffer to feed ws.send(), WebSocket
+ // will end up sending a packet with 10000 bytes of data. That
+ // is, WebSocket will flush the entire buffer in BinaryXMLEncoder
+ // regardless of the offset of the Uint8Array. So we have to
+ // create a new Uint8Array buffer with just the right size and
+ // copy the content from coBinary to the new buffer.
+ // ---Wentao
+ var bytearray = new Uint8Array(coBinary.length);
+ bytearray.set(coBinary);
- 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.transport.ws.send(bytearray.buffer);
- console.log('ws.send() finised.');
-
- return Closure.RESULT_INTEREST_CONSUMED;
+ upcallInfo.ndn.transport.ws.send(bytearray.buffer);
+ console.log('ws.send() finised.');
+
+ return Closure.RESULT_INTEREST_CONSUMED;
}
return Closure.RESULT_OK;
};
diff --git a/wsproxy/.gitignore b/wsproxy/.gitignore
new file mode 100644
index 0000000..ce380c6
--- /dev/null
+++ b/wsproxy/.gitignore
@@ -0,0 +1,2 @@
+node_modules/*
+.DS_Store
diff --git a/wsproxy/README.md b/wsproxy/README.md
index eb0cdc0..89078e9 100644
--- a/wsproxy/README.md
+++ b/wsproxy/README.md
@@ -1,10 +1,25 @@
ws-ndn-js
=========
-WebSocket proxy server between NDN javascript stack and ccnd
+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.
+This proxy runs on top of 'node.js'. 'ws' and 'node-getopt' packages are 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'.
+Installation guide:
+
+1) node.js: go to http://nodejs.org/ to download and install node.js;
+2) ws package: use command 'npm install ws' or go to https://github.com/einaros/ws for more information;
+3) node-getopt package: use command 'npm install node-getopt' or go to https://npmjs.org/package/node-getopt for more information.
+
+
+To run the proxy, simply use the command 'node wsproxy-tcp.js' or 'node wsproxy-udp.js'.
+To specify remote ccnd router's hostname or ip address, use option '-c x.x.x.x'. Default is 'localhost'.
+To specify the port number on which the proxy will listen, use option '-p xxxx'. Default is 9696.
+To specify maximum number of concurrent clients, use option '-m N'. Default is 40.
+To specify the level of log info display, use option '-L x'. x=0 means no output; x=1 will log connection startup and close; x=2 will log contents of all messages that flow across the proxy. Default is 1.
+
+Example: to setup UDP connection to ccnd router 192.168.1.51 with max client number 50 and log level 2, use the command:
+
+node wsproxy-udp.js -c 192.168.1.51 -m 50 -L 2
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
deleted file mode 100644
index 2b67e0d..0000000
--- a/wsproxy/ws-ndn.js
+++ /dev/null
@@ -1,80 +0,0 @@
-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-tcp.js b/wsproxy/wsproxy-tcp.js
new file mode 100644
index 0000000..fe4f816
--- /dev/null
+++ b/wsproxy/wsproxy-tcp.js
@@ -0,0 +1,114 @@
+/*
+ * @author: Wentao Shang
+ * See COPYING for copyright and distribution information.
+ * Implement WebSocket proxy between ccnd and javascript stack.
+ */
+
+var WebSocketServer = require('ws').Server;
+var net = require('net');
+
+var opt = require('node-getopt').create([
+ ['c' , 'ccnd=ARG', 'host name or ip of ccnd router'],
+ ['p' , 'port=ARG', 'port number on which the proxy will listen'],
+ ['m' , 'maxclient=ARG', 'maximum number of concurrent client'],
+ ['L' , 'LOG=ARG', 'level of log message display'],
+ ['h' , 'help', 'display this help']
+]) // create Getopt instance
+.bindHelp() // bind option 'help' to default action
+.parseSystem(); // parse command line
+
+//console.log(opt);
+
+var ccndhost = opt.options.ccnd || 'localhost';
+//console.log(ccndhost);
+
+var wsport = opt.options.port || 9696;
+//console.log(wsport);
+
+var wss = new WebSocketServer({port:wsport, host:'0.0.0.0'}); // Set host to '0.0.0.0' so that we can accept connections from anywhere
+ // This host has nothing to do with ccndhost.
+
+var MaxNumOfClients = opt.options.maxclient || 40;
+//console.log(MaxNumOfClients);
+
+var LOG = opt.options.LOG || 1;
+//console.log(LOG);
+
+if (LOG > 0) console.log('WebSocketServer started...');
+
+wss.on('connection', function(ws) {
+ if (LOG > 0) console.log('WebSocket client connection received.');
+ if (LOG > 0) console.log('Number of clients now is ' + wss.clients.length);
+
+ if (wss.clients.length > MaxNumOfClients) {
+ if (LOG > 0) console.log('Max num of clients exceeded. Close WS connection now.');
+ ws.terminate();
+ return;
+ }
+
+ var sock_ready = false;
+ var send_queue = [];
+ var sock = net.connect({port: 9695, host: ccndhost});
+
+ ws.on('message', function(message) {
+ if (typeof message == 'string') {
+ if (LOG > 1) console.log("Message from clinet: " + message);
+ }
+ else if (typeof message == 'object') {
+ var bytesView = new Uint8Array(message);
+
+ if (LOG > 1) {
+ 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);
+ } else {
+ send_queue.push(message);
+ }
+ }
+ });
+
+ ws.on('close', function() {
+ if (LOG > 0) 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;
+ if (LOG > 0) console.log('ccnd socket connection ready.');
+ });
+
+ sock.on('data', function(data) {
+ if (typeof data == 'object') {
+ var bytesView = new Uint8Array(data);
+
+ if (LOG > 1) {
+ 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});
+ }
+ });
+
+ sock.on('end', function() {
+ if (LOG > 0) console.log('TCP connection terminated by ccnd. Shut down WS connection to client.');
+ ws.terminate();
+ });
+
+ sock.on('error', function() {
+ if (LOG > 0) 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
index bec9421..b81e2bd 100644
--- a/wsproxy/wsproxy-udp.js
+++ b/wsproxy/wsproxy-udp.js
@@ -1,18 +1,40 @@
+/*
+ * @author: Wentao Shang
+ * See COPYING for copyright and distribution information.
+ * Implement WebSocket proxy between ccnd and javascript stack.
+ */
+
var WebSocketServer = require('ws').Server;
var dgram = require('dgram');
-var ccndhost = 'localhost';
+var opt = require('node-getopt').create([
+ ['c' , 'ccnd=ARG', 'host name or ip of ccnd router'],
+ ['p' , 'port=ARG', 'port number on which the proxy will listen'],
+ ['m' , 'maxclient=ARG', 'maximum number of concurrent client'],
+ ['L' , 'LOG=ARG', 'level of log message display'],
+ ['h' , 'help', 'display this help']
+]) // create Getopt instance
+.bindHelp() // bind option 'help' to default action
+.parseSystem(); // parse command line
-var wss = new WebSocketServer({port:9696, host:ccndhost});
+var ccndhost = opt.options.ccnd || 'localhost';
+var wsport = opt.options.port || 9696;
-var MaxNumOfClients = 2;
+var wss = new WebSocketServer({port:wsport, host:'0.0.0.0'}); // Set host to '0.0.0.0' so that we can accept connections from anywhere
+ // This host has nothing to do with ccndhost.
+
+var MaxNumOfClients = opt.options.maxclient || 40;
+
+var LOG = opt.options.LOG || 1;
+
+if (LOG > 0) console.log('WebSocketServer started...');
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 (LOG > 0) console.log('wss.onconnection: WebSocket client connection received.');
+ if (LOG > 0) 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.');
+ if (LOG > 0) console.log('wss.onconnection: Max num of clients exceeded. Close WS connection now.');
ws.terminate();
return;
}
@@ -43,30 +65,32 @@
var hb = new Buffer(1);
hb[0] = 0x21;
udp.send(hb, 0, 1, 9695, ccndhost, null);
- //console.log('UDP heartbeat fired at ccnd.');
+ if (LOG > 1) 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);
+ if (typeof message == 'string') {
+ if (LOG > 2) 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);
+ if (LOG > 2) {
+ 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.');
+ if (LOG > 0) console.log('ws.onclose: WebSocket connection closed. Close UDP connection to ccnd and stop "heartbeat" timer.');
clearInterval(timerID);
udp.close();
udp = null;
@@ -77,15 +101,16 @@
// 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);
+ if (LOG > 2) {
+ 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.');
}
});
@@ -97,13 +122,13 @@
// 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.');
+ if (LOG > 0) 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.');
+ if (LOG > 0) console.log('udp.onerror: Error on UDP connection to ccnd. Shut down WS connection to client and stop "heartbeat" timer.');
clearInterval(timerID);
ws.terminate();
});