Example #1
0
        private static bool Encode(Http3HeadersEnumerator enumerator, Span <byte> buffer, bool throwIfNoneEncoded, ref int totalHeaderSize, out int length)
        {
            length = 0;

            do
            {
                var current       = enumerator.Current;
                var valueEncoding = ReferenceEquals(enumerator.EncodingSelector, KestrelServerOptions.DefaultHeaderEncodingSelector)
                    ? null : enumerator.EncodingSelector(current.Key);

                if (!QPackEncoder.EncodeLiteralHeaderFieldWithoutNameReference(current.Key, current.Value, valueEncoding, buffer.Slice(length), out int headerLength))
                {
                    if (length == 0 && throwIfNoneEncoded)
                    {
                        throw new QPackEncodingException("TODO sync with corefx" /* CoreStrings.HPackErrorNotEnoughBuffer */);
                    }
                    return(false);
                }

                // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-4.1.1.3
                totalHeaderSize += HeaderField.GetLength(current.Key.Length, current.Value.Length);
                length          += headerLength;
            } while (enumerator.MoveNext());

            return(true);
        }
Example #2
0
    private static bool Encode(Http3HeadersEnumerator headersEnumerator, Span <byte> buffer, bool throwIfNoneEncoded, ref int totalHeaderSize, out int length)
    {
        length = 0;

        do
        {
            // Match the current header to the QPACK static table. Possible outcomes:
            // 1. Known header and value. Write index.
            // 2. Known header with custom value. Write name index and full value.
            // 3. Unknown header. Write full name and value.
            var(staticTableId, matchedValue) = headersEnumerator.GetQPackStaticTableId();
            var name  = headersEnumerator.Current.Key;
            var value = headersEnumerator.Current.Value;

            int headerLength;
            if (matchedValue)
            {
                if (!QPackEncoder.EncodeStaticIndexedHeaderField(staticTableId, buffer.Slice(length), out headerLength))
                {
                    if (length == 0 && throwIfNoneEncoded)
                    {
                        throw new QPackEncodingException("TODO sync with corefx" /* CoreStrings.HPackErrorNotEnoughBuffer */);
                    }
                    return(false);
                }
            }
            else
            {
                var valueEncoding = ReferenceEquals(headersEnumerator.EncodingSelector, KestrelServerOptions.DefaultHeaderEncodingSelector)
                    ? null : headersEnumerator.EncodingSelector(name);

                if (!EncodeHeader(buffer.Slice(length), staticTableId, name, value, valueEncoding, out headerLength))
                {
                    if (length == 0 && throwIfNoneEncoded)
                    {
                        throw new QPackEncodingException("TODO sync with corefx" /* CoreStrings.HPackErrorNotEnoughBuffer */);
                    }
                    return(false);
                }
            }

            // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-4.1.1.3
            totalHeaderSize += HeaderField.GetLength(name.Length, value.Length);
            length          += headerLength;
        } while (headersEnumerator.MoveNext());

        return(true);
    }
Example #3
0
        public void Insert(ReadOnlySpan <byte> name, ReadOnlySpan <byte> value)
        {
            int entryLength = HeaderField.GetLength(name.Length, value.Length);

            EnsureAvailable(entryLength);

            if (entryLength > _maxSize)
            {
                // http://httpwg.org/specs/rfc7541.html#rfc.section.4.4
                // It is not an error to attempt to add an entry that is larger than the maximum size;
                // an attempt to add an entry larger than the maximum size causes the table to be emptied
                // of all existing entries and results in an empty table.
                return;
            }

            var entry = new HeaderField(name, value);

            _buffer[_insertIndex] = entry;
            _insertIndex          = (_insertIndex + 1) % _buffer.Length;
            _size += entry.Length;
            _count++;
        }
Example #4
0
    public bool EncodeHeader(Span <byte> buffer, int staticTableIndex, HeaderEncodingHint encodingHint, string name, string value,
                             Encoding?valueEncoding, out int bytesWritten)
    {
        Debug.Assert(!_pendingTableSizeUpdate, "Dynamic table size update should be encoded before headers.");

        // Never index sensitive value.
        if (encodingHint == HeaderEncodingHint.NeverIndex)
        {
            int index = ResolveDynamicTableIndex(staticTableIndex, name);

            return(index == -1
                ? HPackEncoder.EncodeLiteralHeaderFieldNeverIndexingNewName(name, value, valueEncoding, buffer, out bytesWritten)
                : HPackEncoder.EncodeLiteralHeaderFieldNeverIndexing(index, value, valueEncoding, buffer, out bytesWritten));
        }

        // No dynamic table. Only use the static table.
        if (!_allowDynamicCompression || _maxHeaderTableSize == 0 || encodingHint == HeaderEncodingHint.IgnoreIndex)
        {
            return(staticTableIndex == -1
                ? HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, valueEncoding, buffer, out bytesWritten)
                : HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexing(staticTableIndex, value, valueEncoding, buffer, out bytesWritten));
        }

        // Header is greater than the maximum table size.
        // Don't attempt to add dynamic header as all existing dynamic headers will be removed.
        var headerLength = HeaderField.GetLength(name.Length, valueEncoding?.GetByteCount(value) ?? value.Length);

        if (headerLength > _maxHeaderTableSize)
        {
            int index = ResolveDynamicTableIndex(staticTableIndex, name);

            return(index == -1
                ? HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexingNewName(name, value, valueEncoding, buffer, out bytesWritten)
                : HPackEncoder.EncodeLiteralHeaderFieldWithoutIndexing(index, value, valueEncoding, buffer, out bytesWritten));
        }

        return(EncodeDynamicHeader(buffer, staticTableIndex, name, value, headerLength, valueEncoding, out bytesWritten));
    }