blob: e8d2891c2d0a19356cfc3705545195c33df3585a [file] [log] [blame]
Wentao Shangbd63e462012-12-03 16:19:33 -08001/**
Jeff Thompson146d7de2012-11-17 16:15:28 -08002 * @author: Meki Cheraoui
Jeff Thompson745026e2012-10-13 12:49:20 -07003 * See COPYING for copyright and distribution information.
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -07004 * This class represents Interest Objects
5 */
6
Jeff Thompson42806a12012-12-29 18:19:39 -08007// _interestLifetime is in milliseconds.
Jeff Thompsonea3a6902013-02-17 21:56:34 -08008var Interest = function Interest
9 (_name, _faceInstance, _minSuffixComponents, _maxSuffixComponents, _publisherPublicKeyDigest, _exclude,
10 _childSelector, _answerOriginKind, _scope, _interestLifetime, _nonce) {
Meki Cherkaoui8f173612012-06-06 01:05:40 -070011
Jeff Thompson86aea882012-09-29 17:32:48 -070012 this.name = _name;
13 this.faceInstance = _faceInstance;
14 this.maxSuffixComponents = _maxSuffixComponents;
15 this.minSuffixComponents = _minSuffixComponents;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070016
Jeff Thompson86aea882012-09-29 17:32:48 -070017 this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
18 this.exclude = _exclude;
19 this.childSelector = _childSelector;
20 this.answerOriginKind = _answerOriginKind;
21 this.scope = _scope;
Jeff Thompson42806a12012-12-29 18:19:39 -080022 this.interestLifetime = _interestLifetime; // milli seconds
Jeff Thompson5fc9b672012-11-24 10:00:56 -080023 this.nonce = _nonce;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070024};
25
Jeff Thompson821183d2012-11-24 18:46:21 -080026Interest.RECURSIVE_POSTFIX = "*";
27
28Interest.CHILD_SELECTOR_LEFT = 0;
29Interest.CHILD_SELECTOR_RIGHT = 1;
30Interest.ANSWER_CONTENT_STORE = 1;
31Interest.ANSWER_GENERATED = 2;
32Interest.ANSWER_STALE = 4; // Stale answer OK
33Interest.MARK_STALE = 16; // Must have scope 0. Michael calls this a "hack"
34
35Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
36
37
Jeff Thompson86aea882012-09-29 17:32:48 -070038Interest.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070039
40 decoder.readStartElement(CCNProtocolDTags.Interest);
41
Jeff Thompsonf3bd3592012-09-29 23:25:30 -070042 this.name = new Name();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070043 this.name.from_ccnb(decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070044
Jeff Thompson5fc9b672012-11-24 10:00:56 -080045 if (decoder.peekStartElement(CCNProtocolDTags.MinSuffixComponents))
Jeff Thompson86aea882012-09-29 17:32:48 -070046 this.minSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MinSuffixComponents);
Jeff Thompson12414d62013-07-26 17:01:29 -070047 else
48 this.minSuffixComponents = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070049
Jeff Thompson5fc9b672012-11-24 10:00:56 -080050 if (decoder.peekStartElement(CCNProtocolDTags.MaxSuffixComponents))
Jeff Thompson86aea882012-09-29 17:32:48 -070051 this.maxSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents);
Jeff Thompson12414d62013-07-26 17:01:29 -070052 else
53 this.maxSuffixComponents = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070054
Jeff Thompson86aea882012-09-29 17:32:48 -070055 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
Jeff Thompson5fc9b672012-11-24 10:00:56 -080056 this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070057 this.publisherPublicKeyDigest.from_ccnb(decoder);
Meki Cherkaoui8f173612012-06-06 01:05:40 -070058 }
Jeff Thompson12414d62013-07-26 17:01:29 -070059 else
60 this.publisherPublicKeyDigest = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070061
62 if (decoder.peekStartElement(CCNProtocolDTags.Exclude)) {
Jeff Thompson86aea882012-09-29 17:32:48 -070063 this.exclude = new Exclude();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070064 this.exclude.from_ccnb(decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070065 }
Jeff Thompson12414d62013-07-26 17:01:29 -070066 else
67 this.exclude = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070068
Jeff Thompson5fc9b672012-11-24 10:00:56 -080069 if (decoder.peekStartElement(CCNProtocolDTags.ChildSelector))
Jeff Thompson86aea882012-09-29 17:32:48 -070070 this.childSelector = decoder.readIntegerElement(CCNProtocolDTags.ChildSelector);
Jeff Thompson12414d62013-07-26 17:01:29 -070071 else
72 this.childSelector = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070073
Jeff Thompson5fc9b672012-11-24 10:00:56 -080074 if (decoder.peekStartElement(CCNProtocolDTags.AnswerOriginKind))
Jeff Thompson86aea882012-09-29 17:32:48 -070075 this.answerOriginKind = decoder.readIntegerElement(CCNProtocolDTags.AnswerOriginKind);
Jeff Thompson12414d62013-07-26 17:01:29 -070076 else
77 this.answerOriginKind = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070078
Jeff Thompson5fc9b672012-11-24 10:00:56 -080079 if (decoder.peekStartElement(CCNProtocolDTags.Scope))
Jeff Thompson86aea882012-09-29 17:32:48 -070080 this.scope = decoder.readIntegerElement(CCNProtocolDTags.Scope);
Jeff Thompson12414d62013-07-26 17:01:29 -070081 else
82 this.scope = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070083
Jeff Thompson5fc9b672012-11-24 10:00:56 -080084 if (decoder.peekStartElement(CCNProtocolDTags.InterestLifetime))
Jeff Thompson42806a12012-12-29 18:19:39 -080085 this.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
Jeff Thompson5fc9b672012-11-24 10:00:56 -080086 (decoder.readBinaryElement(CCNProtocolDTags.InterestLifetime)) / 4096;
Jeff Thompson12414d62013-07-26 17:01:29 -070087 else
88 this.interestLifetime = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070089
Jeff Thompson5fc9b672012-11-24 10:00:56 -080090 if (decoder.peekStartElement(CCNProtocolDTags.Nonce))
Jeff Thompson86aea882012-09-29 17:32:48 -070091 this.nonce = decoder.readBinaryElement(CCNProtocolDTags.Nonce);
Jeff Thompson12414d62013-07-26 17:01:29 -070092 else
93 this.nonce = null;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070094
95 decoder.readEndElement();
96};
97
Jeff Thompson86aea882012-09-29 17:32:48 -070098Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
Meki Cherkaoui8f173612012-06-06 01:05:40 -070099 //Could check if name is present
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700100
101 encoder.writeStartElement(CCNProtocolDTags.Interest);
102
Jeff Thompsone85ff1d2012-09-29 21:21:57 -0700103 this.name.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700104
Jeff Thompson86aea882012-09-29 17:32:48 -0700105 if (null != this.minSuffixComponents)
106 encoder.writeElement(CCNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700107
Jeff Thompson86aea882012-09-29 17:32:48 -0700108 if (null != this.maxSuffixComponents)
109 encoder.writeElement(CCNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700110
Jeff Thompson86aea882012-09-29 17:32:48 -0700111 if (null != this.publisherPublicKeyDigest)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -0700112 this.publisherPublicKeyDigest.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700113
Jeff Thompson86aea882012-09-29 17:32:48 -0700114 if (null != this.exclude)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -0700115 this.exclude.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700116
Jeff Thompson86aea882012-09-29 17:32:48 -0700117 if (null != this.childSelector)
118 encoder.writeElement(CCNProtocolDTags.ChildSelector, this.childSelector);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700119
Jeff Thompson86aea882012-09-29 17:32:48 -0700120 if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null)
121 encoder.writeElement(CCNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700122
Jeff Thompson86aea882012-09-29 17:32:48 -0700123 if (null != this.scope)
124 encoder.writeElement(CCNProtocolDTags.Scope, this.scope);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700125
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800126 if (null != this.interestLifetime)
127 encoder.writeElement(CCNProtocolDTags.InterestLifetime,
Jeff Thompson42806a12012-12-29 18:19:39 -0800128 DataUtils.nonNegativeIntToBigEndian((this.interestLifetime / 1000.0) * 4096));
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800129
Jeff Thompson86aea882012-09-29 17:32:48 -0700130 if (null != this.nonce)
131 encoder.writeElement(CCNProtocolDTags.Nonce, this.nonce);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700132
133 encoder.writeEndElement();
134
135};
136
Jeff Thompson202728a2013-02-10 22:20:08 -0800137/*
138 * Return true if this.name.match(name) and the name conforms to the interest selectors.
139 */
Jeff Thompson3f4be552013-01-05 22:36:40 -0800140Interest.prototype.matches_name = function(/*Name*/ name) {
Jeff Thompson202728a2013-02-10 22:20:08 -0800141 if (!this.name.match(name))
142 return false;
143
144 if (this.minSuffixComponents != null &&
145 // Add 1 for the implicit digest.
146 !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
147 return false;
148 if (this.maxSuffixComponents != null &&
149 // Add 1 for the implicit digest.
150 !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
151 return false;
152 if (this.exclude != null && name.components.length > this.name.components.length &&
153 this.exclude.matches(name.components[this.name.components.length]))
154 return false;
155
156 return true;
Jeff Thompsonea3a6902013-02-17 21:56:34 -0800157};
158
159/*
160 * Return a new Interest with the same fields as this Interest.
161 * Note: This does NOT make a deep clone of the name, exclue or other objects.
162 */
163Interest.prototype.clone = function() {
164 return new Interest
165 (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents,
166 this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind,
167 this.scope, this.interestLifetime, this.nonce);
168};
Jeff Thompson86aea882012-09-29 17:32:48 -0700169
Jeff Thompson08d41b72013-02-03 23:09:29 -0800170/*
171 * Handle the interest Exclude element.
172 * _values is an array where each element is either Uint8Array component or Exclude.ANY.
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700173 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800174var Exclude = function Exclude(_values) {
175 this.values = (_values || []);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700176}
177
Jeff Thompson08d41b72013-02-03 23:09:29 -0800178Exclude.ANY = "*";
179
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700180Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson08d41b72013-02-03 23:09:29 -0800181 decoder.readStartElement(CCNProtocolDTags.Exclude);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700182
Jeff Thompson08d41b72013-02-03 23:09:29 -0800183 while (true) {
184 if (decoder.peekStartElement(CCNProtocolDTags.Component))
185 this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
186 else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
187 decoder.readStartElement(CCNProtocolDTags.Any);
188 decoder.readEndElement();
189 this.values.push(Exclude.ANY);
190 }
191 else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
192 // Skip the Bloom and treat it as Any.
193 decoder.readBinaryElement(CCNProtocolDTags.Bloom);
194 this.values.push(Exclude.ANY);
195 }
196 else
197 break;
198 }
199
200 decoder.readEndElement();
201};
202
203Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
204 if (this.values == null || this.values.length == 0)
205 return;
206
207 encoder.writeStartElement(CCNProtocolDTags.Exclude);
208
209 // TODO: Do we want to order the components (except for ANY)?
210 for (var i = 0; i < this.values.length; ++i) {
211 if (this.values[i] == Exclude.ANY) {
212 encoder.writeStartElement(CCNProtocolDTags.Any);
213 encoder.writeEndElement();
214 }
215 else
216 encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
217 }
218
219 encoder.writeEndElement();
220};
221
Jeff Thompson202728a2013-02-10 22:20:08 -0800222/*
223 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
224 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800225Exclude.prototype.to_uri = function() {
226 if (this.values == null || this.values.length == 0)
227 return "";
228
229 var result = "";
230 for (var i = 0; i < this.values.length; ++i) {
231 if (i > 0)
232 result += ",";
Jeff Thompsonfced4c22013-01-27 16:34:13 -0800233
Jeff Thompson08d41b72013-02-03 23:09:29 -0800234 if (this.values[i] == Exclude.ANY)
235 result += "*";
236 else
237 result += Name.toEscapedString(this.values[i]);
238 }
239 return result;
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700240};
Jeff Thompson202728a2013-02-10 22:20:08 -0800241
242/*
243 * Return true if the component matches any of the exclude criteria.
244 */
245Exclude.prototype.matches = function(/*Uint8Array*/ component) {
246 for (var i = 0; i < this.values.length; ++i) {
247 if (this.values[i] == Exclude.ANY) {
248 var lowerBound = null;
249 if (i > 0)
250 lowerBound = this.values[i - 1];
251
252 // Find the upper bound, possibly skipping over multiple ANY in a row.
253 var iUpperBound;
254 var upperBound = null;
255 for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
256 if (this.values[iUpperBound] != Exclude.ANY) {
257 upperBound = this.values[iUpperBound];
258 break;
259 }
260 }
261
262 // If lowerBound != null, we already checked component equals lowerBound on the last pass.
263 // If upperBound != null, we will check component equals upperBound on the next pass.
264 if (upperBound != null) {
265 if (lowerBound != null) {
266 if (Exclude.compareComponents(component, lowerBound) > 0 &&
267 Exclude.compareComponents(component, upperBound) < 0)
268 return true;
269 }
270 else {
271 if (Exclude.compareComponents(component, upperBound) < 0)
272 return true;
273 }
274
275 // Make i equal iUpperBound on the next pass.
276 i = iUpperBound - 1;
277 }
278 else {
279 if (lowerBound != null) {
280 if (Exclude.compareComponents(component, lowerBound) > 0)
281 return true;
282 }
283 else
284 // this.values has only ANY.
285 return true;
286 }
287 }
288 else {
289 if (DataUtils.arraysEqual(component, this.values[i]))
290 return true;
291 }
292 }
293
294 return false;
295};
296
297/*
298 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
299 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
300 */
301Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
302 if (component1.length < component2.length)
303 return -1;
304 if (component1.length > component2.length)
305 return 1;
306
307 for (var i = 0; i < component1.length; ++i) {
308 if (component1[i] < component2[i])
309 return -1;
310 if (component1[i] > component2[i])
311 return 1;
312 }
313
314 return 0;
315};