Example #1
0
        /// <summary>
        /// Compress incremental.
        /// </summary>
        /// <param name="header">The header.</param>
        private void CompressIncremental(KeyValuePair <string, string> header)
        {
            const byte prefix = (byte)UVarIntPrefix.Incremental;

            /* 12 -> 8.1.3
             * Just as in HTTP/1.x, header field names are strings of ASCII
             * characters that are compared in a case-insensitive fashion.  However,
             * header field names MUST be converted to lowercase prior to their
             * encoding in HTTP/2. */
            int  index   = _remoteHeadersTable.FindIndex(kv => kv.Key.Equals(header.Key, StringComparison.OrdinalIgnoreCase));
            bool isFound = index != -1;

            /* 07 -> 3.1.4
             *      <----------  Index Address Space ---------->
             *      <-- Header  Table -->  <-- Static  Table -->
             +---+-----------+---+  +---+-----------+---+
             | 1 |    ...    | k |  |k+1|    ...    | n |
             +---+-----------+---+  +---+-----------+---+
             |      ^                   |
             |                   V
             | Insertion Point       Drop Point
             */
            // 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[] nameBinary = new byte[0];
                byte[] valueBinary;

                if (isFound)
                {
                    // Header key was found in the header table. Hence we should encode only value
                    indexBinary = (index + 1).ToUVarInt(prefix);
                    valueBinary = EncodeString(header.Value, true);
                }
                else
                {
                    // Header key was not found in the header table. Hence we should encode name and value
                    indexBinary = 0.ToUVarInt(prefix);
                    nameBinary  = EncodeString(header.Key, true);
                    valueBinary = EncodeString(header.Value, true);
                }

                // Set without index type
                indexBinary[0] |= (byte)IndexationType.Incremental;

                stream.Write(indexBinary, 0, indexBinary.Length);
                stream.Write(nameBinary, 0, nameBinary.Length);
                stream.Write(valueBinary, 0, valueBinary.Length);

                WriteToOutput(stream.GetBuffer(), 0, (int)stream.Position);
            }

            InsertToHeadersTable(header, _remoteRefSet, _remoteHeadersTable);
        }