blob: 8f19f1400d9f96107bda61cd9827636f3b9a0871 [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);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070047
Jeff Thompson5fc9b672012-11-24 10:00:56 -080048 if (decoder.peekStartElement(CCNProtocolDTags.MaxSuffixComponents))
Jeff Thompson86aea882012-09-29 17:32:48 -070049 this.maxSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070050
Jeff Thompson86aea882012-09-29 17:32:48 -070051 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
Jeff Thompson5fc9b672012-11-24 10:00:56 -080052 this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070053 this.publisherPublicKeyDigest.from_ccnb(decoder);
Meki Cherkaoui8f173612012-06-06 01:05:40 -070054 }
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070055
56 if (decoder.peekStartElement(CCNProtocolDTags.Exclude)) {
Jeff Thompson86aea882012-09-29 17:32:48 -070057 this.exclude = new Exclude();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070058 this.exclude.from_ccnb(decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070059 }
60
Jeff Thompson5fc9b672012-11-24 10:00:56 -080061 if (decoder.peekStartElement(CCNProtocolDTags.ChildSelector))
Jeff Thompson86aea882012-09-29 17:32:48 -070062 this.childSelector = decoder.readIntegerElement(CCNProtocolDTags.ChildSelector);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070063
Jeff Thompson5fc9b672012-11-24 10:00:56 -080064 if (decoder.peekStartElement(CCNProtocolDTags.AnswerOriginKind))
Jeff Thompson86aea882012-09-29 17:32:48 -070065 this.answerOriginKind = decoder.readIntegerElement(CCNProtocolDTags.AnswerOriginKind);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070066
Jeff Thompson5fc9b672012-11-24 10:00:56 -080067 if (decoder.peekStartElement(CCNProtocolDTags.Scope))
Jeff Thompson86aea882012-09-29 17:32:48 -070068 this.scope = decoder.readIntegerElement(CCNProtocolDTags.Scope);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070069
Jeff Thompson5fc9b672012-11-24 10:00:56 -080070 if (decoder.peekStartElement(CCNProtocolDTags.InterestLifetime))
Jeff Thompson42806a12012-12-29 18:19:39 -080071 this.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
Jeff Thompson5fc9b672012-11-24 10:00:56 -080072 (decoder.readBinaryElement(CCNProtocolDTags.InterestLifetime)) / 4096;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070073
Jeff Thompson5fc9b672012-11-24 10:00:56 -080074 if (decoder.peekStartElement(CCNProtocolDTags.Nonce))
Jeff Thompson86aea882012-09-29 17:32:48 -070075 this.nonce = decoder.readBinaryElement(CCNProtocolDTags.Nonce);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070076
77 decoder.readEndElement();
78};
79
Jeff Thompson86aea882012-09-29 17:32:48 -070080Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
Meki Cherkaoui8f173612012-06-06 01:05:40 -070081 //Could check if name is present
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070082
83 encoder.writeStartElement(CCNProtocolDTags.Interest);
84
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070085 this.name.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070086
Jeff Thompson86aea882012-09-29 17:32:48 -070087 if (null != this.minSuffixComponents)
88 encoder.writeElement(CCNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070089
Jeff Thompson86aea882012-09-29 17:32:48 -070090 if (null != this.maxSuffixComponents)
91 encoder.writeElement(CCNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070092
Jeff Thompson86aea882012-09-29 17:32:48 -070093 if (null != this.publisherPublicKeyDigest)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070094 this.publisherPublicKeyDigest.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070095
Jeff Thompson86aea882012-09-29 17:32:48 -070096 if (null != this.exclude)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070097 this.exclude.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070098
Jeff Thompson86aea882012-09-29 17:32:48 -070099 if (null != this.childSelector)
100 encoder.writeElement(CCNProtocolDTags.ChildSelector, this.childSelector);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700101
Jeff Thompson86aea882012-09-29 17:32:48 -0700102 if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null)
103 encoder.writeElement(CCNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700104
Jeff Thompson86aea882012-09-29 17:32:48 -0700105 if (null != this.scope)
106 encoder.writeElement(CCNProtocolDTags.Scope, this.scope);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700107
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800108 if (null != this.interestLifetime)
109 encoder.writeElement(CCNProtocolDTags.InterestLifetime,
Jeff Thompson42806a12012-12-29 18:19:39 -0800110 DataUtils.nonNegativeIntToBigEndian((this.interestLifetime / 1000.0) * 4096));
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800111
Jeff Thompson86aea882012-09-29 17:32:48 -0700112 if (null != this.nonce)
113 encoder.writeElement(CCNProtocolDTags.Nonce, this.nonce);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700114
115 encoder.writeEndElement();
116
117};
118
Jeff Thompson202728a2013-02-10 22:20:08 -0800119/*
120 * Return true if this.name.match(name) and the name conforms to the interest selectors.
121 */
Jeff Thompson3f4be552013-01-05 22:36:40 -0800122Interest.prototype.matches_name = function(/*Name*/ name) {
Jeff Thompson202728a2013-02-10 22:20:08 -0800123 if (!this.name.match(name))
124 return false;
125
126 if (this.minSuffixComponents != null &&
127 // Add 1 for the implicit digest.
128 !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
129 return false;
130 if (this.maxSuffixComponents != null &&
131 // Add 1 for the implicit digest.
132 !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
133 return false;
134 if (this.exclude != null && name.components.length > this.name.components.length &&
135 this.exclude.matches(name.components[this.name.components.length]))
136 return false;
137
138 return true;
Jeff Thompsonea3a6902013-02-17 21:56:34 -0800139};
140
141/*
142 * Return a new Interest with the same fields as this Interest.
143 * Note: This does NOT make a deep clone of the name, exclue or other objects.
144 */
145Interest.prototype.clone = function() {
146 return new Interest
147 (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents,
148 this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind,
149 this.scope, this.interestLifetime, this.nonce);
150};
Jeff Thompson86aea882012-09-29 17:32:48 -0700151
Jeff Thompson08d41b72013-02-03 23:09:29 -0800152/*
153 * Handle the interest Exclude element.
154 * _values is an array where each element is either Uint8Array component or Exclude.ANY.
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700155 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800156var Exclude = function Exclude(_values) {
157 this.values = (_values || []);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700158}
159
Jeff Thompson08d41b72013-02-03 23:09:29 -0800160Exclude.ANY = "*";
161
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700162Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson08d41b72013-02-03 23:09:29 -0800163 decoder.readStartElement(CCNProtocolDTags.Exclude);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700164
Jeff Thompson08d41b72013-02-03 23:09:29 -0800165 while (true) {
166 if (decoder.peekStartElement(CCNProtocolDTags.Component))
167 this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
168 else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
169 decoder.readStartElement(CCNProtocolDTags.Any);
170 decoder.readEndElement();
171 this.values.push(Exclude.ANY);
172 }
173 else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
174 // Skip the Bloom and treat it as Any.
175 decoder.readBinaryElement(CCNProtocolDTags.Bloom);
176 this.values.push(Exclude.ANY);
177 }
178 else
179 break;
180 }
181
182 decoder.readEndElement();
183};
184
185Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
186 if (this.values == null || this.values.length == 0)
187 return;
188
189 encoder.writeStartElement(CCNProtocolDTags.Exclude);
190
191 // TODO: Do we want to order the components (except for ANY)?
192 for (var i = 0; i < this.values.length; ++i) {
193 if (this.values[i] == Exclude.ANY) {
194 encoder.writeStartElement(CCNProtocolDTags.Any);
195 encoder.writeEndElement();
196 }
197 else
198 encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
199 }
200
201 encoder.writeEndElement();
202};
203
Jeff Thompson202728a2013-02-10 22:20:08 -0800204/*
205 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
206 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800207Exclude.prototype.to_uri = function() {
208 if (this.values == null || this.values.length == 0)
209 return "";
210
211 var result = "";
212 for (var i = 0; i < this.values.length; ++i) {
213 if (i > 0)
214 result += ",";
Jeff Thompsonfced4c22013-01-27 16:34:13 -0800215
Jeff Thompson08d41b72013-02-03 23:09:29 -0800216 if (this.values[i] == Exclude.ANY)
217 result += "*";
218 else
219 result += Name.toEscapedString(this.values[i]);
220 }
221 return result;
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700222};
Jeff Thompson202728a2013-02-10 22:20:08 -0800223
224/*
225 * Return true if the component matches any of the exclude criteria.
226 */
227Exclude.prototype.matches = function(/*Uint8Array*/ component) {
228 for (var i = 0; i < this.values.length; ++i) {
229 if (this.values[i] == Exclude.ANY) {
230 var lowerBound = null;
231 if (i > 0)
232 lowerBound = this.values[i - 1];
233
234 // Find the upper bound, possibly skipping over multiple ANY in a row.
235 var iUpperBound;
236 var upperBound = null;
237 for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
238 if (this.values[iUpperBound] != Exclude.ANY) {
239 upperBound = this.values[iUpperBound];
240 break;
241 }
242 }
243
244 // If lowerBound != null, we already checked component equals lowerBound on the last pass.
245 // If upperBound != null, we will check component equals upperBound on the next pass.
246 if (upperBound != null) {
247 if (lowerBound != null) {
248 if (Exclude.compareComponents(component, lowerBound) > 0 &&
249 Exclude.compareComponents(component, upperBound) < 0)
250 return true;
251 }
252 else {
253 if (Exclude.compareComponents(component, upperBound) < 0)
254 return true;
255 }
256
257 // Make i equal iUpperBound on the next pass.
258 i = iUpperBound - 1;
259 }
260 else {
261 if (lowerBound != null) {
262 if (Exclude.compareComponents(component, lowerBound) > 0)
263 return true;
264 }
265 else
266 // this.values has only ANY.
267 return true;
268 }
269 }
270 else {
271 if (DataUtils.arraysEqual(component, this.values[i]))
272 return true;
273 }
274 }
275
276 return false;
277};
278
279/*
280 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
281 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
282 */
283Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
284 if (component1.length < component2.length)
285 return -1;
286 if (component1.length > component2.length)
287 return 1;
288
289 for (var i = 0; i < component1.length; ++i) {
290 if (component1[i] < component2[i])
291 return -1;
292 if (component1[i] > component2[i])
293 return 1;
294 }
295
296 return 0;
297};