/
Interest.java
826 lines (743 loc) · 27.3 KB
/
Interest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
/**
* Copyright (C) 2013-2016 Regents of the University of California.
* @author: Jeff Thompson <jefft0@remap.ucla.edu>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
package net.named_data.jndn;
import java.nio.ByteBuffer;
import java.util.Random;
import net.named_data.jndn.encoding.EncodingException;
import net.named_data.jndn.encoding.WireFormat;
import net.named_data.jndn.lp.IncomingFaceId;
import net.named_data.jndn.lp.LpPacket;
import net.named_data.jndn.util.Blob;
import net.named_data.jndn.util.ChangeCountable;
import net.named_data.jndn.util.ChangeCounter;
import net.named_data.jndn.util.SignedBlob;
/**
* An Interest holds a Name and other fields for an interest.
*/
public class Interest implements ChangeCountable {
/**
* Create a new Interest with the given name and interest lifetime and "none"
* for other values.
* @param name The name for the interest.
* @param interestLifetimeMilliseconds The interest lifetime in milliseconds,
* or -1 for none.
*/
public
Interest(Name name, double interestLifetimeMilliseconds)
{
if (name != null)
name_.set(new Name(name));
interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
}
/**
* Create a new Interest with the given name and "none" for other values.
* @param name The name for the interest.
*/
public
Interest(Name name)
{
if (name != null)
name_.set(new Name(name));
}
/**
* Create a new interest as a deep copy of the given interest.
* @param interest The interest to copy.
*/
public
Interest(Interest interest)
{
name_.set(new Name(interest.getName()));
minSuffixComponents_ = interest.minSuffixComponents_;
maxSuffixComponents_ = interest.maxSuffixComponents_;
keyLocator_.set(new KeyLocator(interest.getKeyLocator()));
exclude_.set(new Exclude(interest.getExclude()));
childSelector_ = interest.childSelector_;
mustBeFresh_ = interest.mustBeFresh_;
interestLifetimeMilliseconds_ = interest.interestLifetimeMilliseconds_;
nonce_ = interest.getNonce();
linkWireEncoding_ = interest.linkWireEncoding_;
linkWireEncodingFormat_ = interest.linkWireEncodingFormat_;
if (interest.link_.get() != null)
link_.set(new Link((Link)interest.link_.get()));
selectedDelegationIndex_ = interest.selectedDelegationIndex_;
setDefaultWireEncoding
(interest.getDefaultWireEncoding(), interest.defaultWireEncodingFormat_);
}
/**
* Create a new Interest with an empty name and "none" for all values.
*/
public
Interest()
{
}
public static final int CHILD_SELECTOR_LEFT = 0;
public static final int CHILD_SELECTOR_RIGHT = 1;
/**
* Encode this Interest for a particular wire format. If wireFormat is the
* default wire format, also set the defaultWireEncoding field to the encoded
* result.
* @param wireFormat A WireFormat object used to encode this Interest.
* @return The encoded buffer.
*/
public final SignedBlob
wireEncode(WireFormat wireFormat)
{
if (!getDefaultWireEncoding().isNull() &&
getDefaultWireEncodingFormat() == wireFormat)
// We already have an encoding in the desired format.
return getDefaultWireEncoding();
int[] signedPortionBeginOffset = new int[1];
int[] signedPortionEndOffset = new int[1];
Blob encoding = wireFormat.encodeInterest
(this, signedPortionBeginOffset, signedPortionEndOffset);
SignedBlob wireEncoding = new SignedBlob
(encoding, signedPortionBeginOffset[0], signedPortionEndOffset[0]);
if (wireFormat == WireFormat.getDefaultWireFormat())
// This is the default wire encoding.
setDefaultWireEncoding(wireEncoding, WireFormat.getDefaultWireFormat());
return wireEncoding;
}
/**
* Encode this Interest for the default wire format
* WireFormat.getDefaultWireFormat().
* @return The encoded buffer.
*/
public final SignedBlob
wireEncode()
{
return wireEncode(WireFormat.getDefaultWireFormat());
}
/**
* Decode the input using a particular wire format and update this Interest.
* @param input The input buffer to decode. This reads from position() to
* limit(), but does not change the position.
* @param wireFormat A WireFormat object used to decode the input.
* @throws EncodingException For invalid encoding.
*/
public final void
wireDecode(ByteBuffer input, WireFormat wireFormat) throws EncodingException
{
int[] signedPortionBeginOffset = new int[1];
int[] signedPortionEndOffset = new int[1];
wireFormat.decodeInterest
(this, input, signedPortionBeginOffset, signedPortionEndOffset);
if (wireFormat == WireFormat.getDefaultWireFormat())
// This is the default wire encoding.
setDefaultWireEncoding
(new SignedBlob(input, true, signedPortionBeginOffset[0],
signedPortionEndOffset[0]), WireFormat.getDefaultWireFormat());
else
setDefaultWireEncoding(new SignedBlob(), null);
}
/**
* Decode the input using the default wire format
* WireFormat.getDefaultWireFormat() and update this Interest.
* @param input The input buffer to decode. This reads from position() to
* limit(), but does not change the position.
* @throws EncodingException For invalid encoding.
*/
public final void
wireDecode(ByteBuffer input) throws EncodingException
{
wireDecode(input, WireFormat.getDefaultWireFormat());
}
/**
* Decode the input using a particular wire format and update this Interest. If
* wireFormat is the default wire format, also set the defaultWireEncoding
* field another pointer to the input Blob.
* @param input The input blob to decode.
* @param wireFormat A WireFormat object used to decode the input.
* @throws EncodingException For invalid encoding.
*/
public final void
wireDecode(Blob input, WireFormat wireFormat) throws EncodingException
{
int[] signedPortionBeginOffset = new int[1];
int[] signedPortionEndOffset = new int[1];
wireFormat.decodeInterest
(this, input.buf(), signedPortionBeginOffset, signedPortionEndOffset);
if (wireFormat == WireFormat.getDefaultWireFormat())
// This is the default wire encoding.
setDefaultWireEncoding
(new SignedBlob(input, signedPortionBeginOffset[0],
signedPortionEndOffset[0]), WireFormat.getDefaultWireFormat());
else
setDefaultWireEncoding(new SignedBlob(), null);
}
/**
* Decode the input using the default wire format
* WireFormat.getDefaultWireFormat() and update this Interest.
* @param input The input blob to decode.
* @throws EncodingException For invalid encoding.
*/
public final void
wireDecode(Blob input) throws EncodingException
{
wireDecode(input, WireFormat.getDefaultWireFormat());
}
/**
* Encode the name according to the "NDN URI Scheme". If there are interest
* selectors, append "?" and added the selectors as a query string. For
* example "/test/name?ndn.ChildSelector=1".
* @return The URI string.
* @note This is an experimental feature. See the API docs for more detail at
* http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method .
*/
public final String
toUri()
{
StringBuffer selectors = new StringBuffer();
if (minSuffixComponents_ >= 0)
selectors.append("&ndn.MinSuffixComponents=").append(minSuffixComponents_);
if (maxSuffixComponents_ >= 0)
selectors.append("&ndn.MaxSuffixComponents=").append(maxSuffixComponents_);
if (childSelector_ >= 0)
selectors.append("&ndn.ChildSelector=").append(childSelector_);
selectors.append("&ndn.MustBeFresh=").append(mustBeFresh_ ? 1 : 0);
if (interestLifetimeMilliseconds_ >= 0)
selectors.append("&ndn.InterestLifetime=").append
((long)Math.round(interestLifetimeMilliseconds_));
if (nonce_.size() > 0) {
selectors.append("&ndn.Nonce=");
Name.toEscapedString(nonce_.buf(), selectors);
}
if (getExclude().size() > 0)
selectors.append("&ndn.Exclude=").append(getExclude().toUri());
StringBuffer result = new StringBuffer();
result.append(getName().toUri());
String selectorsString = selectors.toString();
if (selectorsString.length() > 0)
// Replace the first & with ?.
result.append("?").append(selectorsString.substring(1));
return result.toString();
}
public final Name
getName() { return (Name)name_.get(); }
public final int
getMinSuffixComponents() { return minSuffixComponents_; }
public final int
getMaxSuffixComponents() { return maxSuffixComponents_; }
public final KeyLocator
getKeyLocator() { return (KeyLocator)keyLocator_.get(); }
public final Exclude
getExclude() { return (Exclude)exclude_.get(); }
public final int
getChildSelector() { return childSelector_; }
/**
* Get the must be fresh flag. If not specified, the default is true.
* @return The must be fresh flag.
*/
public final boolean
getMustBeFresh() { return mustBeFresh_; }
public final double
getInterestLifetimeMilliseconds() { return interestLifetimeMilliseconds_; }
/**
* Return the nonce value from the incoming interest. If you change any of
* the fields in this Interest object, then the nonce value is cleared.
* @return The nonce.
*/
public final Blob
getNonce()
{
if (getNonceChangeCount_ != getChangeCount()) {
// The values have changed, so the existing nonce is invalidated.
nonce_ = new Blob();
getNonceChangeCount_ = getChangeCount();
}
return nonce_;
}
/**
* Check if this interest has a link object (or a link wire encoding which
* can be decoded to make the link object).
* @return True if this interest has a link object, false if not.
*/
public final boolean
hasLink()
{
return link_.get() != null || !linkWireEncoding_.isNull();
}
/**
* Get the link object. If necessary, decode it from the link wire encoding.
* @return The link object, or null if not specified.
* @throws EncodingException For error decoding the link wire encoding (if
* necessary).
*/
public final Link
getLink() throws EncodingException
{
if (link_.get() != null)
return (Link)link_.get();
else if (!linkWireEncoding_.isNull()) {
// Decode the link object from linkWireEncoding_.
Link link = new Link();
link.wireDecode(linkWireEncoding_, linkWireEncodingFormat_);
link_.set(link);
// Clear linkWireEncoding_ since it is now managed by the link object.
linkWireEncoding_ = new Blob();
linkWireEncodingFormat_ = null;
return link;
}
else
return null;
}
/**
* Get the wire encoding of the link object. If there is already a wire
* encoding then return it. Otherwise encode from the link object (if
* available).
* @param wireFormat The desired wire format for the encoding.
* @return The wire encoding, or an isNull Blob if the link is not specified.
* @throws EncodingException for error encoding the link object.
*/
public final Blob
getLinkWireEncoding(WireFormat wireFormat) throws EncodingException
{
if (!linkWireEncoding_.isNull() && linkWireEncodingFormat_ == wireFormat)
return linkWireEncoding_;
Link link = getLink();
if (link != null)
return link.wireEncode(wireFormat);
else
return new Blob();
}
/**
* Get the wire encoding of the link object. If there is already a wire
* encoding then return it. Otherwise encode from the link object (if
* available).
* @return The wire encoding, or an isNull Blob if the link is not specified.
* @throws EncodingException for error encoding the link object.
*/
public final Blob
getLinkWireEncoding() throws EncodingException
{
return getLinkWireEncoding(WireFormat.getDefaultWireFormat());
}
/**
* Get the selected delegation index.
* @return The selected delegation index. If not specified, return -1.
*/
public final int
getSelectedDelegationIndex() { return selectedDelegationIndex_; }
/**
* Get the incoming face ID according to the incoming packet header.
* @return The incoming face ID. If not specified, return -1.
*/
public final long
getIncomingFaceId()
{
IncomingFaceId field =
lpPacket_ == null ? null : IncomingFaceId.getFirstHeader(lpPacket_);
return field == null ? -1 : field.getFaceId();
}
/**
* Set the interest name.
* @note You can also call getName and change the name values directly.
* @param name The interest name. This makes a copy of the name.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setName(Name name)
{
name_.set(name == null ? new Name() : new Name(name));
++changeCount_;
return this;
}
/**
* Set the min suffix components count.
* @param minSuffixComponents The min suffix components count. If not
* specified, set to -1.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setMinSuffixComponents(int minSuffixComponents)
{
minSuffixComponents_ = minSuffixComponents;
++changeCount_;
return this;
}
/**
* Set the max suffix components count.
* @param maxSuffixComponents The max suffix components count. If not
* specified, set to -1.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setMaxSuffixComponents(int maxSuffixComponents)
{
maxSuffixComponents_ = maxSuffixComponents;
++changeCount_;
return this;
}
/**
* Set the child selector.
* @param childSelector The child selector. If not specified, set to -1.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setChildSelector(int childSelector)
{
childSelector_ = childSelector;
++changeCount_;
return this;
}
/**
* Set the MustBeFresh flag.
* @param mustBeFresh True if the content must be fresh, otherwise false. If
* you do not set this flag, the default value is true.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setMustBeFresh(boolean mustBeFresh)
{
mustBeFresh_ = mustBeFresh;
++changeCount_;
return this;
}
/**
* Set the interest lifetime.
* @param interestLifetimeMilliseconds The interest lifetime in milliseconds.
* If not specified, set to -1.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setInterestLifetimeMilliseconds(double interestLifetimeMilliseconds)
{
interestLifetimeMilliseconds_ = interestLifetimeMilliseconds;
++changeCount_;
return this;
}
/**
* @deprecated You should let the wire encoder generate a random nonce
* internally before sending the interest.
*/
public final Interest
setNonce(Blob nonce)
{
nonce_ = (nonce == null ? new Blob() : nonce);
// Set getNonceChangeCount_ so that the next call to getNonce() won't
// clear nonce_.
++changeCount_;
getNonceChangeCount_ = getChangeCount();
return this;
}
/**
* Set this interest to use a copy of the given KeyLocator object.
* @note You can also call getKeyLocator and change the key locator directly.
* @param keyLocator The KeyLocator object. This makes a copy of the object.
* If no key locator is specified, set to a new default KeyLocator(), or to a
* KeyLocator with an unspecified type.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setKeyLocator(KeyLocator keyLocator)
{
keyLocator_.set(keyLocator == null ? new KeyLocator() : new KeyLocator(keyLocator));
++changeCount_;
return this;
}
/**
* Set this interest to use a copy of the given Exclude object.
* @note You can also call getExclude and change the exclude entries directly.
* @param exclude The Exclude object. This makes a copy of the object. If no
* exclude is specified, set to a new default Exclude(), or to an Exclude with
* size() 0.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setExclude(Exclude exclude)
{
exclude_.set(exclude == null ? new Exclude() : new Exclude(exclude));
++changeCount_;
return this;
}
/**
* Set the link wire encoding bytes, without decoding them. If there is
* a link object, set it to null. If you later call getLink(), it will
* decode the wireEncoding to create the link object.
* @param encoding The buffer with the bytes of the link wire encoding.
* If no link is specified, set to an empty Blob() or call unsetLink().
* @param wireFormat The wire format of the encoding, to be used later if
* necessary to decode.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setLinkWireEncoding(Blob encoding, WireFormat wireFormat)
{
linkWireEncoding_ = encoding;
linkWireEncodingFormat_ = wireFormat;
// Clear the link object, assuming that it has a different encoding.
link_.set(null);
++changeCount_;
return this;
}
/**
* Set the link wire encoding bytes, without decoding them. If there is
* a link object, set it to null. IF you later call getLink(), it will
* decode the wireEncoding to create the link object.
* @param encoding The buffer with the bytes of the link wire encoding.
* If no link is specified, set to an empty Blob().
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setLinkWireEncoding(Blob encoding)
{
return setLinkWireEncoding(encoding, WireFormat.getDefaultWireFormat());
}
/**
* Clear the link wire encoding and link object so that getLink() returns null.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
unsetLink()
{
return setLinkWireEncoding(new Blob(), null);
}
/**
* Set the selected delegation index.
* @param selectedDelegationIndex The selected delegation index. If not
* specified, set to -1.
* @return This Interest so that you can chain calls to update values.
*/
public final Interest
setSelectedDelegationIndex(int selectedDelegationIndex)
{
selectedDelegationIndex_ = selectedDelegationIndex;
++changeCount_;
return this;
}
/**
* An internal library method to set the LpPacket for an incoming packet. The
* application should not call this.
* @param lpPacket The LpPacket. This does not make a copy.
* @return This Interest so that you can chain calls to update values.
* @note This is an experimental feature. This API may change in the future.
*/
final Interest
setLpPacket(LpPacket lpPacket)
{
lpPacket_ = lpPacket;
// Don't update changeCount_ since this doesn't affect the wire encoding.
return this;
}
/**
* Update the bytes of the nonce with new random values. This ensures that the
* new nonce value is different than the current one. If the current nonce is
* not specified, this does nothing.
*/
public final void
refreshNonce()
{
Blob currentNonce = getNonce();
if (currentNonce.size() == 0)
return;
ByteBuffer newNonce = ByteBuffer.allocate(currentNonce.size());
while (true) {
random_.nextBytes(newNonce.array());
if (!newNonce.equals(currentNonce.buf()))
break;
}
nonce_ = new Blob(newNonce, false);
// Set getNonceChangeCount_ so that the next call to getNonce() won't clear
// nonce_.
++changeCount_;
getNonceChangeCount_ = getChangeCount();
}
/**
* Check if this Interest's name matches the given name (using Name.match)
* and the given name also conforms to the interest selectors.
* @param name The name to check.
* @return True if the name and interest selectors match, otherwise false.
*/
public final boolean
matchesName(Name name)
{
if (!getName().match(name))
return false;
if (minSuffixComponents_ >= 0 &&
// Add 1 for the implicit digest.
!(name.size() + 1 - getName().size() >= minSuffixComponents_))
return false;
if (maxSuffixComponents_ >= 0 &&
// Add 1 for the implicit digest.
!(name.size() + 1 - getName().size() <= maxSuffixComponents_))
return false;
if (getExclude().size() > 0 && name.size() > getName().size() &&
getExclude().matches(name.get(getName().size())))
return false;
return true;
}
/**
* Check if the given Data packet can satisfy this Interest. This method
* considers the Name, MinSuffixComponents, MaxSuffixComponents,
* PublisherPublicKeyLocator, and Exclude. It does not consider the
* ChildSelector or MustBeFresh. This uses the given wireFormat to get the
* Data packet encoding for the full Name.
* @param data The Data packet to check.
* @param wireFormat A WireFormat object used to encode the Data packet to
* get its full Name.
* @return True if the given Data packet can satisfy this Interest.
*/
public final boolean
matchesData(Data data, WireFormat wireFormat) throws EncodingException
{
// Imitate ndn-cxx Interest::matchesData.
int interestNameLength = getName().size();
Name dataName = data.getName();
int fullNameLength = dataName.size() + 1;
// Check MinSuffixComponents.
boolean hasMinSuffixComponents = getMinSuffixComponents() >= 0;
int minSuffixComponents =
hasMinSuffixComponents ? getMinSuffixComponents() : 0;
if (!(interestNameLength + minSuffixComponents <= fullNameLength))
return false;
// Check MaxSuffixComponents.
boolean hasMaxSuffixComponents = getMaxSuffixComponents() >= 0;
if (hasMaxSuffixComponents &&
!(interestNameLength + getMaxSuffixComponents() >= fullNameLength))
return false;
// Check the prefix.
if (interestNameLength == fullNameLength) {
if (getName().get(-1).isImplicitSha256Digest()) {
if (!getName().equals(data.getFullName(wireFormat)))
return false;
}
else
// The Interest Name is the same length as the Data full Name, but the
// last component isn't a digest so there's no possibility of matching.
return false;
}
else {
// The Interest Name should be a strict prefix of the Data full Name,
if (!getName().isPrefixOf(dataName))
return false;
}
// Check the Exclude.
// The Exclude won't be violated if the Interest Name is the same as the
// Data full Name.
if (getExclude().size() > 0 && fullNameLength > interestNameLength) {
if (interestNameLength == fullNameLength - 1) {
// The component to exclude is the digest.
if (getExclude().matches
(data.getFullName(wireFormat).get(interestNameLength)))
return false;
}
else {
// The component to exclude is not the digest.
if (getExclude().matches(dataName.get(interestNameLength)))
return false;
}
}
// Check the KeyLocator.
KeyLocator publisherPublicKeyLocator = getKeyLocator();
if (publisherPublicKeyLocator.getType() != KeyLocatorType.NONE) {
Signature signature = data.getSignature();
if (!KeyLocator.canGetFromSignature(signature))
// No KeyLocator in the Data packet.
return false;
if (!publisherPublicKeyLocator.equals
(KeyLocator.getFromSignature(signature)))
return false;
}
return true;
}
/**
* Check if the given Data packet can satisfy this Interest. This method
* considers the Name, MinSuffixComponents, MaxSuffixComponents,
* PublisherPublicKeyLocator, and Exclude. It does not consider the
* ChildSelector or MustBeFresh. This uses the default WireFormat to get the
* Data packet encoding for the full Name.
* @param data The Data packet to check.
* @return True if the given Data packet can satisfy this Interest.
*/
public final boolean
matchesData(Data data) throws EncodingException
{
return matchesData(data, WireFormat.getDefaultWireFormat());
}
/**
* Return a pointer to the defaultWireEncoding, which was encoded with
* getDefaultWireEncodingFormat().
* @return The default wire encoding. Its pointer may be null.
*/
public final SignedBlob
getDefaultWireEncoding()
{
if (getDefaultWireEncodingChangeCount_ != getChangeCount()) {
// The values have changed, so the default wire encoding is invalidated.
defaultWireEncoding_ = new SignedBlob();
defaultWireEncodingFormat_ = null;
getDefaultWireEncodingChangeCount_ = getChangeCount();
}
return defaultWireEncoding_;
}
/**
* Get the WireFormat which is used by getDefaultWireEncoding().
* @return The WireFormat, which is only meaningful if the
* getDefaultWireEncoding() does not have a null pointer.
*/
WireFormat
getDefaultWireEncodingFormat() { return defaultWireEncodingFormat_; }
/**
* Get the change count, which is incremented each time this object
* (or a child object) is changed.
* @return The change count.
*/
public final long
getChangeCount()
{
// Make sure each of the checkChanged is called.
boolean changed = name_.checkChanged();
changed = keyLocator_.checkChanged() || changed;
changed = exclude_.checkChanged() || changed;
changed = link_.checkChanged() || changed;
if (changed)
// A child object has changed, so update the change count.
++changeCount_;
return changeCount_;
}
private void
setDefaultWireEncoding
(SignedBlob defaultWireEncoding, WireFormat defaultWireEncodingFormat)
{
defaultWireEncoding_ = defaultWireEncoding;
defaultWireEncodingFormat_ = defaultWireEncodingFormat;
// Set getDefaultWireEncodingChangeCount_ so that the next call to
// getDefaultWireEncoding() won't clear defaultWireEncoding_.
getDefaultWireEncodingChangeCount_ = getChangeCount();
}
private final ChangeCounter name_ = new ChangeCounter(new Name());
private int minSuffixComponents_ = -1;
private int maxSuffixComponents_ = -1;
private final ChangeCounter keyLocator_ = new ChangeCounter(new KeyLocator());
private final ChangeCounter exclude_ = new ChangeCounter(new Exclude());
private int childSelector_ = -1;
private boolean mustBeFresh_ = true;
private double interestLifetimeMilliseconds_ = -1;
private Blob nonce_ = new Blob();
private long getNonceChangeCount_ = 0;
private LpPacket lpPacket_ = null;
private Blob linkWireEncoding_ = new Blob();
private WireFormat linkWireEncodingFormat_ = null;
private final ChangeCounter link_ = new ChangeCounter(null);
private int selectedDelegationIndex_ = -1;
private SignedBlob defaultWireEncoding_ = new SignedBlob();
private WireFormat defaultWireEncodingFormat_;
private long getDefaultWireEncodingChangeCount_ = 0;
private long changeCount_ = 0;
private static final Random random_ = new Random();
}