blob: 8c8ecf15b2fafb6e13d17d6c0cc042b350f2216a [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 Thompson86aea882012-09-29 17:32:48 -07008var Interest = function Interest(_name,_faceInstance,_minSuffixComponents,_maxSuffixComponents,_publisherPublicKeyDigest, _exclude, _childSelector,_answerOriginKind,_scope,_interestLifetime,_nonce){
Meki Cherkaoui8f173612012-06-06 01:05:40 -07009
Jeff Thompson86aea882012-09-29 17:32:48 -070010 this.name = _name;
11 this.faceInstance = _faceInstance;
12 this.maxSuffixComponents = _maxSuffixComponents;
13 this.minSuffixComponents = _minSuffixComponents;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070014
Jeff Thompson86aea882012-09-29 17:32:48 -070015 this.publisherPublicKeyDigest = _publisherPublicKeyDigest;
16 this.exclude = _exclude;
17 this.childSelector = _childSelector;
18 this.answerOriginKind = _answerOriginKind;
19 this.scope = _scope;
Jeff Thompson42806a12012-12-29 18:19:39 -080020 this.interestLifetime = _interestLifetime; // milli seconds
Jeff Thompson5fc9b672012-11-24 10:00:56 -080021 this.nonce = _nonce;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070022};
23
Jeff Thompson821183d2012-11-24 18:46:21 -080024Interest.RECURSIVE_POSTFIX = "*";
25
26Interest.CHILD_SELECTOR_LEFT = 0;
27Interest.CHILD_SELECTOR_RIGHT = 1;
28Interest.ANSWER_CONTENT_STORE = 1;
29Interest.ANSWER_GENERATED = 2;
30Interest.ANSWER_STALE = 4; // Stale answer OK
31Interest.MARK_STALE = 16; // Must have scope 0. Michael calls this a "hack"
32
33Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
34
35
Jeff Thompson86aea882012-09-29 17:32:48 -070036Interest.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070037
38 decoder.readStartElement(CCNProtocolDTags.Interest);
39
Jeff Thompsonf3bd3592012-09-29 23:25:30 -070040 this.name = new Name();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070041 this.name.from_ccnb(decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070042
Jeff Thompson5fc9b672012-11-24 10:00:56 -080043 if (decoder.peekStartElement(CCNProtocolDTags.MinSuffixComponents))
Jeff Thompson86aea882012-09-29 17:32:48 -070044 this.minSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MinSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070045
Jeff Thompson5fc9b672012-11-24 10:00:56 -080046 if (decoder.peekStartElement(CCNProtocolDTags.MaxSuffixComponents))
Jeff Thompson86aea882012-09-29 17:32:48 -070047 this.maxSuffixComponents = decoder.readIntegerElement(CCNProtocolDTags.MaxSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070048
Jeff Thompson86aea882012-09-29 17:32:48 -070049 if (decoder.peekStartElement(CCNProtocolDTags.PublisherPublicKeyDigest)) {
Jeff Thompson5fc9b672012-11-24 10:00:56 -080050 this.publisherPublicKeyDigest = new PublisherPublicKeyDigest();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070051 this.publisherPublicKeyDigest.from_ccnb(decoder);
Meki Cherkaoui8f173612012-06-06 01:05:40 -070052 }
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070053
54 if (decoder.peekStartElement(CCNProtocolDTags.Exclude)) {
Jeff Thompson86aea882012-09-29 17:32:48 -070055 this.exclude = new Exclude();
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070056 this.exclude.from_ccnb(decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070057 }
58
Jeff Thompson5fc9b672012-11-24 10:00:56 -080059 if (decoder.peekStartElement(CCNProtocolDTags.ChildSelector))
Jeff Thompson86aea882012-09-29 17:32:48 -070060 this.childSelector = decoder.readIntegerElement(CCNProtocolDTags.ChildSelector);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070061
Jeff Thompson5fc9b672012-11-24 10:00:56 -080062 if (decoder.peekStartElement(CCNProtocolDTags.AnswerOriginKind))
Jeff Thompson86aea882012-09-29 17:32:48 -070063 this.answerOriginKind = decoder.readIntegerElement(CCNProtocolDTags.AnswerOriginKind);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070064
Jeff Thompson5fc9b672012-11-24 10:00:56 -080065 if (decoder.peekStartElement(CCNProtocolDTags.Scope))
Jeff Thompson86aea882012-09-29 17:32:48 -070066 this.scope = decoder.readIntegerElement(CCNProtocolDTags.Scope);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070067
Jeff Thompson5fc9b672012-11-24 10:00:56 -080068 if (decoder.peekStartElement(CCNProtocolDTags.InterestLifetime))
Jeff Thompson42806a12012-12-29 18:19:39 -080069 this.interestLifetime = 1000.0 * DataUtils.bigEndianToUnsignedInt
Jeff Thompson5fc9b672012-11-24 10:00:56 -080070 (decoder.readBinaryElement(CCNProtocolDTags.InterestLifetime)) / 4096;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070071
Jeff Thompson5fc9b672012-11-24 10:00:56 -080072 if (decoder.peekStartElement(CCNProtocolDTags.Nonce))
Jeff Thompson86aea882012-09-29 17:32:48 -070073 this.nonce = decoder.readBinaryElement(CCNProtocolDTags.Nonce);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070074
75 decoder.readEndElement();
76};
77
Jeff Thompson86aea882012-09-29 17:32:48 -070078Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
Meki Cherkaoui8f173612012-06-06 01:05:40 -070079 //Could check if name is present
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070080
81 encoder.writeStartElement(CCNProtocolDTags.Interest);
82
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070083 this.name.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070084
Jeff Thompson86aea882012-09-29 17:32:48 -070085 if (null != this.minSuffixComponents)
86 encoder.writeElement(CCNProtocolDTags.MinSuffixComponents, this.minSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070087
Jeff Thompson86aea882012-09-29 17:32:48 -070088 if (null != this.maxSuffixComponents)
89 encoder.writeElement(CCNProtocolDTags.MaxSuffixComponents, this.maxSuffixComponents);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070090
Jeff Thompson86aea882012-09-29 17:32:48 -070091 if (null != this.publisherPublicKeyDigest)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070092 this.publisherPublicKeyDigest.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070093
Jeff Thompson86aea882012-09-29 17:32:48 -070094 if (null != this.exclude)
Jeff Thompsone85ff1d2012-09-29 21:21:57 -070095 this.exclude.to_ccnb(encoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070096
Jeff Thompson86aea882012-09-29 17:32:48 -070097 if (null != this.childSelector)
98 encoder.writeElement(CCNProtocolDTags.ChildSelector, this.childSelector);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070099
Jeff Thompson86aea882012-09-29 17:32:48 -0700100 if (this.DEFAULT_ANSWER_ORIGIN_KIND != this.answerOriginKind && this.answerOriginKind!=null)
101 encoder.writeElement(CCNProtocolDTags.AnswerOriginKind, this.answerOriginKind);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700102
Jeff Thompson86aea882012-09-29 17:32:48 -0700103 if (null != this.scope)
104 encoder.writeElement(CCNProtocolDTags.Scope, this.scope);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700105
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800106 if (null != this.interestLifetime)
107 encoder.writeElement(CCNProtocolDTags.InterestLifetime,
Jeff Thompson42806a12012-12-29 18:19:39 -0800108 DataUtils.nonNegativeIntToBigEndian((this.interestLifetime / 1000.0) * 4096));
Jeff Thompson5fc9b672012-11-24 10:00:56 -0800109
Jeff Thompson86aea882012-09-29 17:32:48 -0700110 if (null != this.nonce)
111 encoder.writeElement(CCNProtocolDTags.Nonce, this.nonce);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -0700112
113 encoder.writeEndElement();
114
115};
116
Jeff Thompson202728a2013-02-10 22:20:08 -0800117/*
118 * Return true if this.name.match(name) and the name conforms to the interest selectors.
119 */
Jeff Thompson3f4be552013-01-05 22:36:40 -0800120Interest.prototype.matches_name = function(/*Name*/ name) {
Jeff Thompson202728a2013-02-10 22:20:08 -0800121 if (!this.name.match(name))
122 return false;
123
124 if (this.minSuffixComponents != null &&
125 // Add 1 for the implicit digest.
126 !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
127 return false;
128 if (this.maxSuffixComponents != null &&
129 // Add 1 for the implicit digest.
130 !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
131 return false;
132 if (this.exclude != null && name.components.length > this.name.components.length &&
133 this.exclude.matches(name.components[this.name.components.length]))
134 return false;
135
136 return true;
Jeff Thompson86aea882012-09-29 17:32:48 -0700137}
138
Jeff Thompson08d41b72013-02-03 23:09:29 -0800139/*
140 * Handle the interest Exclude element.
141 * _values is an array where each element is either Uint8Array component or Exclude.ANY.
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700142 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800143var Exclude = function Exclude(_values) {
144 this.values = (_values || []);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700145}
146
Jeff Thompson08d41b72013-02-03 23:09:29 -0800147Exclude.ANY = "*";
148
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700149Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson08d41b72013-02-03 23:09:29 -0800150 decoder.readStartElement(CCNProtocolDTags.Exclude);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700151
Jeff Thompson08d41b72013-02-03 23:09:29 -0800152 while (true) {
153 if (decoder.peekStartElement(CCNProtocolDTags.Component))
154 this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
155 else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
156 decoder.readStartElement(CCNProtocolDTags.Any);
157 decoder.readEndElement();
158 this.values.push(Exclude.ANY);
159 }
160 else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
161 // Skip the Bloom and treat it as Any.
162 decoder.readBinaryElement(CCNProtocolDTags.Bloom);
163 this.values.push(Exclude.ANY);
164 }
165 else
166 break;
167 }
168
169 decoder.readEndElement();
170};
171
172Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
173 if (this.values == null || this.values.length == 0)
174 return;
175
176 encoder.writeStartElement(CCNProtocolDTags.Exclude);
177
178 // TODO: Do we want to order the components (except for ANY)?
179 for (var i = 0; i < this.values.length; ++i) {
180 if (this.values[i] == Exclude.ANY) {
181 encoder.writeStartElement(CCNProtocolDTags.Any);
182 encoder.writeEndElement();
183 }
184 else
185 encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
186 }
187
188 encoder.writeEndElement();
189};
190
Jeff Thompson202728a2013-02-10 22:20:08 -0800191/*
192 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
193 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800194Exclude.prototype.to_uri = function() {
195 if (this.values == null || this.values.length == 0)
196 return "";
197
198 var result = "";
199 for (var i = 0; i < this.values.length; ++i) {
200 if (i > 0)
201 result += ",";
Jeff Thompsonfced4c22013-01-27 16:34:13 -0800202
Jeff Thompson08d41b72013-02-03 23:09:29 -0800203 if (this.values[i] == Exclude.ANY)
204 result += "*";
205 else
206 result += Name.toEscapedString(this.values[i]);
207 }
208 return result;
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700209};
Jeff Thompson202728a2013-02-10 22:20:08 -0800210
211/*
212 * Return true if the component matches any of the exclude criteria.
213 */
214Exclude.prototype.matches = function(/*Uint8Array*/ component) {
215 for (var i = 0; i < this.values.length; ++i) {
216 if (this.values[i] == Exclude.ANY) {
217 var lowerBound = null;
218 if (i > 0)
219 lowerBound = this.values[i - 1];
220
221 // Find the upper bound, possibly skipping over multiple ANY in a row.
222 var iUpperBound;
223 var upperBound = null;
224 for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
225 if (this.values[iUpperBound] != Exclude.ANY) {
226 upperBound = this.values[iUpperBound];
227 break;
228 }
229 }
230
231 // If lowerBound != null, we already checked component equals lowerBound on the last pass.
232 // If upperBound != null, we will check component equals upperBound on the next pass.
233 if (upperBound != null) {
234 if (lowerBound != null) {
235 if (Exclude.compareComponents(component, lowerBound) > 0 &&
236 Exclude.compareComponents(component, upperBound) < 0)
237 return true;
238 }
239 else {
240 if (Exclude.compareComponents(component, upperBound) < 0)
241 return true;
242 }
243
244 // Make i equal iUpperBound on the next pass.
245 i = iUpperBound - 1;
246 }
247 else {
248 if (lowerBound != null) {
249 if (Exclude.compareComponents(component, lowerBound) > 0)
250 return true;
251 }
252 else
253 // this.values has only ANY.
254 return true;
255 }
256 }
257 else {
258 if (DataUtils.arraysEqual(component, this.values[i]))
259 return true;
260 }
261 }
262
263 return false;
264};
265
266/*
267 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
268 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
269 */
270Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
271 if (component1.length < component2.length)
272 return -1;
273 if (component1.length > component2.length)
274 return 1;
275
276 for (var i = 0; i < component1.length; ++i) {
277 if (component1[i] < component2[i])
278 return -1;
279 if (component1[i] > component2[i])
280 return 1;
281 }
282
283 return 0;
284};