/// <summary> /// Remove and return the oldest header field from the dynamic table. /// </summary> private HeaderField Remove() { if (this.size == 0) { return(null); } HeaderEntry eldest = head.After; int h = eldest.Hash; int i = Encoder.Index(h); HeaderEntry prev = headerFields[i]; HeaderEntry e = prev; while (e != null) { HeaderEntry next = e.Next; if (e == eldest) { if (prev == eldest) { headerFields[i] = next; } else { prev.Next = next; } eldest.Remove(); this.size -= eldest.Size; return(eldest); } prev = e; e = next; } return(null); }
/// <summary> /// Add the header field to the dynamic table. /// Entries are evicted from the dynamic table until the size of the table /// and the new header field is less than the table's capacity. /// If the size of the new entry is larger than the table's capacity, /// the dynamic table will be cleared. /// </summary> /// <param name="name">Name.</param> /// <param name="value">Value.</param> private void Add(byte[] name, byte[] value) { int headerSize = HeaderField.SizeOf(name, value); // Clear the table if the header field size is larger than the capacity. if (headerSize > this.capacity) { this.Clear(); return; } // Evict oldest entries until we have enough capacity. while (this.size + headerSize > this.capacity) { this.Remove(); } // Copy name and value that modifications of original do not affect the dynamic table. name.CopyTo(name, 0); value.CopyTo(value, 0); int h = Encoder.Hash(name); int i = Encoder.Index(h); HeaderEntry old = headerFields[i]; HeaderEntry e = new HeaderEntry(h, name, value, head.Before.Index - 1, old); headerFields[i] = e; e.AddBefore(head); this.size += headerSize; }
/// <summary> /// Returns the header entry with the lowest index value for the header field. /// Returns null if header field is not in the dynamic table. /// </summary> /// <returns>The entry.</returns> /// <param name="name">Name.</param> /// <param name="value">Value.</param> private HeaderEntry GetEntry(byte[] name, byte[] value) { if (this.Length() == 0 || name == null || value == null) { return(null); } int h = Encoder.Hash(name); int i = Encoder.Index(h); for (HeaderEntry e = headerFields[i]; e != null; e = e.Next) { if (e.Hash == h && HPackUtil.Equals(name, e.Name) && HPackUtil.Equals(value, e.Value)) { return(e); } } return(null); }
/// <summary> /// Returns the lowest index value for the header field name in the dynamic table. /// Returns -1 if the header field name is not in the dynamic table. /// </summary> /// <returns>The index.</returns> /// <param name="name">Name.</param> private int GetIndex(byte[] name) { if (this.Length() == 0 || name == null) { return(-1); } int h = Encoder.Hash(name); int i = Encoder.Index(h); int index = -1; for (HeaderEntry e = headerFields[i]; e != null; e = e.Next) { if (e.Hash == h && HPackUtil.Equals(name, e.Name)) { index = e.Index; break; } } return(this.GetIndex(index)); }