blob: 8a507eb9db99ed3ff1636225707b332a381c1075 [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 Thompson2b14c7e2013-07-29 15:09:56 -07007/**
8 * Create a new Interest with the optional values.
9 *
10 * @constructor
11 * @param {Name} name
12 * @param {FaceInstance} faceInstance
13 * @param {number} minSuffixComponents
14 * @param {number} maxSuffixComponents
15 * @param {Uint8Array} publisherPublicKeyDigest
16 * @param {Exclude} exclude
17 * @param {number} childSelector
18 * @param {number} answerOriginKind
19 * @param {number} scope
20 * @param {number} interestLifetime in milliseconds
21 * @param {Uint8Array} nonce
22 */
Jeff Thompsonea3a6902013-02-17 21:56:34 -080023var Interest = function Interest
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070024 (name, faceInstance, minSuffixComponents, maxSuffixComponents, publisherPublicKeyDigest, exclude,
Jeff Thompson2256e9c2013-07-31 16:59:41 -070025 childSelector, answerOriginKind, scope, interestLifetimeMilliseconds, nonce) {
Meki Cherkaoui8f173612012-06-06 01:05:40 -070026
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070027 this.name = name;
28 this.faceInstance = faceInstance;
29 this.maxSuffixComponents = maxSuffixComponents;
30 this.minSuffixComponents = minSuffixComponents;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070031
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070032 this.publisherPublicKeyDigest = publisherPublicKeyDigest;
33 this.exclude = exclude;
34 this.childSelector = childSelector;
35 this.answerOriginKind = answerOriginKind;
36 this.scope = scope;
Jeff Thompson2256e9c2013-07-31 16:59:41 -070037 this.interestLifetime = interestLifetimeMilliseconds;
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070038 this.nonce = nonce;
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070039};
40
Jeff Thompson821183d2012-11-24 18:46:21 -080041Interest.RECURSIVE_POSTFIX = "*";
42
43Interest.CHILD_SELECTOR_LEFT = 0;
44Interest.CHILD_SELECTOR_RIGHT = 1;
45Interest.ANSWER_CONTENT_STORE = 1;
46Interest.ANSWER_GENERATED = 2;
47Interest.ANSWER_STALE = 4; // Stale answer OK
48Interest.MARK_STALE = 16; // Must have scope 0. Michael calls this a "hack"
49
50Interest.DEFAULT_ANSWER_ORIGIN_KIND = Interest.ANSWER_CONTENT_STORE | Interest.ANSWER_GENERATED;
51
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070052/**
53 * @deprecated Use BinaryXMLWireFormat.decodeInterest.
54 */
Jeff Thompson86aea882012-09-29 17:32:48 -070055Interest.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson86bcd022013-07-26 17:55:03 -070056 BinaryXMLWireFormat.decodeInterest(this, decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070057};
58
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070059/**
60 * @deprecated Use BinaryXMLWireFormat.encodeInterest.
61 */
Jeff Thompson86aea882012-09-29 17:32:48 -070062Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
Jeff Thompson86bcd022013-07-26 17:55:03 -070063 BinaryXMLWireFormat.encodeInterest(this, encoder);
64};
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070065
Jeff Thompson86bcd022013-07-26 17:55:03 -070066/**
67 * Encode this Interest for a particular wire format.
68 * @param {WireFormat} wireFormat if null, use BinaryXMLWireFormat.
69 * @returns {Uint8Array}
70 */
71Interest.prototype.encode = function(wireFormat) {
72 wireFormat = (wireFormat || BinaryXMLWireFormat.instance);
73 return wireFormat.encodeInterest(this);
74};
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070075
Jeff Thompson86bcd022013-07-26 17:55:03 -070076/**
77 * Decode the input using a particular wire format and update this Interest.
78 * @param {Uint8Array} input
79 * @param {WireFormat} wireFormat if null, use BinaryXMLWireFormat.
80 */
81Interest.prototype.decode = function(input, wireFormat) {
82 wireFormat = (wireFormat || BinaryXMLWireFormat.instance);
83 wireFormat.decodeInterest(this, input);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070084};
85
Jeff Thompson2b14c7e2013-07-29 15:09:56 -070086/**
Jeff Thompson202728a2013-02-10 22:20:08 -080087 * Return true if this.name.match(name) and the name conforms to the interest selectors.
88 */
Jeff Thompson3f4be552013-01-05 22:36:40 -080089Interest.prototype.matches_name = function(/*Name*/ name) {
Jeff Thompson202728a2013-02-10 22:20:08 -080090 if (!this.name.match(name))
91 return false;
92
93 if (this.minSuffixComponents != null &&
94 // Add 1 for the implicit digest.
95 !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
96 return false;
97 if (this.maxSuffixComponents != null &&
98 // Add 1 for the implicit digest.
99 !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
100 return false;
101 if (this.exclude != null && name.components.length > this.name.components.length &&
102 this.exclude.matches(name.components[this.name.components.length]))
103 return false;
104
105 return true;
Jeff Thompsonea3a6902013-02-17 21:56:34 -0800106};
107
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700108/**
Jeff Thompsonea3a6902013-02-17 21:56:34 -0800109 * Return a new Interest with the same fields as this Interest.
110 * Note: This does NOT make a deep clone of the name, exclue or other objects.
111 */
112Interest.prototype.clone = function() {
113 return new Interest
114 (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents,
115 this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind,
116 this.scope, this.interestLifetime, this.nonce);
117};
Jeff Thompson86aea882012-09-29 17:32:48 -0700118
Jeff Thompson08d41b72013-02-03 23:09:29 -0800119/*
120 * Handle the interest Exclude element.
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700121 * values is
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700122 */
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700123
124/**
125 *
126 * @constructor
127 * @param {Array<Uint8Array|Exclude.ANY>} values an array where each element is either Uint8Array component or Exclude.ANY.
128 */
129var Exclude = function Exclude(values) {
130 this.values = (values || []);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700131}
132
Jeff Thompson08d41b72013-02-03 23:09:29 -0800133Exclude.ANY = "*";
134
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700135Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson08d41b72013-02-03 23:09:29 -0800136 decoder.readStartElement(CCNProtocolDTags.Exclude);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700137
Jeff Thompson08d41b72013-02-03 23:09:29 -0800138 while (true) {
139 if (decoder.peekStartElement(CCNProtocolDTags.Component))
140 this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
141 else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
142 decoder.readStartElement(CCNProtocolDTags.Any);
143 decoder.readEndElement();
144 this.values.push(Exclude.ANY);
145 }
146 else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
147 // Skip the Bloom and treat it as Any.
148 decoder.readBinaryElement(CCNProtocolDTags.Bloom);
149 this.values.push(Exclude.ANY);
150 }
151 else
152 break;
153 }
154
155 decoder.readEndElement();
156};
157
158Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
159 if (this.values == null || this.values.length == 0)
160 return;
161
162 encoder.writeStartElement(CCNProtocolDTags.Exclude);
163
164 // TODO: Do we want to order the components (except for ANY)?
165 for (var i = 0; i < this.values.length; ++i) {
166 if (this.values[i] == Exclude.ANY) {
167 encoder.writeStartElement(CCNProtocolDTags.Any);
168 encoder.writeEndElement();
169 }
170 else
171 encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
172 }
173
174 encoder.writeEndElement();
175};
176
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700177/**
Jeff Thompson202728a2013-02-10 22:20:08 -0800178 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
179 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800180Exclude.prototype.to_uri = function() {
181 if (this.values == null || this.values.length == 0)
182 return "";
183
184 var result = "";
185 for (var i = 0; i < this.values.length; ++i) {
186 if (i > 0)
187 result += ",";
Jeff Thompsonfced4c22013-01-27 16:34:13 -0800188
Jeff Thompson08d41b72013-02-03 23:09:29 -0800189 if (this.values[i] == Exclude.ANY)
190 result += "*";
191 else
192 result += Name.toEscapedString(this.values[i]);
193 }
194 return result;
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700195};
Jeff Thompson202728a2013-02-10 22:20:08 -0800196
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700197/**
Jeff Thompson202728a2013-02-10 22:20:08 -0800198 * Return true if the component matches any of the exclude criteria.
199 */
200Exclude.prototype.matches = function(/*Uint8Array*/ component) {
201 for (var i = 0; i < this.values.length; ++i) {
202 if (this.values[i] == Exclude.ANY) {
203 var lowerBound = null;
204 if (i > 0)
205 lowerBound = this.values[i - 1];
206
207 // Find the upper bound, possibly skipping over multiple ANY in a row.
208 var iUpperBound;
209 var upperBound = null;
210 for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
211 if (this.values[iUpperBound] != Exclude.ANY) {
212 upperBound = this.values[iUpperBound];
213 break;
214 }
215 }
216
217 // If lowerBound != null, we already checked component equals lowerBound on the last pass.
218 // If upperBound != null, we will check component equals upperBound on the next pass.
219 if (upperBound != null) {
220 if (lowerBound != null) {
221 if (Exclude.compareComponents(component, lowerBound) > 0 &&
222 Exclude.compareComponents(component, upperBound) < 0)
223 return true;
224 }
225 else {
226 if (Exclude.compareComponents(component, upperBound) < 0)
227 return true;
228 }
229
230 // Make i equal iUpperBound on the next pass.
231 i = iUpperBound - 1;
232 }
233 else {
234 if (lowerBound != null) {
235 if (Exclude.compareComponents(component, lowerBound) > 0)
236 return true;
237 }
238 else
239 // this.values has only ANY.
240 return true;
241 }
242 }
243 else {
244 if (DataUtils.arraysEqual(component, this.values[i]))
245 return true;
246 }
247 }
248
249 return false;
250};
251
Jeff Thompson2b14c7e2013-07-29 15:09:56 -0700252/**
Jeff Thompson202728a2013-02-10 22:20:08 -0800253 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
254 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
255 */
256Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
257 if (component1.length < component2.length)
258 return -1;
259 if (component1.length > component2.length)
260 return 1;
261
262 for (var i = 0; i < component1.length; ++i) {
263 if (component1[i] < component2[i])
264 return -1;
265 if (component1[i] > component2[i])
266 return 1;
267 }
268
269 return 0;
270};