Added Closure.js. Put expressInterest in NDN.js. Use it in ccnxProtocolService.js.
diff --git a/js/Closure.js b/js/Closure.js
new file mode 100644
index 0000000..909c3c8
--- /dev/null
+++ b/js/Closure.js
@@ -0,0 +1,62 @@
+/*
+ * @author: ucla-cs
+ * See COPYING for copyright and distribution information.
+ * Provide the callback closure for the async communication methods in the NDN class.
+ * This is a port of Closure.py from PyCCN, written by:
+ * Derek Kulinski <takeda@takeda.tk>
+ * Jeff Burke <jburke@ucla.edu>
+ */
+
+/*
+ * Create a subclass of Closure and pass an object to async calls.
+ */
+var Closure = function Closure() {
+ // I don't think storing NDN's closure is needed
+ // and it creates a reference loop, as of now both
+ // of those variables are never set -- Derek
+ //
+ // Use instance variables to return data to callback
+ this.ndn_data = null; // this holds the ndn_closure
+ this.ndn_data_dirty = false;
+};
+
+// Upcall result
+Closure.RESULT_ERR = -1; // upcall detected an error
+Closure.RESULT_OK = 0; // normal upcall return
+Closure.RESULT_REEXPRESS = 1; // reexpress the same interest again
+Closure.RESULT_INTEREST_CONSUMED = 2; // upcall claims to consume interest
+Closure.RESULT_VERIFY = 3; // force an unverified result to be verified
+
+// Upcall kind
+Closure.UPCALL_FINAL = 0; // handler is about to be deregistered
+Closure.UPCALL_INTEREST = 1; // incoming interest
+Closure.UPCALL_CONSUMED_INTEREST = 2; // incoming interest, someone has answered
+Closure.UPCALL_CONTENT = 3; // incoming verified content
+Closure.UPCALL_INTEREST_TIMED_OUT = 4; // interest timed out
+Closure.UPCALL_CONTENT_UNVERIFIED = 5; // content that has not been verified
+Closure.UPCALL_CONTENT_BAD = 6; // verification failed
+
+/*
+ * Override this in your subclass.
+ * If you're getting strange errors in upcall()
+ * check your code whether you're returning a value.
+ */
+Closure.prototype.upcall = function(kind, upcallInfo) {
+ //dump('upcall ' + this + " " + kind + " " + upcallInfo + "\n");
+ return Closure.RESULT_OK;
+};
+
+var UpcallInfo = function UpcallInfo(ndn, interest, matchedComps, contentObject) {
+ this.ndn = ndn; // NDN object (not used)
+ this.interest = interest; // Interest object
+ this.matchedComps = matchedComps; // int
+ this.contentObject = contentObject; // Content object
+};
+
+UpcallInfo.prototype.toString = function() {
+ var ret = "ndn = " + this.ndn;
+ ret += "\nInterest = " + this.interest;
+ ret += "\nmatchedComps = " + this.matchedComps;
+ ret += "\nContentObject: " + this.contentObject;
+ return ret;
+}
diff --git a/js/NDN.js b/js/NDN.js
index 2b32df8..1202f08 100644
--- a/js/NDN.js
+++ b/js/NDN.js
@@ -72,7 +72,6 @@
}
-
NDN.prototype.put = function(name,content){
if(this.host!=null && this.port!=null){
@@ -149,13 +148,60 @@
return result;
}
else{
-
-
console.log('ERROR URL OR PORT NOT SET');
return null;
-
}
-
+}
-}
\ No newline at end of file
+/** Encode name as an Interest. If template is not null, use its attributes.
+ * Send the interest to host:port, read the entire response and call
+ * closure.upcall(Closure.UPCALL_CONTENT (or Closure.UPCALL_CONTENT_UNVERIFIED),
+ * new UpcallInfo(this, interest, 0, contentObject)).
+ */
+NDN.prototype.expressInterest = function(
+ // Name
+ name,
+ // Closure
+ closure,
+ // Interest
+ template) {
+ if (this.host == null || this.port == null) {
+ dump('ERROR host OR port NOT SET\n');
+ return;
+ }
+
+ interest = new Interest(name);
+ if (template != null) {
+ // TODO: Exactly what do we copy from template?
+ interest.InterestLifetime = template.InterestLifetime;
+ }
+ else
+ interest.InterestLifetime = 4200;
+ var outputHex = encodeToHexInterest(interest);
+
+ var dataListener = {
+ onReceivedData : function(result) {
+ if (result == null || result == undefined || result.length == 0)
+ listener.onReceivedContentObject(null);
+ else {
+ var decoder = new BinaryXMLDecoder(result);
+ var co = new ContentObject();
+ co.from_ccnb(decoder);
+
+ if(LOG>2) {
+ dump('DECODED CONTENT OBJECT\n');
+ dump(co);
+ dump('\n');
+ }
+
+ // TODO: verify the content object and set kind to UPCALL_CONTENT.
+ closure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED,
+ new UpcallInfo(this, interest, 0, co))
+ }
+ }
+ }
+
+ return getAsync(this.host, this.port, outputHex, dataListener);
+};
+
diff --git a/js/NDNSocketTransportService.js b/js/NDNSocketTransportService.js
index aa12588..1f8a93d 100644
--- a/js/NDNSocketTransportService.js
+++ b/js/NDNSocketTransportService.js
@@ -63,7 +63,7 @@
// Finish.
this.onStopRequest();
} catch (ex) {
- dump("onDataAvailable exception: " + ex + "\n");
+ dump("readAllFromSocket.onDataAvailable exception: " + ex + "\n");
}
}
};
@@ -71,50 +71,3 @@
pump.init(inStream, -1, -1, 0, 0, true);
pump.asyncRead(dataListener, null);
}
-
-
-// TODO: This should be moved to the main NDN.js when we agree on how to do non-blocking get.
-// For now, assume this is included after NDN.js and modify it.
-/** Encode message as an Interest, send it to host:port, read the entire response and call
- listener.onReceivedContentObject(contentObject).
- */
-NDN.prototype.getAsync = function(message, listener) {
- if (this.host != null && this.port != null) {
- var output ='';
- message = message.trim();
- if(message==null || message =="" ){
- dump('INVALID INPUT TO GET\n');
- return null;
- }
-
- interest = new Interest(new Name(message));
- interest.InterestLifetime = 4200;
- var outputHex = encodeToHexInterest(interest);
-
- var dataListener = {
- onReceivedData : function(result) {
- if (result == null || result == undefined || result.length == 0)
- listener.onReceivedContentObject(null);
- else {
- var decoder = new BinaryXMLDecoder(result);
- var co = new ContentObject();
- co.from_ccnb(decoder);
-
- if(LOG>2) {
- dump('DECODED CONTENT OBJECT\n');
- dump(co);
- dump('\n');
- }
-
- listener.onReceivedContentObject(co);
- }
- }
- }
-
- return getAsync(this.host, this.port, outputHex, dataListener);
- }
- else {
- dump('ERROR host OR port NOT SET\n');
- }
-}
-
diff --git a/js/ccnxProtocol.xpi b/js/ccnxProtocol.xpi
index 9fd4dbb..45cb47f 100644
--- a/js/ccnxProtocol.xpi
+++ b/js/ccnxProtocol.xpi
Binary files differ
diff --git a/js/ccnxProtocol/components/ccnxProtocolService.js b/js/ccnxProtocol/components/ccnxProtocolService.js
index 2bf369b..c7d4d1e 100644
--- a/js/ccnxProtocol/components/ccnxProtocolService.js
+++ b/js/ccnxProtocol/components/ccnxProtocolService.js
@@ -35,50 +35,58 @@
{
try {
var requestContent = function(contentListener) {
- var interest = aURI.spec.split(":")[1];
+ var name = aURI.spec.split(":")[1];
// 131.179.141.18 is lioncub.metwi.ucla.edu .
var ndn = new NDN('131.179.141.18');
- var coListener = {
- onReceivedContentObject : function(contentObject) {
- // Set up defaults.
- var content = "";
- var contentType = "text/html";
- var contentCharset = "utf-8";
+ var ContentClosure = function ContentClosure() {
+ // Inherit from Closure.
+ Closure.call(this);
+ }
+ ContentClosure.prototype.upcall = function(kind, upcallInfo) {
+ if (!(kind == Closure.UPCALL_CONTENT ||
+ kind == Closure.UPCALL_CONTENT_UNVERIFIED))
+ // The upcall is not for us.
+ return;
+
+ var contentObject = upcallInfo.contentObject;
+
+ // Set up defaults.
+ var content = "";
+ var contentType = "text/html";
+ var contentCharset = "utf-8";
- // TODO: Need to check the signature, confirm that the name matches, etc.
- if (contentObject.content != null) {
- content = DataUtils.toString(contentObject.content);
+ if (contentObject.content != null) {
+ content = DataUtils.toString(contentObject.content);
- // TODO: Should look at the returned Name to get contentType. For now,
- // just look for a file extension in the original interest.
- var interestLowerCase = interest.toLowerCase();
- if (interestLowerCase.indexOf(".gif") >= 0) {
- contentType = "image/gif";
- contentCharset = "ISO-8859-1";
- }
- else if (interestLowerCase.indexOf(".jpg") >= 0 ||
- interestLowerCase.indexOf(".jpeg") >= 0) {
- contentType = "image/jpeg";
- contentCharset = "ISO-8859-1";
- }
- else if (interestLowerCase.indexOf(".png") >= 0) {
- contentType = "image/png";
- contentCharset = "ISO-8859-1";
- }
- else if (interestLowerCase.indexOf(".bmp") >= 0) {
- contentType = "image/bmp";
- contentCharset = "ISO-8859-1";
- }
- else if (interestLowerCase.indexOf(".css") >= 0)
- contentType = "text/css";
+ // TODO: Should look at the returned Name to get contentType. For now,
+ // just look for a file extension in the original name.
+ var nameLowerCase = name.toLowerCase();
+ if (nameLowerCase.indexOf(".gif") >= 0) {
+ contentType = "image/gif";
+ contentCharset = "ISO-8859-1";
}
-
- contentListener.onReceivedContent(content, contentType, contentCharset);
+ else if (nameLowerCase.indexOf(".jpg") >= 0 ||
+ nameLowerCase.indexOf(".jpeg") >= 0) {
+ contentType = "image/jpeg";
+ contentCharset = "ISO-8859-1";
+ }
+ else if (nameLowerCase.indexOf(".png") >= 0) {
+ contentType = "image/png";
+ contentCharset = "ISO-8859-1";
+ }
+ else if (nameLowerCase.indexOf(".bmp") >= 0) {
+ contentType = "image/bmp";
+ contentCharset = "ISO-8859-1";
+ }
+ else if (nameLowerCase.indexOf(".css") >= 0)
+ contentType = "text/css";
}
+
+ contentListener.onReceivedContent(content, contentType, contentCharset);
};
- ndn.getAsync(interest, coListener);
+ ndn.expressInterest(new Name(name), new ContentClosure());
};
return new ContentChannel(aURI, requestContent);
diff --git a/js/ccnxProtocol/modules/make-ndn-js.jsm.sh b/js/ccnxProtocol/modules/make-ndn-js.jsm.sh
index 2c4209b..27749e3 100755
--- a/js/ccnxProtocol/modules/make-ndn-js.jsm.sh
+++ b/js/ccnxProtocol/modules/make-ndn-js.jsm.sh
@@ -1,5 +1,6 @@
#!/bin/sh
cat ndn-js-header.txt \
+ ../../Closure.js emptyLine.txt \
../../NDN.js emptyLine.txt \
../../NDNSocketTransportService.js emptyLine.txt \
../../util/CCNProtocolDTags.js emptyLine.txt \
diff --git a/js/ccnxProtocol/modules/ndn-js-header.txt b/js/ccnxProtocol/modules/ndn-js-header.txt
index 63c037c..967f9e2 100644
--- a/js/ccnxProtocol/modules/ndn-js-header.txt
+++ b/js/ccnxProtocol/modules/ndn-js-header.txt
@@ -5,7 +5,7 @@
* See COPYING for copyright and distribution information.
*/
-var EXPORTED_SYMBOLS = ["NDN", "DataUtils", "readAllFromSocket"];
+var EXPORTED_SYMBOLS = ["NDN", "Closure", "Name", "Interest", "ContentObject", "DataUtils"];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
diff --git a/js/ccnxProtocol/modules/ndn-js.jsm b/js/ccnxProtocol/modules/ndn-js.jsm
index e5f2837..a432819 100644
--- a/js/ccnxProtocol/modules/ndn-js.jsm
+++ b/js/ccnxProtocol/modules/ndn-js.jsm
@@ -5,7 +5,7 @@
* See COPYING for copyright and distribution information.
*/
-var EXPORTED_SYMBOLS = ["NDN", "DataUtils", "readAllFromSocket"];
+var EXPORTED_SYMBOLS = ["NDN", "Closure", "Name", "Interest", "ContentObject", "DataUtils"];
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/NetUtil.jsm");
@@ -25,6 +25,69 @@
}
};
+/*
+ * @author: ucla-cs
+ * See COPYING for copyright and distribution information.
+ * Provide the callback closure for the async communication methods in the NDN class.
+ * This is a port of Closure.py from PyCCN, written by:
+ * Derek Kulinski <takeda@takeda.tk>
+ * Jeff Burke <jburke@ucla.edu>
+ */
+
+/*
+ * Create a subclass of Closure and pass an object to async calls.
+ */
+var Closure = function Closure() {
+ // I don't think storing NDN's closure is needed
+ // and it creates a reference loop, as of now both
+ // of those variables are never set -- Derek
+ //
+ // Use instance variables to return data to callback
+ this.ndn_data = null; // this holds the ndn_closure
+ this.ndn_data_dirty = false;
+};
+
+// Upcall result
+Closure.RESULT_ERR = -1; // upcall detected an error
+Closure.RESULT_OK = 0; // normal upcall return
+Closure.RESULT_REEXPRESS = 1; // reexpress the same interest again
+Closure.RESULT_INTEREST_CONSUMED = 2; // upcall claims to consume interest
+Closure.RESULT_VERIFY = 3; // force an unverified result to be verified
+
+// Upcall kind
+Closure.UPCALL_FINAL = 0; // handler is about to be deregistered
+Closure.UPCALL_INTEREST = 1; // incoming interest
+Closure.UPCALL_CONSUMED_INTEREST = 2; // incoming interest, someone has answered
+Closure.UPCALL_CONTENT = 3; // incoming verified content
+Closure.UPCALL_INTEREST_TIMED_OUT = 4; // interest timed out
+Closure.UPCALL_CONTENT_UNVERIFIED = 5; // content that has not been verified
+Closure.UPCALL_CONTENT_BAD = 6; // verification failed
+
+/*
+ * Override this in your subclass.
+ * If you're getting strange errors in upcall()
+ * check your code whether you're returning a value.
+ */
+Closure.prototype.upcall = function(kind, upcallInfo) {
+ //dump('upcall ' + this + " " + kind + " " + upcallInfo + "\n");
+ return Closure.RESULT_OK;
+};
+
+var UpcallInfo = function UpcallInfo(ndn, interest, matchedComps, contentObject) {
+ this.ndn = ndn; // NDN object (not used)
+ this.interest = interest; // Interest object
+ this.matchedComps = matchedComps; // int
+ this.contentObject = contentObject; // Content object
+};
+
+UpcallInfo.prototype.toString = function() {
+ var ret = "ndn = " + this.ndn;
+ ret += "\nInterest = " + this.interest;
+ ret += "\nmatchedComps = " + this.matchedComps;
+ ret += "\nContentObject: " + this.contentObject;
+ return ret;
+}
+
/*
* @author: ucla-cs
* See COPYING for copyright and distribution information.
@@ -99,7 +162,6 @@
}
-
NDN.prototype.put = function(name,content){
if(this.host!=null && this.port!=null){
@@ -176,16 +238,64 @@
return result;
}
else{
-
-
console.log('ERROR URL OR PORT NOT SET');
return null;
-
}
-
-
}
+
+/** Encode name as an Interest. If template is not null, use its attributes.
+ * Send the interest to host:port, read the entire response and call
+ * closure.upcall(Closure.UPCALL_CONTENT (or Closure.UPCALL_CONTENT_UNVERIFIED),
+ * new UpcallInfo(this, interest, 0, contentObject)).
+ */
+NDN.prototype.expressInterest = function(
+ // Name
+ name,
+ // Closure
+ closure,
+ // Interest
+ template) {
+ if (this.host == null || this.port == null) {
+ dump('ERROR host OR port NOT SET\n');
+ return;
+ }
+
+ interest = new Interest(name);
+ if (template != null) {
+ // TODO: Exactly what do we copy from template?
+ interest.InterestLifetime = template.InterestLifetime;
+ }
+ else
+ interest.InterestLifetime = 4200;
+ var outputHex = encodeToHexInterest(interest);
+
+ var dataListener = {
+ onReceivedData : function(result) {
+ if (result == null || result == undefined || result.length == 0)
+ listener.onReceivedContentObject(null);
+ else {
+ var decoder = new BinaryXMLDecoder(result);
+ var co = new ContentObject();
+ co.from_ccnb(decoder);
+
+ if(LOG>2) {
+ dump('DECODED CONTENT OBJECT\n');
+ dump(co);
+ dump('\n');
+ }
+
+ // TODO: verify the content object and set kind to UPCALL_CONTENT.
+ closure.upcall(Closure.UPCALL_CONTENT_UNVERIFIED,
+ new UpcallInfo(this, interest, 0, co))
+ }
+ }
+ }
+
+ return getAsync(this.host, this.port, outputHex, dataListener);
+};
+
+
/*
* @author: ucla-cs
* See COPYING for copyright and distribution information.
@@ -251,7 +361,7 @@
// Finish.
this.onStopRequest();
} catch (ex) {
- dump("onDataAvailable exception: " + ex + "\n");
+ dump("readAllFromSocket.onDataAvailable exception: " + ex + "\n");
}
}
};
@@ -260,53 +370,6 @@
pump.asyncRead(dataListener, null);
}
-
-// TODO: This should be moved to the main NDN.js when we agree on how to do non-blocking get.
-// For now, assume this is included after NDN.js and modify it.
-/** Encode message as an Interest, send it to host:port, read the entire response and call
- listener.onReceivedContentObject(contentObject).
- */
-NDN.prototype.getAsync = function(message, listener) {
- if (this.host != null && this.port != null) {
- var output ='';
- message = message.trim();
- if(message==null || message =="" ){
- dump('INVALID INPUT TO GET\n');
- return null;
- }
-
- interest = new Interest(new Name(message));
- interest.InterestLifetime = 4200;
- var outputHex = encodeToHexInterest(interest);
-
- var dataListener = {
- onReceivedData : function(result) {
- if (result == null || result == undefined || result.length == 0)
- listener.onReceivedContentObject(null);
- else {
- var decoder = new BinaryXMLDecoder(result);
- var co = new ContentObject();
- co.from_ccnb(decoder);
-
- if(LOG>2) {
- dump('DECODED CONTENT OBJECT\n');
- dump(co);
- dump('\n');
- }
-
- listener.onReceivedContentObject(co);
- }
- }
- }
-
- return getAsync(this.host, this.port, outputHex, dataListener);
- }
- else {
- dump('ERROR host OR port NOT SET\n');
- }
-}
-
-
/*
* @author: ucla-cs
* See COPYING for copyright and distribution information.
@@ -4005,6 +4068,10 @@
output+= "<br />";
}
+ if(co.signedInfo !=null && co.signedInfo.finalBlockID!=null){
+ output += "FinalBlockID: "+ DataUtils.toHex(co.signedInfo.finalBlockID);
+ output+= "<br />";
+ }
if(co.signedInfo!=null && co.signedInfo.locator!=null && co.signedInfo.locator.certificate!=null){
var tmp = DataUtils.toString(co.signedInfo.locator.certificate);
var publickey = rstr2b64(tmp);