In Interest.matches_name used to match interests in the PITTable, added a check for minSuffixComponents, maxSuffixComponents and exclude.
This helps to call the correct closure callback.
diff --git a/js/Interest.js b/js/Interest.js
index 3d91de5..8c8ecf1 100644
--- a/js/Interest.js
+++ b/js/Interest.js
@@ -114,8 +114,26 @@
};
+/*
+ * Return true if this.name.match(name) and the name conforms to the interest selectors.
+ */
Interest.prototype.matches_name = function(/*Name*/ name) {
- return this.name.match(name);
+ if (!this.name.match(name))
+ return false;
+
+ if (this.minSuffixComponents != null &&
+ // Add 1 for the implicit digest.
+ !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
+ return false;
+ if (this.maxSuffixComponents != null &&
+ // Add 1 for the implicit digest.
+ !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
+ return false;
+ if (this.exclude != null && name.components.length > this.name.components.length &&
+ this.exclude.matches(name.components[this.name.components.length]))
+ return false;
+
+ return true;
}
/*
@@ -170,7 +188,9 @@
encoder.writeEndElement();
};
-// Return a string with elements separated by "," and Exclude.ANY shown as "*".
+/*
+ * Return a string with elements separated by "," and Exclude.ANY shown as "*".
+ */
Exclude.prototype.to_uri = function() {
if (this.values == null || this.values.length == 0)
return "";
@@ -187,3 +207,78 @@
}
return result;
};
+
+/*
+ * Return true if the component matches any of the exclude criteria.
+ */
+Exclude.prototype.matches = function(/*Uint8Array*/ component) {
+ for (var i = 0; i < this.values.length; ++i) {
+ if (this.values[i] == Exclude.ANY) {
+ var lowerBound = null;
+ if (i > 0)
+ lowerBound = this.values[i - 1];
+
+ // Find the upper bound, possibly skipping over multiple ANY in a row.
+ var iUpperBound;
+ var upperBound = null;
+ for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
+ if (this.values[iUpperBound] != Exclude.ANY) {
+ upperBound = this.values[iUpperBound];
+ break;
+ }
+ }
+
+ // If lowerBound != null, we already checked component equals lowerBound on the last pass.
+ // If upperBound != null, we will check component equals upperBound on the next pass.
+ if (upperBound != null) {
+ if (lowerBound != null) {
+ if (Exclude.compareComponents(component, lowerBound) > 0 &&
+ Exclude.compareComponents(component, upperBound) < 0)
+ return true;
+ }
+ else {
+ if (Exclude.compareComponents(component, upperBound) < 0)
+ return true;
+ }
+
+ // Make i equal iUpperBound on the next pass.
+ i = iUpperBound - 1;
+ }
+ else {
+ if (lowerBound != null) {
+ if (Exclude.compareComponents(component, lowerBound) > 0)
+ return true;
+ }
+ else
+ // this.values has only ANY.
+ return true;
+ }
+ }
+ else {
+ if (DataUtils.arraysEqual(component, this.values[i]))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/*
+ * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
+ * A component is less if it is shorter, otherwise if equal length do a byte comparison.
+ */
+Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
+ if (component1.length < component2.length)
+ return -1;
+ if (component1.length > component2.length)
+ return 1;
+
+ for (var i = 0; i < component1.length; ++i) {
+ if (component1[i] < component2[i])
+ return -1;
+ if (component1[i] > component2[i])
+ return 1;
+ }
+
+ return 0;
+};
diff --git a/js/NDN.js b/js/NDN.js
index 9e76e4a..e6e1a37 100644
--- a/js/NDN.js
+++ b/js/NDN.js
@@ -86,10 +86,11 @@
this.timerID = -1; // Timer ID
};
-// Return the longest entry from NDN.PITTable that matches name.
+/*
+ * Return the entry from NDN.PITTable where the name conforms to the interest selectors, and
+ * the interest name is the longest that matches name.
+ */
NDN.getEntryForExpressedInterest = function(/*Name*/ name) {
- // TODO: handle multiple matches? Maybe not from registerPrefix because multiple ContentObject
- // could be sent for one Interest?
var result = null;
for (var i = 0; i < NDN.PITTable.length; i++) {
diff --git a/js/ndnProtocol.xpi b/js/ndnProtocol.xpi
index 0b7fc58..298aad1 100644
--- a/js/ndnProtocol.xpi
+++ b/js/ndnProtocol.xpi
Binary files differ
diff --git a/js/ndnProtocol/modules/ndn-js.jsm b/js/ndnProtocol/modules/ndn-js.jsm
index 200fc41..a444697 100644
--- a/js/ndnProtocol/modules/ndn-js.jsm
+++ b/js/ndnProtocol/modules/ndn-js.jsm
@@ -88,10 +88,12 @@
a.peekStartElement(CCNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(CCNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(CCNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(CCNProtocolDTags.Nonce));a.readEndElement()};
Interest.prototype.to_ccnb=function(a){a.writeStartElement(CCNProtocolDTags.Interest);this.name.to_ccnb(a);null!=this.minSuffixComponents&&a.writeElement(CCNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(CCNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ccnb(a);null!=this.exclude&&this.exclude.to_ccnb(a);null!=this.childSelector&&a.writeElement(CCNProtocolDTags.ChildSelector,
this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(CCNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(CCNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(CCNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(CCNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
+Interest.prototype.matches_name=function(a){return!this.name.match(a)||null!=this.minSuffixComponents&&!(a.components.length+1-this.name.components.length>=this.minSuffixComponents)||null!=this.maxSuffixComponents&&!(a.components.length+1-this.name.components.length<=this.maxSuffixComponents)||null!=this.exclude&&a.components.length>this.name.components.length&&this.exclude.matches(a.components[this.name.components.length])?!1:!0};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
Exclude.prototype.from_ccnb=function(a){for(a.readStartElement(CCNProtocolDTags.Exclude);;)if(a.peekStartElement(CCNProtocolDTags.Component))this.values.push(a.readBinaryElement(CCNProtocolDTags.Component));else if(a.peekStartElement(CCNProtocolDTags.Any))a.readStartElement(CCNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(CCNProtocolDTags.Bloom))a.readBinaryElement(CCNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
Exclude.prototype.to_ccnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(CCNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(CCNProtocolDTags.Any),a.writeEndElement()):a.writeElement(CCNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
+Exclude.prototype.matches=function(a){for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<Exclude.compareComponents(a,c)&&0>Exclude.compareComponents(a,e))return!0}else if(0>Exclude.compareComponents(a,e))return!0;b=d-1}else if(null!=c){if(0<Exclude.compareComponents(a,c))return!0}else return!0}else if(DataUtils.arraysEqual(a,
+this.values[b]))return!0;return!1};Exclude.compareComponents=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};
var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
KeyLocator.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(CCNProtocolDTags.Key)){try{this.publicKey=encodedKey=a.readBinaryElement(CCNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(CCNProtocolDTags.Certificate)){try{this.certificate=encodedCert=a.readBinaryElement(CCNProtocolDTags.Certificate),
this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ccnb(a);a.readEndElement()};
@@ -294,7 +296,7 @@
NDN.makeShuffledGetHostAndPort=function(a,b){a=a.slice(0,a.length);DataUtils.shuffle(a);return function(){return 0==a.length?null:{host:a.splice(0,1)[0],port:b}}};
NDN.prototype.expressInterest=function(a,b,c){var d=new Interest(a);null!=c?(d.minSuffixComponents=c.minSuffixComponents,d.maxSuffixComponents=c.maxSuffixComponents,d.publisherPublicKeyDigest=c.publisherPublicKeyDigest,d.exclude=c.exclude,d.childSelector=c.childSelector,d.answerOriginKind=c.answerOriginKind,d.scope=c.scope,d.interestLifetime=c.interestLifetime):d.interestLifetime=4E3;if(null==this.host||null==this.port)if(null==this.getHostAndPort)console.log("ERROR: host OR port NOT SET");else{var e=
this;this.connectAndExecute(function(){e.reconnectAndExpressInterest(d,b)})}else this.reconnectAndExpressInterest(d,b)};NDN.prototype.reconnectAndExpressInterest=function(a,b){if(this.transport.connectedHost!=this.host||this.transport.connectedPort!=this.port){var c=this;this.transport.connect(c,function(){c.expressInterestHelper(a,b)})}else this.expressInterestHelper(a,b)};
-NDN.prototype.expressInterestHelper=function(a,b){if(null!=b){var c=new PITEntry(a,b);NDN.PITTable.push(c);b.pitEntry=c}var d=this;null!=b&&(c.timerID=setTimeout(function(){3<LOG&&console.log("Interest time out.");var e=NDN.PITTable.indexOf(c);0<=e&&NDN.PITTable.splice(e,1);b.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(d,a,0,null))},a.interestLifetime));this.transport.send(encodeToBinaryInterest(a))};
+NDN.prototype.expressInterestHelper=function(a,b){if(null!=b){var c=new PITEntry(a,b);NDN.PITTable.push(c);b.pitEntry=c}var d=this;null!=b&&(c.timerID=setTimeout(function(){3<LOG&&console.log("Interest time out.");var e=NDN.PITTable.indexOf(c);0<=e&&NDN.PITTable.splice(e,1);b.upcall(Closure.UPCALL_INTEREST_TIMED_OUT,new UpcallInfo(d,a,0,null))},a.interestLifetime||4E3));this.transport.send(encodeToBinaryInterest(a))};
NDN.prototype.registerPrefix=function(a,b,c){var d=this,e=function(){if(null==d.ccndid){var e=new Interest(NDN.ccndIdFetcher);e.interestLifetime=4E3;3<LOG&&console.log("Expressing interest for ccndid from ccnd.");d.reconnectAndExpressInterest(e,new NDN.FetchCcndidClosure(d,a,b,c))}else d.registerPrefixHelper(a,b,c)};null==this.host||null==this.port?null==this.getHostAndPort?console.log("ERROR: host OR port NOT SET"):this.connectAndExecute(e):e()};
NDN.FetchCcndidClosure=function(a,b,c,d){Closure.call(this);this.ndn=a;this.name=b;this.callerClosure=c;this.flag=d};
NDN.FetchCcndidClosure.prototype.upcall=function(a,b){if(a==Closure.UPCALL_INTEREST_TIMED_OUT)return console.log("Timeout while requesting the ccndid. Cannot registerPrefix for "+this.name.to_uri()+" ."),Closure.RESULT_OK;if(!(a==Closure.UPCALL_CONTENT||a==Closure.UPCALL_CONTENT_UNVERIFIED))return Closure.RESULT_ERR;var c=b.contentObject;!c.signedInfo||!c.signedInfo.publisher||!c.signedInfo.publisher.publisherPublicKeyDigest?console.log("ContentObject doesn't have a publisherPublicKeyDigest. Cannot set ccndid and registerPrefix for "+
diff --git a/js/testing/test-PIT-matching.html b/js/testing/test-PIT-matching.html
new file mode 100644
index 0000000..4ccac10
--- /dev/null
+++ b/js/testing/test-PIT-matching.html
@@ -0,0 +1,148 @@
+<?xml version = "1.0" encoding="utf-8" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"DTD/xhtml1-strict.dtd">
+<!--
+ See COPYING for copyright and distribution information.
+-->
+<html xmlns = "http://www.w3.org/1999/xhtml">
+<meta charset="UTF-8"/>
+
+<head>
+ <title>NDN PIT Matching</title>
+
+ <script type="text/javascript" src="../Helper.js"></script>
+
+ <script type="text/javascript">
+ var ndn = new NDN({verify:false});
+
+ var AsyncGetClosure = function AsyncGetClosure(target) {
+ // Inherit from Closure.
+ Closure.call(this);
+
+ this.target = target;
+ };
+
+ AsyncGetClosure.prototype.upcall = function(kind, upcallInfo) {
+ if (kind == Closure.UPCALL_CONTENT || kind == Closure.UPCALL_CONTENT_UNVERIFIED) {
+ document.getElementById(this.target).innerHTML =
+ DataUtils.toString(upcallInfo.contentObject.content);
+ return Closure.RESULT_OK;
+ }
+ else
+ return Closure.RESULT_ERR;
+ };
+
+ var name = new Name("/ndn/ucla.edu/apps/ndn-js-test/hello.txt");
+
+ var interestSelector1 = new Interest();
+ interestSelector1.interestLifetime = 10000;
+ interestSelector1.minSuffixComponents = 3;
+ interestSelector1.maxSuffixComponents = 3;
+
+ var interestSelector2 = new Interest();
+ interestSelector2.interestLifetime = 10000;
+ interestSelector2.minSuffixComponents = 4;
+ interestSelector2.maxSuffixComponents = 4;
+
+ var interestSelector3 = new Interest();
+ interestSelector3.interestLifetime = 10000;
+ interestSelector3.exclude = new Exclude([Exclude.ANY, DataUtils.toNumbersFromString("zzzzzz")]);
+
+ var interestSelector4 = new Interest();
+ interestSelector4.interestLifetime = 10000;
+ interestSelector4.exclude = new Exclude([DataUtils.toNumbersFromString("zzzzzz"), Exclude.ANY]);
+
+ function run() {
+ ndn.onopen = function() {
+ for (var i = 0; i < 10; ++i) {
+ // "col1Content0" is already fetched.
+ if (i != 0)
+ ndn.expressInterest(name, new AsyncGetClosure("col1Content" + i), interestSelector1);
+ ndn.expressInterest(name, new AsyncGetClosure("col2Content" + i), interestSelector2);
+ ndn.expressInterest(name, new AsyncGetClosure("col3Content" + i), interestSelector3);
+ ndn.expressInterest(name, new AsyncGetClosure("col4Content" + i), interestSelector4);
+ }
+ // For testing, make sure we don't just process in the order returned.
+ DataUtils.shuffle(NDN.PITTable);
+ };
+
+ ndn.expressInterest(name, new AsyncGetClosure("col1Content0"), interestSelector1);
+ }
+ </script>
+</head>
+<body >
+ <button id="runBtn" onclick="run()">Run</button>
+ <table style="text-align: left;" border="1" cellpadding="2" cellspacing="0">
+ <tbody>
+ <tr>
+ <td style="vertical-align: top;">minSuffixComponents=3,<br/>maxSuffixComponents=3<br/>should be:<br/>
+ hello</td>
+ <td style="vertical-align: top;">minSuffixComponents=4,<br/>maxSuffixComponents=4<br/>should be:<br/>
+ hello world</td>
+ <td style="vertical-align: top;">exclude=*,zzzzzz<br/><br/>should be:<br/>hello</td>
+ <td style="vertical-align: top;">exclude=zzzzzz,*<br/><br/>should be:<br/>hello world</td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content0"/></td>
+ <td style="vertical-align: top;"><div id="col2Content0"/></td>
+ <td style="vertical-align: top;"><div id="col3Content0"/></td>
+ <td style="vertical-align: top;"><div id="col4Content0"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content1"/></td>
+ <td style="vertical-align: top;"><div id="col2Content1"/></td>
+ <td style="vertical-align: top;"><div id="col3Content1"/></td>
+ <td style="vertical-align: top;"><div id="col4Content1"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content2"/></td>
+ <td style="vertical-align: top;"><div id="col2Content2"/></td>
+ <td style="vertical-align: top;"><div id="col3Content2"/></td>
+ <td style="vertical-align: top;"><div id="col4Content2"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content3"/></td>
+ <td style="vertical-align: top;"><div id="col2Content3"/></td>
+ <td style="vertical-align: top;"><div id="col3Content3"/></td>
+ <td style="vertical-align: top;"><div id="col4Content3"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content4"/></td>
+ <td style="vertical-align: top;"><div id="col2Content4"/></td>
+ <td style="vertical-align: top;"><div id="col3Content4"/></td>
+ <td style="vertical-align: top;"><div id="col4Content4"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content5"/></td>
+ <td style="vertical-align: top;"><div id="col2Content5"/></td>
+ <td style="vertical-align: top;"><div id="col3Content5"/></td>
+ <td style="vertical-align: top;"><div id="col4Content5"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content6"/></td>
+ <td style="vertical-align: top;"><div id="col2Content6"/></td>
+ <td style="vertical-align: top;"><div id="col3Content6"/></td>
+ <td style="vertical-align: top;"><div id="col4Content6"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content7"/></td>
+ <td style="vertical-align: top;"><div id="col2Content7"/></td>
+ <td style="vertical-align: top;"><div id="col3Content7"/></td>
+ <td style="vertical-align: top;"><div id="col4Content7"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content8"/></td>
+ <td style="vertical-align: top;"><div id="col2Content8"/></td>
+ <td style="vertical-align: top;"><div id="col3Content8"/></td>
+ <td style="vertical-align: top;"><div id="col4Content8"/></td>
+ </tr>
+ <tr>
+ <td style="vertical-align: top;"><div id="col1Content9"/></td>
+ <td style="vertical-align: top;"><div id="col2Content9"/></td>
+ <td style="vertical-align: top;"><div id="col3Content9"/></td>
+ <td style="vertical-align: top;"><div id="col4Content9"/></td>
+ </tr>
+ </tbody>
+ </table>
+</body>
+</html>
diff --git a/js/tools/build/ndn-js-uncomp.js b/js/tools/build/ndn-js-uncomp.js
index 469a0e5..bb22c6a 100644
--- a/js/tools/build/ndn-js-uncomp.js
+++ b/js/tools/build/ndn-js-uncomp.js
@@ -1431,8 +1431,26 @@
};
+/*
+ * Return true if this.name.match(name) and the name conforms to the interest selectors.
+ */
Interest.prototype.matches_name = function(/*Name*/ name) {
- return this.name.match(name);
+ if (!this.name.match(name))
+ return false;
+
+ if (this.minSuffixComponents != null &&
+ // Add 1 for the implicit digest.
+ !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
+ return false;
+ if (this.maxSuffixComponents != null &&
+ // Add 1 for the implicit digest.
+ !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
+ return false;
+ if (this.exclude != null && name.components.length > this.name.components.length &&
+ this.exclude.matches(name.components[this.name.components.length]))
+ return false;
+
+ return true;
}
/*
@@ -1487,7 +1505,9 @@
encoder.writeEndElement();
};
-// Return a string with elements separated by "," and Exclude.ANY shown as "*".
+/*
+ * Return a string with elements separated by "," and Exclude.ANY shown as "*".
+ */
Exclude.prototype.to_uri = function() {
if (this.values == null || this.values.length == 0)
return "";
@@ -1504,6 +1524,81 @@
}
return result;
};
+
+/*
+ * Return true if the component matches any of the exclude criteria.
+ */
+Exclude.prototype.matches = function(/*Uint8Array*/ component) {
+ for (var i = 0; i < this.values.length; ++i) {
+ if (this.values[i] == Exclude.ANY) {
+ var lowerBound = null;
+ if (i > 0)
+ lowerBound = this.values[i - 1];
+
+ // Find the upper bound, possibly skipping over multiple ANY in a row.
+ var iUpperBound;
+ var upperBound = null;
+ for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
+ if (this.values[iUpperBound] != Exclude.ANY) {
+ upperBound = this.values[iUpperBound];
+ break;
+ }
+ }
+
+ // If lowerBound != null, we already checked component equals lowerBound on the last pass.
+ // If upperBound != null, we will check component equals upperBound on the next pass.
+ if (upperBound != null) {
+ if (lowerBound != null) {
+ if (Exclude.compareComponents(component, lowerBound) > 0 &&
+ Exclude.compareComponents(component, upperBound) < 0)
+ return true;
+ }
+ else {
+ if (Exclude.compareComponents(component, upperBound) < 0)
+ return true;
+ }
+
+ // Make i equal iUpperBound on the next pass.
+ i = iUpperBound - 1;
+ }
+ else {
+ if (lowerBound != null) {
+ if (Exclude.compareComponents(component, lowerBound) > 0)
+ return true;
+ }
+ else
+ // this.values has only ANY.
+ return true;
+ }
+ }
+ else {
+ if (DataUtils.arraysEqual(component, this.values[i]))
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/*
+ * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
+ * A component is less if it is shorter, otherwise if equal length do a byte comparison.
+ */
+Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
+ if (component1.length < component2.length)
+ return -1;
+ if (component1.length > component2.length)
+ return 1;
+
+ for (var i = 0; i < component1.length; ++i) {
+ if (component1[i] < component2[i])
+ return -1;
+ if (component1[i] > component2[i])
+ return 1;
+ }
+
+ return 0;
+};
/**
* @author: Meki Cheraoui
* See COPYING for copyright and distribution information.
@@ -7544,10 +7639,11 @@
this.timerID = -1; // Timer ID
};
-// Return the longest entry from NDN.PITTable that matches name.
+/*
+ * Return the entry from NDN.PITTable where the name conforms to the interest selectors, and
+ * the interest name is the longest that matches name.
+ */
NDN.getEntryForExpressedInterest = function(/*Name*/ name) {
- // TODO: handle multiple matches? Maybe not from registerPrefix because multiple ContentObject
- // could be sent for one Interest?
var result = null;
for (var i = 0; i < NDN.PITTable.length; i++) {
diff --git a/js/tools/build/ndn-js.js b/js/tools/build/ndn-js.js
index b1a9e17..e6a4ef6 100644
--- a/js/tools/build/ndn-js.js
+++ b/js/tools/build/ndn-js.js
@@ -52,10 +52,12 @@
a.peekStartElement(CCNProtocolDTags.InterestLifetime)&&(this.interestLifetime=1E3*DataUtils.bigEndianToUnsignedInt(a.readBinaryElement(CCNProtocolDTags.InterestLifetime))/4096);a.peekStartElement(CCNProtocolDTags.Nonce)&&(this.nonce=a.readBinaryElement(CCNProtocolDTags.Nonce));a.readEndElement()};
Interest.prototype.to_ccnb=function(a){a.writeStartElement(CCNProtocolDTags.Interest);this.name.to_ccnb(a);null!=this.minSuffixComponents&&a.writeElement(CCNProtocolDTags.MinSuffixComponents,this.minSuffixComponents);null!=this.maxSuffixComponents&&a.writeElement(CCNProtocolDTags.MaxSuffixComponents,this.maxSuffixComponents);null!=this.publisherPublicKeyDigest&&this.publisherPublicKeyDigest.to_ccnb(a);null!=this.exclude&&this.exclude.to_ccnb(a);null!=this.childSelector&&a.writeElement(CCNProtocolDTags.ChildSelector,
this.childSelector);this.DEFAULT_ANSWER_ORIGIN_KIND!=this.answerOriginKind&&null!=this.answerOriginKind&&a.writeElement(CCNProtocolDTags.AnswerOriginKind,this.answerOriginKind);null!=this.scope&&a.writeElement(CCNProtocolDTags.Scope,this.scope);null!=this.interestLifetime&&a.writeElement(CCNProtocolDTags.InterestLifetime,DataUtils.nonNegativeIntToBigEndian(4096*(this.interestLifetime/1E3)));null!=this.nonce&&a.writeElement(CCNProtocolDTags.Nonce,this.nonce);a.writeEndElement()};
-Interest.prototype.matches_name=function(a){return this.name.match(a)};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
+Interest.prototype.matches_name=function(a){return!this.name.match(a)||null!=this.minSuffixComponents&&!(a.components.length+1-this.name.components.length>=this.minSuffixComponents)||null!=this.maxSuffixComponents&&!(a.components.length+1-this.name.components.length<=this.maxSuffixComponents)||null!=this.exclude&&a.components.length>this.name.components.length&&this.exclude.matches(a.components[this.name.components.length])?!1:!0};var Exclude=function(a){this.values=a||[]};Exclude.ANY="*";
Exclude.prototype.from_ccnb=function(a){for(a.readStartElement(CCNProtocolDTags.Exclude);;)if(a.peekStartElement(CCNProtocolDTags.Component))this.values.push(a.readBinaryElement(CCNProtocolDTags.Component));else if(a.peekStartElement(CCNProtocolDTags.Any))a.readStartElement(CCNProtocolDTags.Any),a.readEndElement(),this.values.push(Exclude.ANY);else if(a.peekStartElement(CCNProtocolDTags.Bloom))a.readBinaryElement(CCNProtocolDTags.Bloom),this.values.push(Exclude.ANY);else break;a.readEndElement()};
Exclude.prototype.to_ccnb=function(a){if(!(null==this.values||0==this.values.length)){a.writeStartElement(CCNProtocolDTags.Exclude);for(var b=0;b<this.values.length;++b)this.values[b]==Exclude.ANY?(a.writeStartElement(CCNProtocolDTags.Any),a.writeEndElement()):a.writeElement(CCNProtocolDTags.Component,this.values[b]);a.writeEndElement()}};
Exclude.prototype.to_uri=function(){if(null==this.values||0==this.values.length)return"";for(var a="",b=0;b<this.values.length;++b)0<b&&(a+=","),a=this.values[b]==Exclude.ANY?a+"*":a+Name.toEscapedString(this.values[b]);return a};
+Exclude.prototype.matches=function(a){for(var b=0;b<this.values.length;++b)if(this.values[b]==Exclude.ANY){var c=null;0<b&&(c=this.values[b-1]);var d,e=null;for(d=b+1;d<this.values.length;++d)if(this.values[d]!=Exclude.ANY){e=this.values[d];break}if(null!=e){if(null!=c){if(0<Exclude.compareComponents(a,c)&&0>Exclude.compareComponents(a,e))return!0}else if(0>Exclude.compareComponents(a,e))return!0;b=d-1}else if(null!=c){if(0<Exclude.compareComponents(a,c))return!0}else return!0}else if(DataUtils.arraysEqual(a,
+this.values[b]))return!0;return!1};Exclude.compareComponents=function(a,b){if(a.length<b.length)return-1;if(a.length>b.length)return 1;for(var c=0;c<a.length;++c){if(a[c]<b[c])return-1;if(a[c]>b[c])return 1}return 0};
var Key=function(){},KeyLocatorType={KEY:1,CERTIFICATE:2,KEYNAME:3},KeyLocator=function(a,b){this.type=b;b==KeyLocatorType.KEYNAME?(3<LOG&&console.log("KeyLocator: SET KEYNAME"),this.keyName=a):b==KeyLocatorType.KEY?(3<LOG&&console.log("KeyLocator: SET KEY"),this.publicKey=a):b==KeyLocatorType.CERTIFICATE&&(3<LOG&&console.log("KeyLocator: SET CERTIFICATE"),this.certificate=a)};
KeyLocator.prototype.from_ccnb=function(a){a.readStartElement(this.getElementLabel());if(a.peekStartElement(CCNProtocolDTags.Key)){try{this.publicKey=encodedKey=a.readBinaryElement(CCNProtocolDTags.Key),this.type=KeyLocatorType.KEY,4<LOG&&console.log("PUBLIC KEY FOUND: "+this.publicKey)}catch(b){throw Error("Cannot parse key: ",b);}if(null==this.publicKey)throw Error("Cannot parse key: ");}else if(a.peekStartElement(CCNProtocolDTags.Certificate)){try{this.certificate=encodedCert=a.readBinaryElement(CCNProtocolDTags.Certificate),
this.type=KeyLocatorType.CERTIFICATE,4<LOG&&console.log("CERTIFICATE FOUND: "+this.certificate)}catch(c){throw Error("Cannot decode certificate: "+c);}if(null==this.certificate)throw Error("Cannot parse certificate! ");}else this.type=KeyLocatorType.KEYNAME,this.keyName=new KeyName,this.keyName.from_ccnb(a);a.readEndElement()};