blob: 692b90cb1b01e26c929486d39f5355fb4ac95ec2 [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
Jeff Thompson86bcd022013-07-26 17:55:03 -070037// Deprecated. Use BinaryXMLWireFormat.decodeInterest.
Jeff Thompson86aea882012-09-29 17:32:48 -070038Interest.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson86bcd022013-07-26 17:55:03 -070039 BinaryXMLWireFormat.decodeInterest(this, decoder);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070040};
41
Jeff Thompson86bcd022013-07-26 17:55:03 -070042// Deprecated. Use BinaryXMLWireFormat.encodeInterest.
Jeff Thompson86aea882012-09-29 17:32:48 -070043Interest.prototype.to_ccnb = function(/*XMLEncoder*/ encoder){
Jeff Thompson86bcd022013-07-26 17:55:03 -070044 BinaryXMLWireFormat.encodeInterest(this, encoder);
45};
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070046
Jeff Thompson86bcd022013-07-26 17:55:03 -070047/**
48 * Encode this Interest for a particular wire format.
49 * @param {WireFormat} wireFormat if null, use BinaryXMLWireFormat.
50 * @returns {Uint8Array}
51 */
52Interest.prototype.encode = function(wireFormat) {
53 wireFormat = (wireFormat || BinaryXMLWireFormat.instance);
54 return wireFormat.encodeInterest(this);
55};
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070056
Jeff Thompson86bcd022013-07-26 17:55:03 -070057/**
58 * Decode the input using a particular wire format and update this Interest.
59 * @param {Uint8Array} input
60 * @param {WireFormat} wireFormat if null, use BinaryXMLWireFormat.
61 */
62Interest.prototype.decode = function(input, wireFormat) {
63 wireFormat = (wireFormat || BinaryXMLWireFormat.instance);
64 wireFormat.decodeInterest(this, input);
Meki Cherkaoui88d59cd2012-05-14 07:34:58 -070065};
66
Jeff Thompson202728a2013-02-10 22:20:08 -080067/*
68 * Return true if this.name.match(name) and the name conforms to the interest selectors.
69 */
Jeff Thompson3f4be552013-01-05 22:36:40 -080070Interest.prototype.matches_name = function(/*Name*/ name) {
Jeff Thompson202728a2013-02-10 22:20:08 -080071 if (!this.name.match(name))
72 return false;
73
74 if (this.minSuffixComponents != null &&
75 // Add 1 for the implicit digest.
76 !(name.components.length + 1 - this.name.components.length >= this.minSuffixComponents))
77 return false;
78 if (this.maxSuffixComponents != null &&
79 // Add 1 for the implicit digest.
80 !(name.components.length + 1 - this.name.components.length <= this.maxSuffixComponents))
81 return false;
82 if (this.exclude != null && name.components.length > this.name.components.length &&
83 this.exclude.matches(name.components[this.name.components.length]))
84 return false;
85
86 return true;
Jeff Thompsonea3a6902013-02-17 21:56:34 -080087};
88
89/*
90 * Return a new Interest with the same fields as this Interest.
91 * Note: This does NOT make a deep clone of the name, exclue or other objects.
92 */
93Interest.prototype.clone = function() {
94 return new Interest
95 (this.name, this.faceInstance, this.minSuffixComponents, this.maxSuffixComponents,
96 this.publisherPublicKeyDigest, this.exclude, this.childSelector, this.answerOriginKind,
97 this.scope, this.interestLifetime, this.nonce);
98};
Jeff Thompson86aea882012-09-29 17:32:48 -070099
Jeff Thompson08d41b72013-02-03 23:09:29 -0800100/*
101 * Handle the interest Exclude element.
102 * _values is an array where each element is either Uint8Array component or Exclude.ANY.
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700103 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800104var Exclude = function Exclude(_values) {
105 this.values = (_values || []);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700106}
107
Jeff Thompson08d41b72013-02-03 23:09:29 -0800108Exclude.ANY = "*";
109
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700110Exclude.prototype.from_ccnb = function(/*XMLDecoder*/ decoder) {
Jeff Thompson08d41b72013-02-03 23:09:29 -0800111 decoder.readStartElement(CCNProtocolDTags.Exclude);
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700112
Jeff Thompson08d41b72013-02-03 23:09:29 -0800113 while (true) {
114 if (decoder.peekStartElement(CCNProtocolDTags.Component))
115 this.values.push(decoder.readBinaryElement(CCNProtocolDTags.Component));
116 else if (decoder.peekStartElement(CCNProtocolDTags.Any)) {
117 decoder.readStartElement(CCNProtocolDTags.Any);
118 decoder.readEndElement();
119 this.values.push(Exclude.ANY);
120 }
121 else if (decoder.peekStartElement(CCNProtocolDTags.Bloom)) {
122 // Skip the Bloom and treat it as Any.
123 decoder.readBinaryElement(CCNProtocolDTags.Bloom);
124 this.values.push(Exclude.ANY);
125 }
126 else
127 break;
128 }
129
130 decoder.readEndElement();
131};
132
133Exclude.prototype.to_ccnb = function(/*XMLEncoder*/ encoder) {
134 if (this.values == null || this.values.length == 0)
135 return;
136
137 encoder.writeStartElement(CCNProtocolDTags.Exclude);
138
139 // TODO: Do we want to order the components (except for ANY)?
140 for (var i = 0; i < this.values.length; ++i) {
141 if (this.values[i] == Exclude.ANY) {
142 encoder.writeStartElement(CCNProtocolDTags.Any);
143 encoder.writeEndElement();
144 }
145 else
146 encoder.writeElement(CCNProtocolDTags.Component, this.values[i]);
147 }
148
149 encoder.writeEndElement();
150};
151
Jeff Thompson202728a2013-02-10 22:20:08 -0800152/*
153 * Return a string with elements separated by "," and Exclude.ANY shown as "*".
154 */
Jeff Thompson08d41b72013-02-03 23:09:29 -0800155Exclude.prototype.to_uri = function() {
156 if (this.values == null || this.values.length == 0)
157 return "";
158
159 var result = "";
160 for (var i = 0; i < this.values.length; ++i) {
161 if (i > 0)
162 result += ",";
Jeff Thompsonfced4c22013-01-27 16:34:13 -0800163
Jeff Thompson08d41b72013-02-03 23:09:29 -0800164 if (this.values[i] == Exclude.ANY)
165 result += "*";
166 else
167 result += Name.toEscapedString(this.values[i]);
168 }
169 return result;
Jeff Thompsonb9ce4582012-09-30 17:52:51 -0700170};
Jeff Thompson202728a2013-02-10 22:20:08 -0800171
172/*
173 * Return true if the component matches any of the exclude criteria.
174 */
175Exclude.prototype.matches = function(/*Uint8Array*/ component) {
176 for (var i = 0; i < this.values.length; ++i) {
177 if (this.values[i] == Exclude.ANY) {
178 var lowerBound = null;
179 if (i > 0)
180 lowerBound = this.values[i - 1];
181
182 // Find the upper bound, possibly skipping over multiple ANY in a row.
183 var iUpperBound;
184 var upperBound = null;
185 for (iUpperBound = i + 1; iUpperBound < this.values.length; ++iUpperBound) {
186 if (this.values[iUpperBound] != Exclude.ANY) {
187 upperBound = this.values[iUpperBound];
188 break;
189 }
190 }
191
192 // If lowerBound != null, we already checked component equals lowerBound on the last pass.
193 // If upperBound != null, we will check component equals upperBound on the next pass.
194 if (upperBound != null) {
195 if (lowerBound != null) {
196 if (Exclude.compareComponents(component, lowerBound) > 0 &&
197 Exclude.compareComponents(component, upperBound) < 0)
198 return true;
199 }
200 else {
201 if (Exclude.compareComponents(component, upperBound) < 0)
202 return true;
203 }
204
205 // Make i equal iUpperBound on the next pass.
206 i = iUpperBound - 1;
207 }
208 else {
209 if (lowerBound != null) {
210 if (Exclude.compareComponents(component, lowerBound) > 0)
211 return true;
212 }
213 else
214 // this.values has only ANY.
215 return true;
216 }
217 }
218 else {
219 if (DataUtils.arraysEqual(component, this.values[i]))
220 return true;
221 }
222 }
223
224 return false;
225};
226
227/*
228 * Return -1 if component1 is less than component2, 1 if greater or 0 if equal.
229 * A component is less if it is shorter, otherwise if equal length do a byte comparison.
230 */
231Exclude.compareComponents = function(/*Uint8Array*/ component1, /*Uint8Array*/ component2) {
232 if (component1.length < component2.length)
233 return -1;
234 if (component1.length > component2.length)
235 return 1;
236
237 for (var i = 0; i < component1.length; ++i) {
238 if (component1[i] < component2[i])
239 return -1;
240 if (component1[i] > component2[i])
241 return 1;
242 }
243
244 return 0;
245};