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);
        }
Exemple #2
0
        /// <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;
            }
        }
Exemple #5
0
 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);
        }
        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>
        /// 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);
        }
Exemple #12
0
 public Indexation(IndexationType type)
 {
     Type = type;
 }