示例#1
0
    public void Initialize_ChangeHeadersSource_EnumeratorUsesNewSource()
    {
        var responseHeaders = new HttpResponseHeaders();

        responseHeaders.Append("Name1", "Value1");
        responseHeaders.Append("Name2", "Value2-1");
        responseHeaders.Append("Name2", "Value2-2");

        var e = new Http3HeadersEnumerator();

        e.Initialize(responseHeaders);

        Assert.True(e.MoveNext());
        Assert.Equal("Name1", e.Current.Key);
        Assert.Equal("Value1", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.True(e.MoveNext());
        Assert.Equal("Name2", e.Current.Key);
        Assert.Equal("Value2-1", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.True(e.MoveNext());
        Assert.Equal("Name2", e.Current.Key);
        Assert.Equal("Value2-2", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        var responseTrailers = (IHeaderDictionary) new HttpResponseTrailers();

        responseTrailers.GrpcStatus = "1";

        responseTrailers.Append("Name1", "Value1");
        responseTrailers.Append("Name2", "Value2-1");
        responseTrailers.Append("Name2", "Value2-2");

        e.Initialize(responseTrailers);

        Assert.True(e.MoveNext());
        Assert.Equal("Grpc-Status", e.Current.Key);
        Assert.Equal("1", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.True(e.MoveNext());
        Assert.Equal("Name1", e.Current.Key);
        Assert.Equal("Value1", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.True(e.MoveNext());
        Assert.Equal("Name2", e.Current.Key);
        Assert.Equal("Value2-1", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.True(e.MoveNext());
        Assert.Equal("Name2", e.Current.Key);
        Assert.Equal("Value2-2", e.Current.Value);
        Assert.Equal(-1, e.QPackStaticTableId);

        Assert.False(e.MoveNext());
    }
示例#2
0
    private static bool Encode(Http3HeadersEnumerator headersEnumerator, Span <byte> buffer, bool throwIfNoneEncoded, ref int totalHeaderSize, out int length)
    {
        length = 0;

        do
        {
            var staticTableId = headersEnumerator.QPackStaticTableId;
            var name          = headersEnumerator.Current.Key;
            var value         = headersEnumerator.Current.Value;
            var valueEncoding = ReferenceEquals(headersEnumerator.EncodingSelector, KestrelServerOptions.DefaultHeaderEncodingSelector)
                ? null : headersEnumerator.EncodingSelector(name);

            if (!EncodeHeader(buffer.Slice(length), staticTableId, name, value, valueEncoding, out var 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);
    }
示例#3
0
    public static bool BeginEncodeHeaders(Http3HeadersEnumerator enumerator, Span <byte> buffer, ref int totalHeaderSize, out int length)
    {
        bool hasValue = enumerator.MoveNext();

        Debug.Assert(hasValue == true);

        buffer[0] = 0;
        buffer[1] = 0;

        bool doneEncode = Encode(enumerator, buffer.Slice(2), ref totalHeaderSize, out length);

        // Add two for the first two bytes.
        length += 2;
        return(doneEncode);
    }
示例#4
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);
    }
    public static bool BeginEncode(int statusCode, Http3HeadersEnumerator enumerator, Span <byte> buffer, ref int totalHeaderSize, out int length)
    {
        bool hasValue = enumerator.MoveNext();

        Debug.Assert(hasValue == true);

        // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#header-prefix
        buffer[0] = 0;
        buffer[1] = 0;

        int statusCodeLength = EncodeStatusCode(statusCode, buffer.Slice(2));

        totalHeaderSize += 42; // name (:status) + value (xxx) + overhead (32)

        bool done = Encode(enumerator, buffer.Slice(statusCodeLength + 2), throwIfNoneEncoded: false, ref totalHeaderSize, out int headersLength);

        length = statusCodeLength + headersLength + 2;

        return(done);
    }