/// <summary> /// Set this interest to use a copy of the given Exclude object. /// </summary> /// /// @note You can also call getExclude and change the exclude entries directly. /// <param name="exclude">size() 0.</param> /// <returns>This Interest so that you can chain calls to update values.</returns> public Interest setExclude(Exclude exclude) { exclude_.set((exclude == null) ? new Exclude() : new Exclude(exclude)); ++changeCount_; return this; }
private static void encodeExclude(Exclude exclude, TlvEncoder encoder) { int saveLength = encoder.getLength(); // TODO: Do we want to order the components (except for ANY)? // Encode the entries backwards. for (int i = exclude.size() - 1; i >= 0; --i) { Exclude.Entry entry = exclude.get(i); if (entry.getType() == net.named_data.jndn.Exclude.Type.ANY) encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Any, 0); else encodeNameComponent(entry.getComponent(), encoder); } encoder.writeTypeAndLength(net.named_data.jndn.encoding.tlv.Tlv.Exclude, encoder.getLength() - saveLength); }
/// <summary> /// Create a new Exclude as a copy of the given exclude. /// </summary> /// /// <param name="exclude">The Exclude to copy.</param> public Exclude(Exclude exclude) { this.changeCount_ = 0; // Each entry is read-only, so do a shallow copy. entries_ = new ArrayList<Entry>(exclude.entries_); }
/// <summary> /// Set this interest to use a copy of the given Exclude object. /// </summary> /// /// @note You can also call getExclude and change the exclude entries directly. /// <param name="exclude">size() 0.</param> /// <returns>This Interest so that you can chain calls to update values.</returns> public Interest setExclude(Exclude exclude) { exclude_.set((exclude == null) ? new Exclude() : new Exclude(exclude)); ++changeCount_; return(this); }
private static void decodeExclude(Exclude exclude, TlvDecoder decoder, bool copy) { int endOffset = decoder.readNestedTlvsStart(net.named_data.jndn.encoding.tlv.Tlv.Exclude); exclude.clear(); while (decoder.getOffset() < endOffset) { if (decoder.peekType(net.named_data.jndn.encoding.tlv.Tlv.Any, endOffset)) { // Read past the Any TLV. decoder.readBooleanTlv(net.named_data.jndn.encoding.tlv.Tlv.Any, endOffset); exclude.appendAny(); } else exclude.appendComponent(decodeNameComponent(decoder, copy)); } decoder.finishNestedTlvs(endOffset); }
/// <summary> /// Set the Exclude object from the list of ExcludeEntry. /// </summary> /// /// <param name="exclude">The Exclude object to update.</param> /// <param name="entries">The list of ExcludeEntry.</param> private static void setExcludeEntries(Exclude exclude, ArrayList entries) { exclude.clear(); for (int i = 0; i < entries.Count; ++i) { Producer.ExcludeEntry entry = (Producer.ExcludeEntry ) entries[i]; if (i == 0 && entry.component_.getValue().size() == 0 && entry.anyFollowsComponent_) // This is a "beginning ANY". exclude.appendAny(); else { exclude.appendComponent(entry.component_); if (entry.anyFollowsComponent_) exclude.appendAny(); } } }
/// <summary> /// Create a new Exclude as a copy of the given exclude. /// </summary> /// /// <param name="exclude">The Exclude to copy.</param> public Exclude(Exclude exclude) { this.changeCount_ = 0; // Each entry is read-only, so do a shallow copy. entries_ = new ArrayList <Entry>(exclude.entries_); }
/// <summary> /// Exclude all components in the range beginning at "from" and ending at "to". /// </summary> /// /// <param name="exclude">The Exclude object to update.</param> /// <param name="from">The first component in the exclude range.</param> /// <param name="to">The last component in the exclude range.</param> private static void excludeRange(Exclude exclude, Name.Component from, Name.Component to) { if (from.compare(to) >= 0) { if (from.compare(to) == 0) throw new Exception( "excludeRange: from == to. To exclude a single component, sue excludeOne."); else throw new Exception( "excludeRange: from must be less than to. Invalid range: [" + from.toEscapedString() + ", " + to.toEscapedString() + "]"); } ArrayList entries = getExcludeEntries(exclude); int iNewFrom; int iFoundFrom = findEntryBeforeOrAt(entries, from); if (iFoundFrom < 0) { // There is no entry before "from" so insert at the beginning. entries.Insert(0, new Producer.ExcludeEntry (from, true)); iNewFrom = 0; } else { Producer.ExcludeEntry foundFrom = (Producer.ExcludeEntry ) entries[iFoundFrom]; if (!foundFrom.anyFollowsComponent_) { if (foundFrom.component_.equals(from)) { // There is already an entry with "from", so just set the "ANY" flag. foundFrom.anyFollowsComponent_ = true; iNewFrom = iFoundFrom; } else { // Insert following the entry before "from". entries.Insert(iFoundFrom + 1, new Producer.ExcludeEntry (from, true)); iNewFrom = iFoundFrom + 1; } } else // The entry before "from" already has an "ANY" flag, so do nothing. iNewFrom = iFoundFrom; } // We have at least one "from" before "to", so we know this will find an entry. int iFoundTo = findEntryBeforeOrAt(entries, to); Producer.ExcludeEntry foundTo = (Producer.ExcludeEntry ) entries[iFoundTo]; if (iFoundTo == iNewFrom) // Insert the "to" immediately after the "from". entries.Insert(iNewFrom + 1, new Producer.ExcludeEntry (to, false)); else { int iRemoveEnd; if (!foundTo.anyFollowsComponent_) { if (foundTo.component_.equals(to)) // The "to" entry already exists. Remove up to it. iRemoveEnd = iFoundTo; else { // Insert following the previous entry, which will be removed. entries.Insert(iFoundTo + 1, new Producer.ExcludeEntry (to, false)); iRemoveEnd = iFoundTo + 1; } } else // "to" follows a component which is already followed by "ANY", meaning // the new range now encompasses it, so remove the component. iRemoveEnd = iFoundTo + 1; // Remove intermediate entries since they are inside the range. int iRemoveBegin = iNewFrom + 1; int nRemoveNeeded = iRemoveEnd - iRemoveBegin; for (int i = 0; i < nRemoveNeeded; ++i) ILOG.J2CsMapping.Collections.Collections.RemoveAt(entries,iRemoveBegin); } setExcludeEntries(exclude, entries); }
/// <summary> /// Create a list of ExcludeEntry from the Exclude object. /// </summary> /// /// <param name="exclude">The Exclude object to read.</param> /// <returns>A new list of ExcludeEntry.</returns> private static ArrayList getExcludeEntries(Exclude exclude) { ArrayList entries = new ArrayList(); for (int i = 0; i < exclude.size(); ++i) { if (exclude.get(i).getType() == net.named_data.jndn.Exclude.Type.ANY) { if (entries.Count == 0) // Add a "beginning ANY". ILOG.J2CsMapping.Collections.Collections.Add(entries,new Producer.ExcludeEntry (new Name.Component(), true)); else // Set anyFollowsComponent of the final component. ((Producer.ExcludeEntry ) entries[entries.Count - 1]).anyFollowsComponent_ = true; } else ILOG.J2CsMapping.Collections.Collections.Add(entries,new Producer.ExcludeEntry (exclude.get(i).getComponent(), false)); } return entries; }
/// <summary> /// Exclude all components in the range ending at "to". /// </summary> /// /// <param name="exclude">The Exclude object to update.</param> /// <param name="to">The last component in the exclude range.</param> private static void excludeBefore(Exclude exclude, Name.Component to) { excludeRange(exclude, new Name.Component(), to); }
/// <summary> /// Exclude all components in the range beginning at "from". /// </summary> /// /// <param name="exclude">The Exclude object to update.</param> /// <param name="from">The first component in the exclude range.</param> private static void excludeAfter(Exclude exclude, Name.Component from) { ArrayList entries = getExcludeEntries(exclude); int iNewFrom; int iFoundFrom = findEntryBeforeOrAt(entries, from); if (iFoundFrom < 0) { // There is no entry before "from" so insert at the beginning. entries.Insert(0, new Producer.ExcludeEntry (from, true)); iNewFrom = 0; } else { Producer.ExcludeEntry foundFrom = (Producer.ExcludeEntry ) entries[iFoundFrom]; if (!foundFrom.anyFollowsComponent_) { if (foundFrom.component_.equals(from)) { // There is already an entry with "from", so just set the "ANY" flag. foundFrom.anyFollowsComponent_ = true; iNewFrom = iFoundFrom; } else { // Insert following the entry before "from". entries.Insert(iFoundFrom + 1, new Producer.ExcludeEntry (from, true)); iNewFrom = iFoundFrom + 1; } } else // The entry before "from" already has an "ANY" flag, so do nothing. iNewFrom = iFoundFrom; } // Remove entries after the new "from". int iRemoveBegin = iNewFrom + 1; int nRemoveNeeded = entries.Count - iRemoveBegin; for (int i = 0; i < nRemoveNeeded; ++i) ILOG.J2CsMapping.Collections.Collections.RemoveAt(entries,iRemoveBegin); setExcludeEntries(exclude, entries); }
/// <summary> /// This is called from an expressInterest OnData to check that the encryption /// key contained in data fits the timeSlot. This sends a refined interest if /// required. /// </summary> /// /// <param name="interest">The interest given to expressInterest.</param> /// <param name="data">The fetched Data packet.</param> /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">encrypted content key Data packets. If onEncryptedKeys is null, this does not use it.</param> internal void handleCoveringKey(Interest interest, Data data, double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double timeCount = Math.Round(timeSlot_0,MidpointRounding.AwayFromZero); Producer.KeyRequest keyRequest = (Producer.KeyRequest ) ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_,timeCount); Name interestName = interest.getName(); Name keyName = data.getName(); double begin = net.named_data.jndn.encrypt.Schedule.fromIsoString(keyName .get(START_TIME_STAMP_INDEX).getValue().toString()); double end = net.named_data.jndn.encrypt.Schedule.fromIsoString(keyName.get(END_TIME_STAMP_INDEX) .getValue().toString()); if (timeSlot_0 >= end) { // If the received E-KEY covers some earlier period, try to retrieve an // E-KEY covering a later one. Exclude timeRange = new Exclude(interest.getExclude()); excludeBefore(timeRange, keyName.get(START_TIME_STAMP_INDEX)); ILOG.J2CsMapping.Collections.Collections.Put(keyRequest.repeatAttempts,interestName,0); sendKeyInterest(new Interest(interestName).setExclude(timeRange) .setChildSelector(1), timeSlot_0, onEncryptedKeys_1, onError_2); } else { // If the received E-KEY covers the content key, encrypt the content. Blob encryptionKey = data.getContent(); // If everything is correct, save the E-KEY as the current key. if (encryptContentKey(encryptionKey, keyName, timeSlot_0, onEncryptedKeys_1, onError_2)) { Producer.KeyInfo keyInfo = (Producer.KeyInfo ) ILOG.J2CsMapping.Collections.Collections.Get(eKeyInfo_,interestName); keyInfo.beginTimeSlot = begin; keyInfo.endTimeSlot = end; keyInfo.keyBits = encryptionKey; } } }
/// <summary> /// Create the content key corresponding to the timeSlot. This first checks if /// the content key exists. For an existing content key, this returns the /// content key name directly. If the key does not exist, this creates one and /// encrypts it using the corresponding E-KEYs. The encrypted content keys are /// passed to the onEncryptedKeys callback. /// </summary> /// /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">content key Data packets. If onEncryptedKeys is null, this does not use it. NOTE: The library will log any exceptions thrown by this callback, but for better error handling the callback should catch and properly handle any exceptions.</param> /// <param name="onError_2">better error handling the callback should catch and properly handle any exceptions.</param> /// <returns>The content key name.</returns> public Name createContentKey(double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double hourSlot = getRoundedTimeSlot(timeSlot_0); // Create the content key name. Name contentKeyName = new Name(namespace_); contentKeyName.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_C_KEY); contentKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(hourSlot)); Blob contentKeyBits; // Check if we have created the content key before. if (database_.hasContentKey(timeSlot_0)) // We have created the content key. Return its name directly. return contentKeyName; // We haven't created the content key. Create one and add it into the database. AesKeyParams aesParams = new AesKeyParams(128); contentKeyBits = net.named_data.jndn.encrypt.algo.AesAlgorithm.generateKey(aesParams).getKeyBits(); database_.addContentKey(timeSlot_0, contentKeyBits); // Now we need to retrieve the E-KEYs for content key encryption. double timeCount = Math.Round(timeSlot_0,MidpointRounding.AwayFromZero); ILOG.J2CsMapping.Collections.Collections.Put(keyRequests_,timeCount,new Producer.KeyRequest (eKeyInfo_.Count)); Producer.KeyRequest keyRequest = (Producer.KeyRequest ) ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_,timeCount); // Check if the current E-KEYs can cover the content key. Exclude timeRange = new Exclude(); excludeAfter(timeRange, new Name.Component(net.named_data.jndn.encrypt.Schedule.toIsoString(timeSlot_0))); new ILOG.J2CsMapping.Collections.IteratorAdapter(eKeyInfo_.GetEnumerator()); for (IIterator i = new ILOG.J2CsMapping.Collections.IteratorAdapter(eKeyInfo_.GetEnumerator()); i.HasNext();) { // For each current E-KEY. DictionaryEntry entry = (DictionaryEntry) i.Next(); Producer.KeyInfo keyInfo = (Producer.KeyInfo ) ((DictionaryEntry) entry).Value; if (timeSlot_0 < keyInfo.beginTimeSlot || timeSlot_0 >= keyInfo.endTimeSlot) { // The current E-KEY cannot cover the content key, so retrieve one. ILOG.J2CsMapping.Collections.Collections.Put(keyRequest.repeatAttempts,((DictionaryEntry) entry).Key,0); sendKeyInterest( new Interest((Name) ((DictionaryEntry) entry).Key).setExclude( timeRange).setChildSelector(1), timeSlot_0, onEncryptedKeys_1, onError_2); } else { // The current E-KEY can cover the content key. // Encrypt the content key directly. Name eKeyName = new Name((Name) ((DictionaryEntry) entry).Key); eKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(keyInfo.beginTimeSlot)); eKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(keyInfo.endTimeSlot)); encryptContentKey(keyInfo.keyBits, eKeyName, timeSlot_0, onEncryptedKeys_1, onError_2); } } return contentKeyName; }
public void testExcludeMatches() { Exclude exclude = new Exclude(); exclude.appendComponent(new Name("%00%02").get(0)); exclude.appendAny(); exclude.appendComponent(new Name("%00%20").get(0)); Name.Component component; component = new Name("%00%01").get(0); Assert.AssertFalse(component.toEscapedString() + " should not match " + exclude.toUri(), exclude.matches(component)); component = new Name("%00%0F").get(0); Assert.AssertTrue( component.toEscapedString() + " should match " + exclude.toUri(), exclude.matches(component)); component = new Name("%00%21").get(0); Assert.AssertFalse(component.toEscapedString() + " should not match " + exclude.toUri(), exclude.matches(component)); }