diff --git a/src/net/named_data/jndn/Data.java b/src/net/named_data/jndn/Data.java index bcd92a7f..0c2dd545 100644 --- a/src/net/named_data/jndn/Data.java +++ b/src/net/named_data/jndn/Data.java @@ -20,11 +20,14 @@ package net.named_data.jndn; import java.nio.ByteBuffer; +import java.util.ArrayList; + import net.named_data.jndn.encoding.EncodingException; import net.named_data.jndn.encoding.WireFormat; import net.named_data.jndn.encoding.SignatureHolder; import net.named_data.jndn.lp.CongestionMark; import net.named_data.jndn.lp.IncomingFaceId; +import net.named_data.jndn.lp.LpHeaderFiled; import net.named_data.jndn.lp.LpPacket; import net.named_data.jndn.util.Blob; import net.named_data.jndn.util.ChangeCounter; @@ -197,6 +200,42 @@ public Data(Data data) public final Blob getContent() { return content_; } + /** + * Count the number of LpHeaderFields of current LpPacket which bind to this Data + * @return the number of LpHeaderFields of current LpPacket which bind to this Data + */ + public int + countHeaderField() { + if (lpPacket_ == null) + return 0; + return lpPacket_.countHeaderFields(); + } + + /** + * Get all LpHeaderFields of current LpPacket which bind to this Data + * @return null if current Data has not bind any LpPacket + * >=0 presents all LpHeaderFields contains in current LpPacket which bind to this Data + */ + public ArrayList + getHeaderFields() { + if (lpPacket_ == null) + return null; + return lpPacket_.getHeaderFields(); + } + + /** + * Add a LpHeaderField to current LpPacket which bind to this Data. + * This LpHeaderField will be encode to LpPacket when send current Data + * + * @param lpHeaderFiled The LpHeaderField want to add + */ + public void addHeaderFiled(LpHeaderFiled lpHeaderFiled) { + if (lpPacket_ == null) { + lpPacket_ = new LpPacket(); + } + lpPacket_.addHeaderField(lpHeaderFiled); + } + /** * Get the incoming face ID according to the incoming packet header. * @return The incoming face ID. If not specified, return -1. @@ -209,6 +248,18 @@ public Data(Data data) return field == null ? -1 : field.getFaceId(); } + /** + * Set the CongestionMark, this will append to LpPacket's LpHeaderFields + * + * @param congestionMark congestion level + */ + public void + setCongestionMark(long congestionMark) { + CongestionMark congestionMark1 = new CongestionMark(); + congestionMark1.setCongestionMark(congestionMark); + addHeaderFiled(congestionMark1); + } + /** * Get the congestion mark according to the incoming packet header. * @return The congestion mark. If not specified, return 0. diff --git a/src/net/named_data/jndn/Interest.java b/src/net/named_data/jndn/Interest.java index 0680b59a..1b1c9062 100644 --- a/src/net/named_data/jndn/Interest.java +++ b/src/net/named_data/jndn/Interest.java @@ -1,17 +1,18 @@ /** * Copyright (C) 2013-2019 Regents of the University of California. - * @author: Jeff Thompson * + * @author: Jeff Thompson + *

* 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 . * A copy of the GNU Lesser General Public License is in the file COPYING. @@ -20,13 +21,16 @@ package net.named_data.jndn; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Random; import java.util.logging.Level; import java.util.logging.Logger; import net.named_data.jndn.encoding.EncodingException; import net.named_data.jndn.encoding.WireFormat; +import net.named_data.jndn.lp.CongestionMark; import net.named_data.jndn.lp.IncomingFaceId; +import net.named_data.jndn.lp.LpHeaderFiled; import net.named_data.jndn.lp.LpPacket; import net.named_data.jndn.util.Blob; import net.named_data.jndn.util.ChangeCountable; @@ -45,9 +49,7 @@ public class Interest implements ChangeCountable { * @param interestLifetimeMilliseconds The interest lifetime in milliseconds, * or -1 for none. */ - public - Interest(Name name, double interestLifetimeMilliseconds) - { + public Interest(Name name, double interestLifetimeMilliseconds) { if (name != null) name_.set(new Name(name)); interestLifetimeMilliseconds_ = interestLifetimeMilliseconds; @@ -57,9 +59,7 @@ public class Interest implements ChangeCountable { * Create a new Interest with the given name and "none" for other values. * @param name The name for the interest. */ - public - Interest(Name name) - { + public Interest(Name name) { if (name != null) name_.set(new Name(name)); } @@ -69,9 +69,7 @@ public class Interest implements ChangeCountable { * other values. * @param uri The URI string. */ - public - Interest(String uri) - { + public Interest(String uri) { name_.set(new Name(uri)); } @@ -79,9 +77,7 @@ public class Interest implements ChangeCountable { * Create a new interest as a deep copy of the given interest. * @param interest The interest to copy. */ - public - Interest(Interest interest) - { + public Interest(Interest interest) { name_.set(new Name(interest.getName())); minSuffixComponents_ = interest.minSuffixComponents_; maxSuffixComponents_ = interest.maxSuffixComponents_; @@ -99,31 +95,31 @@ public class Interest implements ChangeCountable { linkWireEncoding_ = interest.linkWireEncoding_; linkWireEncodingFormat_ = interest.linkWireEncodingFormat_; if (interest.link_.get() != null) - link_.set(new Link((Link)interest.link_.get())); + link_.set(new Link((Link) interest.link_.get())); selectedDelegationIndex_ = interest.selectedDelegationIndex_; setDefaultWireEncoding - (interest.getDefaultWireEncoding(), interest.defaultWireEncodingFormat_); + (interest.getDefaultWireEncoding(), interest.defaultWireEncodingFormat_); } /** * Create a new Interest with an empty name and "none" for all values. */ - public - Interest() - { + public Interest() { } public static final int CHILD_SELECTOR_LEFT = 0; public static final int CHILD_SELECTOR_RIGHT = 1; /** - * Get the default value of the CanBePrefix flag used in the Interest + * Get the default value of the CanBePrefix flag used in the Interest * constructor. You can change this with setDefaultCanBePrefix(). * @return The default value of the CanBePrefix flag. */ public static boolean - getDefaultCanBePrefix() { return defaultCanBePrefix_; } + getDefaultCanBePrefix() { + return defaultCanBePrefix_; + } /** * Set the default value of the CanBePrefix flag used in the Interest @@ -136,8 +132,7 @@ public class Interest implements ChangeCountable { * @param defaultCanBePrefix The default value of the CanBePrefix flag. */ public static void - setDefaultCanBePrefix(boolean defaultCanBePrefix) - { + setDefaultCanBePrefix(boolean defaultCanBePrefix) { defaultCanBePrefix_ = defaultCanBePrefix; didSetDefaultCanBePrefix_ = true; } @@ -150,8 +145,7 @@ public class Interest implements ChangeCountable { * @return The encoded buffer. */ public final SignedBlob - wireEncode(WireFormat wireFormat) - { + wireEncode(WireFormat wireFormat) { if (!getDefaultWireEncoding().isNull() && getDefaultWireEncodingFormat() == wireFormat) // We already have an encoding in the desired format. @@ -160,9 +154,9 @@ public class Interest implements ChangeCountable { int[] signedPortionBeginOffset = new int[1]; int[] signedPortionEndOffset = new int[1]; Blob encoding = wireFormat.encodeInterest - (this, signedPortionBeginOffset, signedPortionEndOffset); + (this, signedPortionBeginOffset, signedPortionEndOffset); SignedBlob wireEncoding = new SignedBlob - (encoding, signedPortionBeginOffset[0], signedPortionEndOffset[0]); + (encoding, signedPortionBeginOffset[0], signedPortionEndOffset[0]); if (wireFormat == WireFormat.getDefaultWireFormat()) // This is the default wire encoding. @@ -177,8 +171,7 @@ public class Interest implements ChangeCountable { * @return The encoded buffer. */ public final SignedBlob - wireEncode() - { + wireEncode() { return wireEncode(WireFormat.getDefaultWireFormat()); } @@ -190,25 +183,23 @@ public class Interest implements ChangeCountable { * @throws EncodingException For invalid encoding. */ public final void - wireDecode(ByteBuffer input, WireFormat wireFormat) throws EncodingException - { + wireDecode(ByteBuffer input, WireFormat wireFormat) throws EncodingException { wireDecodeHelper(input, wireFormat, true); } private void wireDecodeHelper - (ByteBuffer input, WireFormat wireFormat, boolean copy) throws EncodingException - { + (ByteBuffer input, WireFormat wireFormat, boolean copy) throws EncodingException { int[] signedPortionBeginOffset = new int[1]; int[] signedPortionEndOffset = new int[1]; wireFormat.decodeInterest - (this, input, signedPortionBeginOffset, signedPortionEndOffset, copy); + (this, input, signedPortionBeginOffset, signedPortionEndOffset, copy); if (wireFormat == WireFormat.getDefaultWireFormat()) // This is the default wire encoding. setDefaultWireEncoding - (new SignedBlob(input, copy, signedPortionBeginOffset[0], - signedPortionEndOffset[0]), WireFormat.getDefaultWireFormat()); + (new SignedBlob(input, copy, signedPortionBeginOffset[0], + signedPortionEndOffset[0]), WireFormat.getDefaultWireFormat()); else setDefaultWireEncoding(new SignedBlob(), null); } @@ -221,8 +212,7 @@ public class Interest implements ChangeCountable { * @throws EncodingException For invalid encoding. */ public final void - wireDecode(ByteBuffer input) throws EncodingException - { + wireDecode(ByteBuffer input) throws EncodingException { wireDecode(input, WireFormat.getDefaultWireFormat()); } @@ -235,8 +225,7 @@ public class Interest implements ChangeCountable { * @throws EncodingException For invalid encoding. */ public final void - wireDecode(Blob input, WireFormat wireFormat) throws EncodingException - { + wireDecode(Blob input, WireFormat wireFormat) throws EncodingException { wireDecodeHelper(input.buf(), wireFormat, false); } @@ -247,8 +236,7 @@ public class Interest implements ChangeCountable { * @throws EncodingException For invalid encoding. */ public final void - wireDecode(Blob input) throws EncodingException - { + wireDecode(Blob input) throws EncodingException { wireDecode(input, WireFormat.getDefaultWireFormat()); } @@ -261,8 +249,7 @@ public class Interest implements ChangeCountable { * http://named-data.net/doc/ndn-ccl-api/interest.html#interest-touri-method . */ public final String - toUri() - { + toUri() { StringBuffer selectors = new StringBuffer(); if (minSuffixComponents_ >= 0) @@ -274,7 +261,7 @@ public class Interest implements ChangeCountable { selectors.append("&ndn.MustBeFresh=").append(mustBeFresh_ ? 1 : 0); if (interestLifetimeMilliseconds_ >= 0) selectors.append("&ndn.InterestLifetime=").append - ((long)Math.round(interestLifetimeMilliseconds_)); + ((long) Math.round(interestLifetimeMilliseconds_)); if (nonce_.size() > 0) { selectors.append("&ndn.Nonce="); Name.toEscapedString(nonce_.buf(), selectors); @@ -294,13 +281,19 @@ public class Interest implements ChangeCountable { } public final Name - getName() { return (Name)name_.get(); } + getName() { + return (Name) name_.get(); + } public final int - getMinSuffixComponents() { return minSuffixComponents_; } + getMinSuffixComponents() { + return minSuffixComponents_; + } public final int - getMaxSuffixComponents() { return maxSuffixComponents_; } + getMaxSuffixComponents() { + return maxSuffixComponents_; + } /** * Get the CanBePrefix flag. If not specified, the default is true, or the @@ -308,31 +301,40 @@ public class Interest implements ChangeCountable { * @return The CanBePrefix flag. */ public final boolean - getCanBePrefix() - { + getCanBePrefix() { // Use the closest v0.2 semantics. CanBePrefix is the opposite of exact // match where MaxSuffixComponents is 1 (for the implicit digest). return maxSuffixComponents_ != 1; } public final KeyLocator - getKeyLocator() { return (KeyLocator)keyLocator_.get(); } + getKeyLocator() { + return (KeyLocator) keyLocator_.get(); + } public final Exclude - getExclude() { return (Exclude)exclude_.get(); } + getExclude() { + return (Exclude) exclude_.get(); + } public final int - getChildSelector() { return childSelector_; } + getChildSelector() { + return childSelector_; + } /** * Get the must be fresh flag. If not specified, the default is false. * @return The must be fresh flag. */ public final boolean - getMustBeFresh() { return mustBeFresh_; } + getMustBeFresh() { + return mustBeFresh_; + } public final double - getInterestLifetimeMilliseconds() { return interestLifetimeMilliseconds_; } + getInterestLifetimeMilliseconds() { + return interestLifetimeMilliseconds_; + } /** * Return the nonce value from the incoming interest. If you change any of @@ -340,8 +342,7 @@ public class Interest implements ChangeCountable { * @return The nonce. */ public final Blob - getNonce() - { + getNonce() { if (getNonceChangeCount_ != getChangeCount()) { // The values have changed, so the existing nonce is invalidated. nonce_ = new Blob(); @@ -357,33 +358,43 @@ public class Interest implements ChangeCountable { * @return The forwarding hint as a DelegationSet. */ public final DelegationSet - getForwardingHint() { return (DelegationSet)forwardingHint_.get(); } + getForwardingHint() { + return (DelegationSet) forwardingHint_.get(); + } /** * Check if the application parameters are specified. * @return True if the application parameters are specified, false if not. */ public final boolean - hasApplicationParameters() { return applicationParameters_.size() > 0; } + hasApplicationParameters() { + return applicationParameters_.size() > 0; + } /** * @deprecated Use hasApplicationParameters. */ public final boolean - hasParameters() { return hasApplicationParameters(); } + hasParameters() { + return hasApplicationParameters(); + } /** * Get the application parameters. * @return The parameters as a Blob, which isNull() if unspecified. */ public final Blob - getApplicationParameters() { return applicationParameters_; } + getApplicationParameters() { + return applicationParameters_; + } /** * @deprecated Use getApplicationParameters. */ public final Blob - getParameters() { return getApplicationParameters(); } + getParameters() { + return getApplicationParameters(); + } /** * Check if this interest has a link object (or a link wire encoding which @@ -392,23 +403,21 @@ public class Interest implements ChangeCountable { * @deprecated Use getForwardingHint. */ public final boolean - hasLink() - { + 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. + * @return The link object, or null if not specified. * @throws EncodingException For error decoding the link wire encoding (if * necessary). * @deprecated Use getForwardingHint. */ public final Link - getLink() throws EncodingException - { + getLink() throws EncodingException { if (link_.get() != null) - return (Link)link_.get(); + return (Link) link_.get(); else if (!linkWireEncoding_.isNull()) { // Decode the link object from linkWireEncoding_. Link link = new Link(); @@ -420,8 +429,7 @@ else if (!linkWireEncoding_.isNull()) { linkWireEncodingFormat_ = null; return link; - } - else + } else return null; } @@ -435,8 +443,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use getForwardingHint. */ public final Blob - getLinkWireEncoding(WireFormat wireFormat) throws EncodingException - { + getLinkWireEncoding(WireFormat wireFormat) throws EncodingException { if (!linkWireEncoding_.isNull() && linkWireEncodingFormat_ == wireFormat) return linkWireEncoding_; @@ -456,8 +463,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use getForwardingHint. */ public final Blob - getLinkWireEncoding() throws EncodingException - { + getLinkWireEncoding() throws EncodingException { return getLinkWireEncoding(WireFormat.getDefaultWireFormat()); } @@ -467,17 +473,78 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use getForwardingHint. */ public final int - getSelectedDelegationIndex() { return selectedDelegationIndex_; } + getSelectedDelegationIndex() { + return selectedDelegationIndex_; + } + + /** + * Count the number of LpHeaderFields of current LpPacket which bind to this Interest + * @return the number of LpHeaderFields of current LpPacket which bind to this Interest + */ + public int + countHeaderField() { + if (lpPacket_ == null) + return 0; + return lpPacket_.countHeaderFields(); + } + + /** + * Get all LpHeaderFields of current LpPacket which bind to this Interest + * @return null if current Interest has not bind any LpPacket + * >=0 presents all LpHeaderFields contains in current LpPacket which bind to this Interest + */ + public ArrayList + getHeaderFields() { + if (lpPacket_ == null) + return null; + return lpPacket_.getHeaderFields(); + } + + /** + * Add a LpHeaderField to current LpPacket which bind to this Interest. + * This LpHeaderField will be encode to LpPacket when send current Interest + * + * @param lpHeaderFiled The LpHeaderField want to add + */ + public void addHeaderFiled(LpHeaderFiled lpHeaderFiled) { + if (lpPacket_ == null) { + lpPacket_ = new LpPacket(); + } + lpPacket_.addHeaderField(lpHeaderFiled); + } + + /** + * Set the CongestionMark, this will append to LpPacket's LpHeaderFields + * + * @param congestionMark congestion level + */ + public void + setCongestionMark(long congestionMark) { + CongestionMark congestionMark1 = new CongestionMark(); + congestionMark1.setCongestionMark(congestionMark); + addHeaderFiled(congestionMark1); + } + + /** + * Get the CongestionMark according to the incoming packet header. + * + * @return The CongestionMark, If not specified, return 0 + */ + public final long + getCongestionMark() { + CongestionMark field = + lpPacket_ == null ? null : CongestionMark.getFirstHeader(lpPacket_); + return field == null ? 0 : field.getCongestionMark(); + } /** * 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() - { + getIncomingFaceId() { IncomingFaceId field = - lpPacket_ == null ? null : IncomingFaceId.getFirstHeader(lpPacket_); + lpPacket_ == null ? null : IncomingFaceId.getFirstHeader(lpPacket_); return field == null ? -1 : field.getFaceId(); } @@ -488,8 +555,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setName(Name name) - { + setName(Name name) { name_.set(name == null ? new Name() : new Name(name)); ++changeCount_; return this; @@ -502,8 +568,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setMinSuffixComponents(int minSuffixComponents) - { + setMinSuffixComponents(int minSuffixComponents) { minSuffixComponents_ = minSuffixComponents; ++changeCount_; return this; @@ -516,8 +581,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setMaxSuffixComponents(int maxSuffixComponents) - { + setMaxSuffixComponents(int maxSuffixComponents) { maxSuffixComponents_ = maxSuffixComponents; ++changeCount_; return this; @@ -529,8 +593,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setCanBePrefix(boolean canBePrefix) - { + setCanBePrefix(boolean canBePrefix) { // Use the closest v0.2 semantics. CanBePrefix is the opposite of exact // match where MaxSuffixComponents is 1 (for the implicit digest). maxSuffixComponents_ = (canBePrefix ? -1 : 1); @@ -545,8 +608,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setChildSelector(int childSelector) - { + setChildSelector(int childSelector) { childSelector_ = childSelector; ++changeCount_; return this; @@ -559,8 +621,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setMustBeFresh(boolean mustBeFresh) - { + setMustBeFresh(boolean mustBeFresh) { mustBeFresh_ = mustBeFresh; ++changeCount_; return this; @@ -573,8 +634,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setInterestLifetimeMilliseconds(double interestLifetimeMilliseconds) - { + setInterestLifetimeMilliseconds(double interestLifetimeMilliseconds) { interestLifetimeMilliseconds_ = interestLifetimeMilliseconds; ++changeCount_; return this; @@ -585,8 +645,7 @@ else if (!linkWireEncoding_.isNull()) { * internally before sending the interest. */ public final Interest - setNonce(Blob nonce) - { + setNonce(Blob nonce) { nonce_ = (nonce == null ? new Blob() : nonce); // Set getNonceChangeCount_ so that the next call to getNonce() won't // clear nonce_. @@ -604,8 +663,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setKeyLocator(KeyLocator keyLocator) - { + setKeyLocator(KeyLocator keyLocator) { keyLocator_.set(keyLocator == null ? new KeyLocator() : new KeyLocator(keyLocator)); ++changeCount_; return this; @@ -620,8 +678,7 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setExclude(Exclude exclude) - { + setExclude(Exclude exclude) { exclude_.set(exclude == null ? new Exclude() : new Exclude(exclude)); ++changeCount_; return this; @@ -638,10 +695,9 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setForwardingHint(DelegationSet forwardingHint) - { + setForwardingHint(DelegationSet forwardingHint) { forwardingHint_.set(forwardingHint == null ? - new DelegationSet() : new DelegationSet(forwardingHint)); + new DelegationSet() : new DelegationSet(forwardingHint)); ++changeCount_; return this; } @@ -652,10 +708,9 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - setApplicationParameters(Blob applicationParameters) - { - applicationParameters_ = - (applicationParameters == null ? new Blob() : applicationParameters); + setApplicationParameters(Blob applicationParameters) { + applicationParameters_ = + (applicationParameters == null ? new Blob() : applicationParameters); ++changeCount_; return this; } @@ -664,8 +719,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use setApplicationParameters. */ public final Interest - setParameters(Blob applicationParameters) - { + setParameters(Blob applicationParameters) { return setApplicationParameters(applicationParameters); } @@ -677,14 +731,13 @@ else if (!linkWireEncoding_.isNull()) { * @return This Interest so that you can chain calls to update values. */ public final Interest - appendParametersDigestToName() - { + appendParametersDigestToName() { if (!hasApplicationParameters()) return this; try { getName().appendParametersSha256Digest - (new Blob(Common.digestSha256(applicationParameters_.buf()), false)); + (new Blob(Common.digestSha256(applicationParameters_.buf()), false)); } catch (EncodingException ex) { // We don't expect this. Logger.getLogger(Interest.class.getName()).log(Level.SEVERE, null, ex); @@ -705,8 +758,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use setForwardingHint. */ public final Interest - setLinkWireEncoding(Blob encoding, WireFormat wireFormat) - { + setLinkWireEncoding(Blob encoding, WireFormat wireFormat) { linkWireEncoding_ = encoding; linkWireEncodingFormat_ = wireFormat; @@ -727,8 +779,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use setForwardingHint. */ public final Interest - setLinkWireEncoding(Blob encoding) - { + setLinkWireEncoding(Blob encoding) { return setLinkWireEncoding(encoding, WireFormat.getDefaultWireFormat()); } @@ -738,8 +789,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use setForwardingHint. */ public final Interest - unsetLink() - { + unsetLink() { return setLinkWireEncoding(new Blob(), null); } @@ -751,8 +801,7 @@ else if (!linkWireEncoding_.isNull()) { * @deprecated Use setForwardingHint. */ public final Interest - setSelectedDelegationIndex(int selectedDelegationIndex) - { + setSelectedDelegationIndex(int selectedDelegationIndex) { selectedDelegationIndex_ = selectedDelegationIndex; ++changeCount_; return this; @@ -766,8 +815,7 @@ else if (!linkWireEncoding_.isNull()) { * @note This is an experimental feature. This API may change in the future. */ final Interest - setLpPacket(LpPacket lpPacket) - { + setLpPacket(LpPacket lpPacket) { lpPacket_ = lpPacket; // Don't update changeCount_ since this doesn't affect the wire encoding. return this; @@ -779,8 +827,7 @@ else if (!linkWireEncoding_.isNull()) { * not specified, this does nothing. */ public final void - refreshNonce() - { + refreshNonce() { Blob currentNonce = getNonce(); if (currentNonce.size() == 0) return; @@ -806,8 +853,7 @@ else if (!linkWireEncoding_.isNull()) { * @return True if the name and interest selectors match, otherwise false. */ public final boolean - matchesName(Name name) - { + matchesName(Name name) { if (!getName().match(name)) return false; @@ -838,8 +884,7 @@ else if (!linkWireEncoding_.isNull()) { * @return True if the given Data packet can satisfy this Interest. */ public final boolean - matchesData(Data data, WireFormat wireFormat) - { + matchesData(Data data, WireFormat wireFormat) { // Imitate ndn-cxx Interest::matchesData. int interestNameLength = getName().size(); Name dataName = data.getName(); @@ -848,7 +893,7 @@ else if (!linkWireEncoding_.isNull()) { // Check MinSuffixComponents. boolean hasMinSuffixComponents = getMinSuffixComponents() >= 0; int minSuffixComponents = - hasMinSuffixComponents ? getMinSuffixComponents() : 0; + hasMinSuffixComponents ? getMinSuffixComponents() : 0; if (!(interestNameLength + minSuffixComponents <= fullNameLength)) return false; @@ -863,13 +908,11 @@ else if (!linkWireEncoding_.isNull()) { if (getName().get(-1).isImplicitSha256Digest()) { if (!getName().equals(data.getFullName(wireFormat))) return false; - } - else + } 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 { + } else { // The Interest Name should be a strict prefix of the Data full Name, if (!getName().isPrefixOf(dataName)) return false; @@ -884,8 +927,7 @@ else if (!linkWireEncoding_.isNull()) { if (getExclude().matches (data.getFullName(wireFormat).get(interestNameLength))) return false; - } - else { + } else { // The component to exclude is not the digest. if (getExclude().matches(dataName.get(interestNameLength))) return false; @@ -917,8 +959,7 @@ else if (!linkWireEncoding_.isNull()) { * @return True if the given Data packet can satisfy this Interest. */ public final boolean - matchesData(Data data) - { + matchesData(Data data) { return matchesData(data, WireFormat.getDefaultWireFormat()); } @@ -928,8 +969,7 @@ else if (!linkWireEncoding_.isNull()) { * @return The default wire encoding. Its pointer may be null. */ public final SignedBlob - getDefaultWireEncoding() - { + getDefaultWireEncoding() { if (getDefaultWireEncodingChangeCount_ != getChangeCount()) { // The values have changed, so the default wire encoding is invalidated. defaultWireEncoding_ = new SignedBlob(); @@ -946,7 +986,9 @@ else if (!linkWireEncoding_.isNull()) { * getDefaultWireEncoding() does not have a null pointer. */ WireFormat - getDefaultWireEncodingFormat() { return defaultWireEncodingFormat_; } + getDefaultWireEncodingFormat() { + return defaultWireEncodingFormat_; + } /** * Get the change count, which is incremented each time this object @@ -954,8 +996,7 @@ else if (!linkWireEncoding_.isNull()) { * @return The change count. */ public final long - getChangeCount() - { + getChangeCount() { // Make sure each of the checkChanged is called. boolean changed = name_.checkChanged(); changed = keyLocator_.checkChanged() || changed; @@ -975,12 +1016,13 @@ else if (!linkWireEncoding_.isNull()) { * called setDefaultCanBePrefix() before creating the Interest. */ public boolean - getDidSetCanBePrefix_() { return didSetCanBePrefix_; } + getDidSetCanBePrefix_() { + return didSetCanBePrefix_; + } private void setDefaultWireEncoding - (SignedBlob defaultWireEncoding, WireFormat defaultWireEncodingFormat) - { + (SignedBlob defaultWireEncoding, WireFormat defaultWireEncodingFormat) { defaultWireEncoding_ = defaultWireEncoding; defaultWireEncodingFormat_ = defaultWireEncodingFormat; // Set getDefaultWireEncodingChangeCount_ so that the next call to @@ -1004,7 +1046,7 @@ else if (!linkWireEncoding_.isNull()) { private Blob linkWireEncoding_ = new Blob(); private WireFormat linkWireEncodingFormat_ = null; private final ChangeCounter forwardingHint_ = - new ChangeCounter(new DelegationSet()); + new ChangeCounter(new DelegationSet()); private Blob applicationParameters_ = new Blob(); private final ChangeCounter link_ = new ChangeCounter(null); private int selectedDelegationIndex_ = -1; diff --git a/src/net/named_data/jndn/NetworkNack.java b/src/net/named_data/jndn/NetworkNack.java index 22741169..56dd2af4 100644 --- a/src/net/named_data/jndn/NetworkNack.java +++ b/src/net/named_data/jndn/NetworkNack.java @@ -20,12 +20,64 @@ package net.named_data.jndn; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.encoding.tlv.Tlv; +import net.named_data.jndn.encoding.tlv.TlvDecoder; +import net.named_data.jndn.encoding.tlv.TlvEncoder; +import net.named_data.jndn.lp.LpHeaderFiled; import net.named_data.jndn.lp.LpPacket; /** * NetworkNack represents a network Nack packet and includes a Nack reason. */ -public class NetworkNack { +public class NetworkNack extends LpHeaderFiled { + @Override + public int getFieldType() { + return Tlv.LpPacket_Nack; + } + + @Override + public void wireEncode(TlvEncoder encoder) { + int reason; + if (getReason() == Reason.NONE || + getReason() == Reason.CONGESTION || + getReason() == Reason.DUPLICATE || + getReason() == Reason.NO_ROUTE) + // The Reason enum is set up with the correct integer for each NDN-TLV Reason. + reason = getReason().getNumericType(); + else if (getReason() == Reason.OTHER_CODE) + reason = getOtherReasonCode(); + else + // We don't expect this to happen. + throw new Error("unrecognized getReason() value"); + + int nackSaveLength = encoder.getLength(); + encoder.writeNonNegativeIntegerTlv(Tlv.LpPacket_NackReason, reason); + encoder.writeTypeAndLength + (getFieldType(), encoder.getLength() - nackSaveLength); + } + + @Override + public void wireDecode(TlvDecoder decoder, int fieldType, int fieldLength, int fieldEndOffset) throws EncodingException { + int code = (int) decoder.readOptionalNonNegativeIntegerTlv + (Tlv.LpPacket_NackReason, fieldEndOffset); + // The enum numeric values are the same as this wire format, so use as is. + if (code < 0 || code == NetworkNack.Reason.NONE.getNumericType()) + // This includes an omitted NackReason. + setReason(NetworkNack.Reason.NONE); + else if (code == NetworkNack.Reason.CONGESTION.getNumericType()) + setReason(NetworkNack.Reason.CONGESTION); + else if (code == NetworkNack.Reason.DUPLICATE.getNumericType()) + setReason(NetworkNack.Reason.DUPLICATE); + else if (code == NetworkNack.Reason.NO_ROUTE.getNumericType()) + setReason(NetworkNack.Reason.NO_ROUTE); + else { + // Unrecognized reason. + setReason(NetworkNack.Reason.OTHER_CODE); + setOtherReasonCode(code); + } + } + /** * A NetworkNack.Reason specifies the reason in a NetworkNack packet. If the * reason code in the packet is not a recognized enum value, then we use diff --git a/src/net/named_data/jndn/Node.java b/src/net/named_data/jndn/Node.java index 47f85523..aec22797 100644 --- a/src/net/named_data/jndn/Node.java +++ b/src/net/named_data/jndn/Node.java @@ -352,7 +352,8 @@ else if (connectStatus_ == ConnectStatus.CONNECT_COMPLETE) return; } - Blob encoding = data.wireEncode(wireFormat); + // Wrap Interest packet in a LpPacket, contain all fields + Blob encoding = WireFormat.encodeLpPacket(data, wireFormat); if (encoding.size() > getMaxNdnPacketSize()) throw new Error ("The encoded Data packet size exceeds the maximum limit getMaxNdnPacketSize()"); @@ -386,8 +387,9 @@ else if (connectStatus_ == ConnectStatus.CONNECT_COMPLETE) public final void putNack(Interest interest, NetworkNack networkNack) throws IOException { - // TODO: Generalize this and move to WireFormat.encodeLpPacket. - Blob encoding = encodeLpNack(interest, networkNack); + // Wrap Interest packet in a LpPacket, contain all fields + interest.addHeaderFiled(networkNack); + Blob encoding = WireFormat.encodeLpPacket(interest, TlvWireFormat.get()); if (encoding.size() > getMaxNdnPacketSize()) throw new Error ("The encoded Nack packet size exceeds the maximum limit getMaxNdnPacketSize()"); @@ -612,7 +614,8 @@ public final boolean isLocal() throws IOException{ // Special case: For timeoutPrefix_ we don't actually send the interest. if (!timeoutPrefix_.match(interestCopy.getName())) { - Blob encoding = interestCopy.wireEncode(wireFormat); + // Wrap Interest packet in a LpPacket, contain all fields + Blob encoding = WireFormat.encodeLpPacket(interestCopy, wireFormat); if (encoding.size() > getMaxNdnPacketSize()) throw new Error ("The encoded interest size exceeds the maximum limit getMaxNdnPacketSize()"); @@ -910,50 +913,6 @@ public static class Info { } } - /** - * Encode the interest into an NDN-TLV LpPacket as a NACK with the reason code - * in the networkNack object. - * TODO: Generalize this and move to WireFormat.encodeLpPacket. - * @param interest The Interest to put in the LpPacket fragment. - * @param networkNack The NetworkNack with the reason code. - * @return A Blob containing the encoding. - */ - private static Blob - encodeLpNack(Interest interest, NetworkNack networkNack) - { - TlvEncoder encoder = new TlvEncoder(256); - int saveLength = encoder.getLength(); - - // Encode backwards. - // Encode the fragment with the Interest. - encoder.writeBlobTlv - (Tlv.LpPacket_Fragment, interest.wireEncode(TlvWireFormat.get()).buf()); - - // Encode the reason. - int reason; - if (networkNack.getReason() == NetworkNack.Reason.NONE || - networkNack.getReason() == NetworkNack.Reason.CONGESTION || - networkNack.getReason() == NetworkNack.Reason.DUPLICATE || - networkNack.getReason() == NetworkNack.Reason.NO_ROUTE) - // The Reason enum is set up with the correct integer for each NDN-TLV Reason. - reason = networkNack.getReason().getNumericType(); - else if (networkNack.getReason() == NetworkNack.Reason.OTHER_CODE) - reason = networkNack.getOtherReasonCode(); - else - // We don't expect this to happen. - throw new Error("unrecognized NetworkNack.getReason() value"); - - int nackSaveLength = encoder.getLength(); - encoder.writeNonNegativeIntegerTlv(Tlv.LpPacket_NackReason, reason); - encoder.writeTypeAndLength - (Tlv.LpPacket_Nack, encoder.getLength() - nackSaveLength); - - encoder.writeTypeAndLength - (Tlv.LpPacket_LpPacket, encoder.getLength() - saveLength); - - return new Blob(encoder.getOutput(), false); - } - private final Transport transport_; private final Transport.ConnectionInfo connectionInfo_; private final PendingInterestTable pendingInterestTable_ = diff --git a/src/net/named_data/jndn/encoding/WireFormat.java b/src/net/named_data/jndn/encoding/WireFormat.java index 66671777..4e4218cd 100644 --- a/src/net/named_data/jndn/encoding/WireFormat.java +++ b/src/net/named_data/jndn/encoding/WireFormat.java @@ -27,7 +27,10 @@ import net.named_data.jndn.Interest; import net.named_data.jndn.Name; import net.named_data.jndn.Signature; +import net.named_data.jndn.encoding.tlv.Tlv; +import net.named_data.jndn.encoding.tlv.TlvEncoder; import net.named_data.jndn.encrypt.EncryptedContent; +import net.named_data.jndn.lp.LpHeaderFiled; import net.named_data.jndn.lp.LpPacket; import net.named_data.jndn.util.Blob; @@ -549,6 +552,64 @@ public class WireFormat { ("encodeSignatureValue is not implemented"); } + /** + * Wrapper a Interest to a LpPacket, and encode the LpHeaderFields contains in Interest's lpPacket_ object. + * Then encode the LpPacket and return the result. + * + * @param interest The Interest need to be wrapper + * @param wireFormat The WireFormat use to encode Interest + * @return The encode result of LpPacket (which contain the input Interest) + */ + public static Blob encodeLpPacket(Interest interest, WireFormat wireFormat) { + TlvEncoder encoder = new TlvEncoder(256); + + int saveLength = encoder.getLength(); + // Encode backwards. + // Encode the fragment with the Interest. + encoder.writeBlobTlv + (Tlv.LpPacket_Fragment, interest.wireEncode(wireFormat).buf()); + + // encode LpHeaderFields + if (interest.countHeaderField() > 0) { + for (LpHeaderFiled lpHeaderFiled : interest.getHeaderFields()) { + lpHeaderFiled.wireEncode(encoder); + } + } + + encoder.writeTypeAndLength + (Tlv.LpPacket_LpPacket, encoder.getLength() - saveLength); + return new Blob(encoder.getOutput(), false); + } + + /** + * Wrapper a Data to a LpPacket, and encode the LpHeaderFields contains in Data's lpPacket_ object. + * Then encode the LpPacket and return the result. + * + * @param data The Data need to be wrapper + * @param wireFormat The WireFormat use to encode Data + * @return The encode result of LpPacket (which contain the input Data) + */ + public static Blob encodeLpPacket(Data data, WireFormat wireFormat) { + TlvEncoder encoder = new TlvEncoder(256); + + int saveLength = encoder.getLength(); + // Encode backwards. + // Encode the fragment with the Data. + encoder.writeBlobTlv + (Tlv.LpPacket_Fragment, data.wireEncode(wireFormat).buf()); + + // encode LpHeaderFields + if (data.countHeaderField() > 0) { + for (LpHeaderFiled lpHeaderFiled : data.getHeaderFields()) { + lpHeaderFiled.wireEncode(encoder); + } + } + + encoder.writeTypeAndLength + (Tlv.LpPacket_LpPacket, encoder.getLength() - saveLength); + return new Blob(encoder.getOutput(), false); + } + /** * Decode input as an LpPacket and set the fields of the lpPacket object. Your * derived class should override. diff --git a/src/net/named_data/jndn/lp/CongestionMark.java b/src/net/named_data/jndn/lp/CongestionMark.java index 6509651c..c06fd2d9 100644 --- a/src/net/named_data/jndn/lp/CongestionMark.java +++ b/src/net/named_data/jndn/lp/CongestionMark.java @@ -19,12 +19,17 @@ package net.named_data.jndn.lp; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.encoding.tlv.Tlv; +import net.named_data.jndn.encoding.tlv.TlvDecoder; +import net.named_data.jndn.encoding.tlv.TlvEncoder; + /** * CongestionMark represents the congestion mark header field in an NDNLPv2 * packet. * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 */ -public class CongestionMark { +public class CongestionMark extends LpHeaderFiled{ /** * Get the congestion mark value. * @return The congestion mark value. @@ -61,4 +66,22 @@ public class CongestionMark { } private long congestionMark_ = 0; + + @Override + public int + getFieldType() { + return Tlv.LpPacket_CongestionMark; + } + + @Override + public void + wireEncode(TlvEncoder encoder) { + encoder.writeNonNegativeIntegerTlv(getFieldType(), congestionMark_); + } + + @Override + public void + wireDecode(TlvDecoder decoder, int fieldType, int fieldLength, int fieldEndOffset) throws EncodingException { + this.setCongestionMark(decoder.readNonNegativeInteger(fieldLength)); + } } diff --git a/src/net/named_data/jndn/lp/IncomingFaceId.java b/src/net/named_data/jndn/lp/IncomingFaceId.java index a984021f..17ec12a5 100644 --- a/src/net/named_data/jndn/lp/IncomingFaceId.java +++ b/src/net/named_data/jndn/lp/IncomingFaceId.java @@ -20,11 +20,16 @@ package net.named_data.jndn.lp; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.encoding.tlv.Tlv; +import net.named_data.jndn.encoding.tlv.TlvDecoder; +import net.named_data.jndn.encoding.tlv.TlvEncoder; + /** * IncomingFaceId represents the incoming face ID header field in an NDNLPv2 packet. * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 */ -public class IncomingFaceId { +public class IncomingFaceId extends LpHeaderFiled{ /** * Get the incoming face ID value. * @return The face ID value. @@ -61,4 +66,19 @@ public class IncomingFaceId { } private long faceId_ = -1; + + @Override + public int getFieldType() { + return Tlv.LpPacket_IncomingFaceId; + } + + @Override + public void wireEncode(TlvEncoder encoder) { + encoder.writeNonNegativeIntegerTlv(getFieldType(), faceId_); + } + + @Override + public void wireDecode(TlvDecoder decoder, int fieldType, int fieldLength, int fieldEndOffset) throws EncodingException { + this.setFaceId(decoder.readNonNegativeInteger(fieldLength)); + } } diff --git a/src/net/named_data/jndn/lp/LpHeaderFiled.java b/src/net/named_data/jndn/lp/LpHeaderFiled.java new file mode 100644 index 00000000..1c50293e --- /dev/null +++ b/src/net/named_data/jndn/lp/LpHeaderFiled.java @@ -0,0 +1,41 @@ +package net.named_data.jndn.lp; + +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.encoding.tlv.TlvDecoder; +import net.named_data.jndn.encoding.tlv.TlvEncoder; + +/** + * LpHeaderField represents the base class of LpHeaderFields define in NDNLPv2 packet. + * http://redmine.named-data.net/projects/nfd/wiki/NDNLPv2 + */ +public abstract class LpHeaderFiled { + + /** + * Get LpHeaderField's TLV-TYPE value + * + * @return TLV-TYPE value + */ + public abstract int + getFieldType(); + + /** + * Use encoder to encode current LpHeaderField to LpPacket + * + * @param encoder a encoder, already encode previous LpPacket_Fragment and some LpHeaderFields (If it exists) + * which's TLV_TYPE code bigger then this LpHeaderFields. + */ + public abstract void + wireEncode(TlvEncoder encoder); + + /** + * Use decoder to decode a LpHeaderField + * + * @param decoder a decoder + * @param fieldType current decode LpHeaderField's TLV_TYPE + * @param fieldLength current decode LpHeaderField's fieldLength + * @param fieldEndOffset current decode LpHeaderField's fieldEndOffset + * @throws EncodingException + */ + public abstract void + wireDecode(TlvDecoder decoder, int fieldType, int fieldLength, int fieldEndOffset) throws EncodingException; +} \ No newline at end of file diff --git a/src/net/named_data/jndn/lp/LpPacket.java b/src/net/named_data/jndn/lp/LpPacket.java index a6e2317c..4c111377 100644 --- a/src/net/named_data/jndn/lp/LpPacket.java +++ b/src/net/named_data/jndn/lp/LpPacket.java @@ -1,18 +1,19 @@ /** * Copyright (C) 2016-2019 Regents of the University of California. + * * @author: Jeff Thompson * @author: From ndn-cxx packet.hpp https://github.com/named-data/ndn-cxx/blob/master/ndn-cxx/lp/packet.hpp - * + *

* 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 . * A copy of the GNU Lesser General Public License is in the file COPYING. @@ -21,6 +22,8 @@ package net.named_data.jndn.lp; import java.util.ArrayList; +import java.util.Comparator; + import net.named_data.jndn.util.Blob; /** @@ -32,56 +35,80 @@ public class LpPacket { /** * Get the fragment wire encoding. + * * @return The wire encoding, or an isNull Blob if not specified. */ public Blob - getFragmentWireEncoding() { return fragmentWireEncoding_; } + getFragmentWireEncoding() { + return fragmentWireEncoding_; + } /** * Get the number of header fields. This does not include the fragment. + * * @return The number of header fields. */ public int - countHeaderFields() { return headerFields_.size(); } + countHeaderFields() { + return headerFields_.size(); + } /** * Get the header field at the given index. + * * @param index The index, starting from 0. It is an error if index is greater - * to or equal to countHeaderFields(). + * to or equal to countHeaderFields(). * @return The header field at the index. */ public Object - getHeaderField(int index) { return headerFields_.get(index); } + getHeaderField(int index) { + return headerFields_.get(index); + } /** * Remove all header fields and set the fragment to an isNull Blob. */ public void - clear() - { - headerFields_ = new ArrayList(); - fragmentWireEncoding_ = new Blob(); + clear() { + headerFields_ = new ArrayList(); + fragmentWireEncoding_ = new Blob(); } /** * Set the fragment wire encoding. + * * @param fragmentWireEncoding The fragment wire encoding or an isNull Blob - * if not specified. + * if not specified. */ public void - setFragmentWireEncoding(Blob fragmentWireEncoding) - { + setFragmentWireEncoding(Blob fragmentWireEncoding) { fragmentWireEncoding_ = - (fragmentWireEncoding == null ? new Blob() : fragmentWireEncoding); + (fragmentWireEncoding == null ? new Blob() : fragmentWireEncoding); + } + + public ArrayList + getHeaderFields() { + return headerFields_; } /** * Add a header field. To add the fragment, use setFragmentWireEncoding(). + * * @param headerField The header field to add. */ public void - addHeaderField(Object headerField) { headerFields_.add(headerField); } + addHeaderField(LpHeaderFiled headerField) { + headerFields_.add(headerField); + + // NDNLPV2 indicates that fields MUST appear in the order of increasing TLV-TYPE codes + headerFields_.sort(new Comparator() { + @Override + public int compare(LpHeaderFiled o1, LpHeaderFiled o2) { + return o2.getFieldType() - o1.getFieldType(); + } + }); + } - private ArrayList headerFields_ = new ArrayList(); + private ArrayList headerFields_ = new ArrayList(); private Blob fragmentWireEncoding_ = new Blob(); } diff --git a/tests/src/net/named_data/jndn/tests/integration_tests/TestLpHeaderField.java b/tests/src/net/named_data/jndn/tests/integration_tests/TestLpHeaderField.java new file mode 100644 index 00000000..6a033c74 --- /dev/null +++ b/tests/src/net/named_data/jndn/tests/integration_tests/TestLpHeaderField.java @@ -0,0 +1,165 @@ +package src.net.named_data.jndn.tests.integration_tests; + +import net.named_data.jndn.*; +import net.named_data.jndn.encoding.EncodingException; +import net.named_data.jndn.encoding.Tlv0_3WireFormat; +import net.named_data.jndn.encoding.WireFormat; +import net.named_data.jndn.security.KeyChain; +import net.named_data.jndn.security.SecurityException; +import net.named_data.jndn.util.Blob; +import net.named_data.jndn.util.Common; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.junit.Assert.assertEquals; + +public class TestLpHeaderField { + Face faceIn; + Face faceOut; + KeyChain keyChain; + Name certificateName; + + @Before + public void setUp() throws SecurityException { + Name[] localCertificateName = new Name[1]; + keyChain = IntegrationTestsCommon.buildKeyChain(localCertificateName); + certificateName = localCertificateName[0]; + + faceIn = IntegrationTestsCommon.buildFaceWithKeyChain + ("localhost", keyChain, certificateName); + faceOut = IntegrationTestsCommon.buildFaceWithKeyChain + ("localhost", keyChain, certificateName); + } + + @Test + public void testFields() throws IOException, SecurityException { + WireFormat.setDefaultWireFormat(new Tlv0_3WireFormat()); + Name registerPrefix = new Name("/test"); + final long[] congestionMarkFieldValue = {0}; + final long[] incomingFaceIdFieldValue = {-1}; + final int[] interestCallbackCount = new int[]{0}; + final int[] failedCallbackCount = new int[]{0}; + faceIn.registerPrefix(registerPrefix, new OnInterestCallback() { + @Override + public void onInterest(Name prefix, Interest interest, Face face, long interestFilterId, InterestFilter filter) { + interestCallbackCount[0]++; + congestionMarkFieldValue[0] = interest.getCongestionMark(); + incomingFaceIdFieldValue[0] = interest.getIncomingFaceId(); + Data data = new Data(interest.getName()); + data.setCongestionMark(1); + data.setContent(new Blob("SUCCESS")); + + try { + keyChain.sign(data, certificateName); + } catch (SecurityException ex) { + logger.log(Level.SEVERE, null, ex); + } + try { + face.putData(data); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + }, new OnRegisterFailed() { + @Override + public void onRegisterFailed(Name prefix) { + failedCallbackCount[0]++; + } + }); + + // Give the "server" time to register the interest. + double timeout = 1000; + double startTime = getNowMilliseconds(); + while (getNowMilliseconds() - startTime < timeout) { + try { + faceIn.processEvents(); + } catch (IOException | EncodingException ex) { + logger.log(Level.SEVERE, null, ex); + break; + } + + try { + // We need to sleep for a few milliseconds so we don't use 100% of the CPU. + Thread.sleep(10); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + break; + } + } + + final int[] dataCallbackCount = new int[]{0}; + final int[] timeoutCallbackCount = new int[]{0}; + final Data[] receivedData = new Data[1]; + + Name interestName = registerPrefix.append("hello" + getNowMilliseconds()); + Interest interest = new Interest(interestName); + interest.setCongestionMark(1); + faceOut.expressInterest(interest, new OnData() { + @Override + public void onData(Interest interest, Data data) { + dataCallbackCount[0]++; + receivedData[0] = data; + } + }, new OnTimeout() { + @Override + public void onTimeout(Interest interest) { + timeoutCallbackCount[0]++; + } + }); + + // Process events for the in and out faces. + timeout = 10000; + startTime = getNowMilliseconds(); + while (getNowMilliseconds() - startTime < timeout) { + try { + faceIn.processEvents(); + faceOut.processEvents(); + } catch (IOException | EncodingException ex) { + logger.log(Level.SEVERE, null, ex); + break; + } + + boolean done = true; + if (interestCallbackCount[0] == 0 && failedCallbackCount[0] == 0) + // Still processing faceIn. + done = false; + if (dataCallbackCount[0] == 0 && timeoutCallbackCount[0] == 0) + // Still processing face_out. + done = false; + + if (done) + break; + + try { + // We need to sleep for a few milliseconds so we don't use 100% of the CPU. + Thread.sleep(10); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, null, ex); + break; + } + } + + assertEquals("Failed to register prefix at all", + 0, failedCallbackCount[0]); + assertEquals("Expected 1 onInterest callback", + 1, interestCallbackCount[0]); + assertEquals("Expected 1 onData callback", + 1, dataCallbackCount[0]); + + assertEquals("Expected Interest's CongestionMark value is 1", 1L, congestionMarkFieldValue[0]); + + assertEquals("Expected Data's CongestionMark value is 1", 1L, receivedData[0].getCongestionMark()); + } + + public static double + getNowMilliseconds() { + return Common.getNowMilliseconds(); + } + + private static final Logger logger = Logger.getLogger + (TestFaceCallRegisterMethods.class.getName()); +} \ No newline at end of file