private void CompressNonIndexed(string headerName, string headerValue, IndexationType headerType, byte prefix) { int index = _remoteHeaderTable.FindIndex(kv => kv.Key == headerName); byte nameLenBinary = 0; // headers cant be more then 255 characters length byte[] nameBinary = new byte[0]; //It's necessary to form result array because partial writeToOutput stream can cause problems because of multithreading using (var stream = new MemoryStream(64)) { byte[] indexBinary; byte valueLenBinary; byte[] valueBinary; if (index != -1) { indexBinary = (index + 1).ToUVarInt(prefix); } else { indexBinary = 0.ToUVarInt(prefix); nameBinary = Encoding.UTF8.GetBytes(headerName); nameLenBinary = (byte)nameBinary.Length; } //Set without index type indexBinary[0] |= (byte)headerType; valueBinary = Encoding.UTF8.GetBytes(headerValue); valueLenBinary = (byte)valueBinary.Length; stream.Write(indexBinary, 0, indexBinary.Length); //write replaced index. It's equal with the found index in our case if (headerType == IndexationType.Substitution) { stream.Write(indexBinary, 0, indexBinary.Length); } if (index == -1) { stream.WriteByte(nameLenBinary); stream.Write(nameBinary, 0, nameBinary.Length); } stream.WriteByte(valueLenBinary); stream.Write(valueBinary, 0, valueBinary.Length); WriteToOutput(stream.GetBuffer(), 0, (int)stream.Position); } ModifyTable(headerName, headerValue, headerType, _remoteHeaderTable, index); }
/// <summary> /// Get index. /// </summary> /// <param name="bytes">The bytes.</param> /// <param name="type">The indexation type.</param> /// <returns>The index.</returns> private int GetIndex(byte[] bytes, IndexationType type) { byte prefix = 0; byte firstByteValue = bytes[_currentOffset]; switch (type) { case IndexationType.Incremental: prefix = (byte)UVarIntPrefix.Incremental; break; case IndexationType.WithoutIndexation: prefix = (byte)UVarIntPrefix.WithoutIndexing; break; case IndexationType.Indexed: prefix = (byte)UVarIntPrefix.Indexed; break; case IndexationType.EncodingContextUpdate: prefix = (byte)UVarIntPrefix.EncodingContextUpdate; break; case IndexationType.NeverIndexed: prefix = (byte)UVarIntPrefix.NeverIndexed; break; } int maxPrefixVal = (1 << prefix) - 1; if (firstByteValue < maxPrefixVal) { _currentOffset++; return(firstByteValue); } int i = 1; while (true) { if ((bytes[_currentOffset + i] & (byte)IndexationType.Indexed) == 0) { break; } i++; } var numberBytes = new byte[++i]; Buffer.BlockCopy(bytes, _currentOffset, numberBytes, 0, i); _currentOffset += i; return(Int32Extensions.FromUVarInt(numberBytes)); }
private int GetIndex(byte[] bytes, IndexationType type) { byte prefix = 0; byte firstByteValue = /*(byte) (*/ bytes[_currentOffset];// & (~(byte)type)); switch (type) { case IndexationType.Incremental: case IndexationType.WithoutIndexation: prefix = 5; break; case IndexationType.Substitution: prefix = 6; break; case IndexationType.Indexed: prefix = 7; break; } int maxPrefixVal = (1 << prefix) - 1; if (firstByteValue < maxPrefixVal) { _currentOffset++; return(firstByteValue); } int i = 1; while (true) { if ((bytes[_currentOffset + i] & 0x80) == 0) { break; } i++; } var numberBytes = new byte[++i]; Buffer.BlockCopy(bytes, _currentOffset, numberBytes, 0, i); _currentOffset += i; return(new int().FromUVarInt(numberBytes)); }
private void ModifyTable(string headerName, string headerValue, IndexationType headerType, SizedHeadersList useHeadersTable, int index) { int headerLen = headerName.Length + headerValue.Length; switch (headerType) { case IndexationType.Incremental: if (useHeadersTable.Count > HeadersLimit - 1) { useHeadersTable.RemoveAt(0); } while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize) { useHeadersTable.RemoveAt(0); } useHeadersTable.Add(new KeyValuePair <string, string>(headerName, headerValue)); break; case IndexationType.Substitution: if (index != -1) { useHeadersTable[index] = new KeyValuePair <string, string>(headerName, headerValue); } else { if (useHeadersTable.Count > HeadersLimit - 1) { useHeadersTable.RemoveAt(0); } while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize) { useHeadersTable.RemoveAt(0); } //If header wasn't found then add it to the table useHeadersTable.Add(new KeyValuePair <string, string>(headerName, headerValue)); } break; default: return; } }
public Indexation(IndexationType type) { Type = type; }
private void ModifyTable(string headerName, string headerValue, IndexationType headerType, SizedHeadersList useHeadersTable, int index) { int headerLen = headerName.Length + headerValue.Length; switch (headerType) { case IndexationType.Incremental: if (useHeadersTable.Count > HeadersLimit - 1) { useHeadersTable.RemoveAt(0); } while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize) { useHeadersTable.RemoveAt(0); } useHeadersTable.Add(new KeyValuePair<string, string>(headerName, headerValue)); break; case IndexationType.Substitution: if (index != -1) { useHeadersTable[index] = new KeyValuePair<string, string>(headerName, headerValue); } else { if (useHeadersTable.Count > HeadersLimit - 1) { useHeadersTable.RemoveAt(0); } while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize) { useHeadersTable.RemoveAt(0); } //If header wasn't found then add it to the table useHeadersTable.Add(new KeyValuePair<string, string>(headerName, headerValue)); } break; default: return; } }
private int GetIndex(byte[] bytes, IndexationType type) { byte prefix = 0; byte firstByteValue = /*(byte) (*/bytes[_currentOffset];// & (~(byte)type)); switch (type) { case IndexationType.Incremental: case IndexationType.WithoutIndexation: prefix = 5; break; case IndexationType.Substitution: prefix = 6; break; case IndexationType.Indexed: prefix = 7; break; } int maxPrefixVal = (1 << prefix) - 1; if (firstByteValue < maxPrefixVal) { _currentOffset++; return firstByteValue; } int i = 1; while (true) { if ((bytes[_currentOffset + i] & 0x80) == 0) { break; } i++; } var numberBytes = new byte[++i]; Buffer.BlockCopy(bytes, _currentOffset, numberBytes, 0, i); _currentOffset += i; return Int32Extensions.FromUVarInt(numberBytes); }
/// <summary> /// Modifies the table. /// </summary> /// <param name="headerName">Name of the header.</param> /// <param name="headerValue">The header value.</param> /// <param name="headerType">Type of the header.</param> /// <param name="useHeadersTable">The use headers table.</param> /// <param name="index">The index.</param> private void ModifyTable(string headerName, string headerValue, IndexationType headerType, HeadersList useHeadersTable, int index) { int headerLen = headerName.Length + headerValue.Length + sizeof(Int32); //spec 04: 3.2.3. Header Table Management // The header table can be modified by either adding a new entry to it //or by replacing an existing one. Before doing such a modification, //it has to be ensured that the header table size will stay lower than //or equal to the SETTINGS_MAX_BUFFER_SIZE limit (see Section 5). To //achieve this, repeatedly, the first entry of the header table is //removed, until enough space is available for the modification. //A consequence of removing one or more entries at the beginning of the //header table is that the remaining entries are renumbered. The first //entry of the header table is always associated to the index 0. //When the modification of the header table is the replacement of an //existing entry, the replaced entry is the one indicated in the //literal representation before any entry is removed from the header //table. If the entry to be replaced is removed from the header table //when performing the size adjustment, the replacement entry is //inserted at the beginning of the header table. //The addition of a new entry with a size greater than the //SETTINGS_MAX_BUFFER_SIZE limit causes all the entries from the header //table to be dropped and the new entry not to be added to the header //table. The replacement of an existing entry with a new entry with a //size greater than the SETTINGS_MAX_BUFFER_SIZE has the same //consequences. switch (headerType) { case IndexationType.Incremental: while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize && useHeadersTable.Count > 0) { useHeadersTable.RemoveAt(0); } useHeadersTable.Add(new KeyValuePair<string, string>(headerName, headerValue)); break; case IndexationType.Substitution: if (index != -1) { var header = useHeadersTable[index]; int substHeaderLen = header.Key.Length + header.Value.Length + sizeof(Int32); int deletedHeadersCounter = 0; while (useHeadersTable.StoredHeadersSize + headerLen - substHeaderLen > MaxHeaderByteSize) { if (useHeadersTable.Count > 0) { useHeadersTable.RemoveAt(0); deletedHeadersCounter++; } } if (index >= deletedHeadersCounter) { useHeadersTable[index - deletedHeadersCounter] = new KeyValuePair<string, string>(headerName, headerValue); } else { useHeadersTable.Insert(0, new KeyValuePair<string, string>(headerName, headerValue)); } } //If header wasn't found then add it to the table else { while (useHeadersTable.StoredHeadersSize + headerLen > MaxHeaderByteSize && useHeadersTable.Count > 0) { useHeadersTable.RemoveAt(0); } useHeadersTable.Add(new KeyValuePair<string, string>(headerName, headerValue)); } break; default: return; } }
private void CompressNonIndexed(string headerName, string headerValue, IndexationType headerType, byte prefix) { //spec 04 //A header name and an entry name match if they are equal //using a character-based, _case insensitive_ comparison (the case //insensitive comparison is used because HTTP header names are defined //in a case insensitive way). A header value and an entry value match //if they are equal using a character-based, _case sensitive_ //comparison. int index = _remoteHeaderTable.FindIndex(kv => kv.Key.Equals(headerName, StringComparison.OrdinalIgnoreCase)); byte nameLenBinary = 0; // headers cant be more then 255 characters length byte[] nameBinary = new byte[0]; //It's necessary to form result array because partial writeToOutput stream can cause problems because of multithreading using (var stream = new MemoryStream(64)) { byte[] indexBinary; byte valueLenBinary; byte[] valueBinary; if (index != -1) { indexBinary = (index + 1).ToUVarInt(prefix); } else { indexBinary = 0.ToUVarInt(prefix); nameBinary = Encoding.UTF8.GetBytes(headerName); nameLenBinary = (byte)nameBinary.Length; } //Set without index type indexBinary[0] |= (byte)headerType; valueBinary = Encoding.UTF8.GetBytes(headerValue); valueLenBinary = (byte)valueBinary.Length; stream.Write(indexBinary, 0, indexBinary.Length); //write replaced index. It's equal with the found index in our case if (headerType == IndexationType.Substitution) { stream.Write(indexBinary, 0, indexBinary.Length); } if (index == -1) { stream.WriteByte(nameLenBinary); stream.Write(nameBinary, 0, nameBinary.Length); } stream.WriteByte(valueLenBinary); stream.Write(valueBinary, 0, valueBinary.Length); WriteToOutput(stream.GetBuffer(), 0, (int)stream.Position); } ModifyTable(headerName, headerValue, headerType, _remoteHeaderTable, index); }
private int GetIndex(byte[] bytes, IndexationType type) { byte prefix = 0; byte firstByteValue = bytes[_currentOffset]; switch (type) { case IndexationType.Incremental: prefix = (byte)UVarIntPrefix.Incremental; break; case IndexationType.WithoutIndexation: prefix = (byte)UVarIntPrefix.WithoutIndexing; break; case IndexationType.Indexed: prefix = (byte)UVarIntPrefix.Indexed; break; case IndexationType.EncodingContextUpdate: prefix = (byte)UVarIntPrefix.EncodingContextUpdate; break; case IndexationType.NeverIndexed: prefix = (byte) UVarIntPrefix.NeverIndexed; break; } int maxPrefixVal = (1 << prefix) - 1; if (firstByteValue < maxPrefixVal) { _currentOffset++; return firstByteValue; } int i = 1; while (true) { if ((bytes[_currentOffset + i] & (byte)IndexationType.Indexed) == 0) { break; } i++; } var numberBytes = new byte[++i]; Buffer.BlockCopy(bytes, _currentOffset, numberBytes, 0, i); _currentOffset += i; return Int32Extensions.FromUVarInt(numberBytes); }