Example #1
0
        public void ParseHeaderWithParameters2()
        {
            HeaderField field = HeaderField.Parse("Content-Disposition: attachment; filename=test.pdf");

            Assert.AreEqual("Content-Disposition", field.FieldName);
            Assert.AreEqual("attachment", field.FieldValue);
            Assert.AreEqual(1, field.Parameters.Count);
            Assert.AreEqual("test.pdf", field.Parameters["filename"]);
        }
Example #2
0
        public void ParseHeaderWithoutParameters()
        {
            HeaderField field = HeaderField.Parse("Content-type  : multipart/mixed");

            Assert.AreEqual("Content-type", field.FieldName);
            Assert.AreEqual(MultipartMessage.MediaTypeMultipartMixed, field.FieldValue);
            Assert.AreEqual(0, field.Parameters.Count);
            Assert.AreEqual("Content-type: multipart/mixed", field.ToString());
        }
        public async Task ClientsShouldBeAbleToReceiveInformationalHeaders()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);
            var res     = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            // Send and receive first set of informational headers
            var readInfoHeaders1Task = res.stream.ReadHeadersAsync();

            Assert.False(readInfoHeaders1Task.IsCompleted);

            var infoHeaders1 = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "100"
                },
                new HeaderField {
                    Name = "extension-field", Value = "bar"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders1);

            var recvdInfoHeaders1 = await readInfoHeaders1Task;

            Assert.True(infoHeaders1.SequenceEqual(recvdInfoHeaders1));

            // Send and receive second set of informational headers
            var readInfoHeaders2Task = res.stream.ReadHeadersAsync();

            Assert.False(readInfoHeaders2Task.IsCompleted);

            var infoHeaders2 = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "108"
                },
                new HeaderField {
                    Name = "extension-field-b", Value = "bar2"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1u, false, infoHeaders2);

            var recvdInfoHeaders2 = await readInfoHeaders2Task;

            Assert.True(infoHeaders2.SequenceEqual(recvdInfoHeaders2));

            // Send and receive final headers
            var recvHeadersTask = res.stream.ReadHeadersAsync();

            Assert.False(recvHeadersTask.IsCompleted);
            await inPipe.WriteHeaders(res.hEncoder, 1u, true, DefaultStatusHeaders);

            var recvdHeaders = await recvHeadersTask;

            Assert.True(DefaultStatusHeaders.SequenceEqual(recvdHeaders));
        }
Example #4
0
        public async Task IfSettingsDecreaseHeaderTableNextOutgoingHeadersShouldContainAnUpdate()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            Func <IStream, bool> listener = (s) =>
            {
                Task.Run(() =>
                {
                    var res = new HeaderField[]
                    {
                        new HeaderField {
                            Name = ":status", Value = "200"
                        },
                    };
                    s.WriteHeadersAsync(res, false);
                });
                return(true);
            };

            var http2Con = await ConnectionUtils.BuildEstablishedConnection(
                true, inPipe, outPipe, loggerProvider, listener);

            // Change remote settings 2 times
            var settings = Settings.Default;

            settings.HeaderTableSize = 8;
            await inPipe.WriteSettings(settings);

            await outPipe.AssertSettingsAck();

            settings.HeaderTableSize = 30;
            await inPipe.WriteSettings(settings);

            await outPipe.AssertSettingsAck();

            // Establish a stream
            // When we send a response through it we should observe the size udpate
            var hEncoder = new Encoder();
            await inPipe.WriteHeaders(hEncoder, 1, false, DefaultGetHeaders);

            // Wait for the incoming status headers with header update
            var fh = await outPipe.ReadFrameHeaderWithTimeout();

            Assert.Equal(FrameType.Headers, fh.Type);
            Assert.Equal((byte)(HeadersFrameFlags.EndOfHeaders), fh.Flags);
            Assert.Equal(1u, fh.StreamId);

            Assert.Equal(3, fh.Length);
            var data = new byte[fh.Length];
            await outPipe.ReadAllWithTimeout(new ArraySegment <byte>(data));

            Assert.Equal(0x28, data[0]); // Size Update to 8
            Assert.Equal(0x3e, data[1]); // Size Update to 30
            Assert.Equal(0x88, data[2]); // :status 200
        }
Example #5
0
        internal static HeaderField <sbyte[]>[] HeaderFields(string[] keys)
        {
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("unchecked") HeaderField<byte[]>[] fields = new HeaderField[keys.length];
            HeaderField <sbyte[]>[] fields = new HeaderField[keys.Length];
            for (int i = 0; i < keys.Length; i++)
            {
                fields[i] = HeaderField(keys[i]);
            }
            return(fields);
        }
Example #6
0
        public void SetHeader(string key, string value)
        {
            var headerField = new HeaderField()
            {
                Name      = key,
                Value     = value,
                Sensitive = false
            };

            SetHeader(headerField);
        }
Example #7
0
File: hpack.cs Project: zjmit/go2cs
                        public static @string String(this HeaderField hf)
                        {
                            @string suffix = default;

                            if (hf.Sensitive)
                            {
                                suffix = " (sensitive)";
                            }

                            return(fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix));
                        }
Example #8
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @SuppressWarnings("unchecked") @Override <Value> Value initialHeader(HeaderField<Value> field)
            internal override Value initialHeader <Value>(HeaderField <Value> field)
            {
                if (field == TX_ID)
                {
                    return(( Value )( object )1L);
                }
                else
                {
                    return(base.initialHeader(field));
                }
            }
Example #9
0
        public void ParseHeaderWithParameters()
        {
            HeaderField field = HeaderField.Parse("Content-type: multipart/mixed; boundary=\"23232\"; test=2");

            Assert.AreEqual("Content-type", field.FieldName);
            Assert.AreEqual(MultipartMessage.MediaTypeMultipartMixed, field.FieldValue);
            Assert.AreEqual(2, field.Parameters.Count);
            Assert.AreEqual("\"23232\"", field.Parameters["boundary"]);
            Assert.AreEqual("2", field.Parameters["test"]);
            Assert.AreEqual("Content-type: multipart/mixed; boundary=\"23232\"; test=2", field.ToString());
        }
Example #10
0
        private void EnsureAvailable(int available)
        {
            while (_count > 0 && _maxSize - _size < available)
            {
                ref HeaderField field = ref _buffer[_removeIndex];
                _size -= field.Length;
                field  = default;

                _count--;
                _removeIndex = (_removeIndex + 1) % _buffer.Length;
            }
        public object Parse(string value, object argument)
        {
            var headers = new List <HeaderField>();

            using (var sr = new StringReader(value)) {
                using (var sw = new StringWriter()) {
                    while (true)
                    {
                        var line = sr.ReadLine();

                        // end of block reached, no more headers
                        if (string.IsNullOrEmpty(line))
                        {
                            break;
                        }

                        sw.Write(line);
                        while (true)
                        {
                            var next = sr.Peek();

                            var isContinuation = next == Characters.Space || next == Characters.Tabulator;
                            if (isContinuation)
                            {
                                var continuation = sr.ReadLine();
                                if (string.IsNullOrEmpty(continuation))
                                {
                                    break;
                                }
                                sw.Write(continuation.Trim());
                            }
                            else
                            {
                                break;
                            }
                        }

                        var literals = sw.ToString();
                        if (!string.IsNullOrEmpty(literals))
                        {
                            var header = new HeaderField();
                            sw.Clear();
                            header.Deserialize(literals);
                            headers.Add(header);
                        }
                    }
                }
            }

            return(headers);
        }
Example #12
0
    static async void HandleIncomingStream(IStream stream)
    {
        try
        {
            // Read the headers
            var headers = await stream.ReadHeadersAsync();

            var method = headers.First(h => h.Name == ":method").Value;
            var path   = headers.First(h => h.Name == ":path").Value;
            // Print the request method and path
            Console.WriteLine("Method: {0}, Path: {1}", method, path);

            // Read the request body and write it to console
            var buf = new byte[2048];
            while (true)
            {
                var readResult = await stream.ReadAsync(new ArraySegment <byte>(buf));

                if (readResult.EndOfStream)
                {
                    break;
                }
                // Print the received bytes
                Console.WriteLine(Encoding.ASCII.GetString(buf, 0, readResult.BytesRead));
            }

            // Send a response which consists of headers and a payload
            var responseHeaders = new HeaderField[]
            {
                new HeaderField {
                    Name = ":status", Value = "200"
                },
                new HeaderField {
                    Name = "content-type", Value = "text/html"
                },
            };
            await stream.WriteHeadersAsync(responseHeaders, false);

            await stream.WriteAsync(new ArraySegment <byte>(
                                        responseBody), true);

            // Request is fully handled here
        }
        catch (Exception e)
        {
            Console.WriteLine("Error during handling request: {0}", e.Message);
            stream.Cancel();
        }
    }
Example #13
0
        public void IfSizeIsChangedMultipleTimesAllNecessaryUpdatesShouldBeEncoded(
            int[] sizeChanges, string expectedTableUpdateHexBytes)
        {
            var encoder = new Encoder(new Encoder.Options {
                HuffmanStrategy = HuffmanStrategy.Never,
            });

            foreach (var newSize in sizeChanges)
            {
                encoder.DynamicTableSize = newSize;
            }

            var fields = new HeaderField[] {
                new HeaderField {
                    Name = "ab", Value = "cd", Sensitive = true
                }
            };

            var result = new Buffer();

            result.AddHexString(expectedTableUpdateHexBytes);
            result.AddHexString("1002");
            result.WriteString("ab");
            result.AddHexString("02");
            result.WriteString("cd");

            var res = EncodeToTempBuf(encoder, fields, MaxFrameSize);

            Assert.Equal(result.Bytes, res.Bytes);
            Assert.Equal(1, res.FieldCount);
            Assert.Equal(0, encoder.DynamicTableUsedSize);
            Assert.Equal(0, encoder.DynamicTableLength);
            Assert.Equal(sizeChanges[sizeChanges.Length - 1], encoder.DynamicTableSize);

            // Encode a further header block
            // This may not contain any tableupdate data
            result = new Buffer();
            result.AddHexString("1002");
            result.WriteString("ab");
            result.AddHexString("02");
            result.WriteString("cd");

            res = EncodeToTempBuf(encoder, fields, MaxFrameSize);
            Assert.Equal(result.Bytes, res.Bytes);
            Assert.Equal(1, res.FieldCount);
            Assert.Equal(0, encoder.DynamicTableUsedSize);
            Assert.Equal(0, encoder.DynamicTableLength);
            Assert.Equal(sizeChanges[sizeChanges.Length - 1], encoder.DynamicTableSize);
        }
        public void WrapsAroundBuffer()
        {
            var header3 = new HeaderField(Encoding.ASCII.GetBytes("header-3"), Encoding.ASCII.GetBytes("value3"));
            var header4 = new HeaderField(Encoding.ASCII.GetBytes("header-4"), Encoding.ASCII.GetBytes("value4"));

            // Make the table small enough that the circular buffer kicks in.
            var dynamicTable = new DynamicTable(HeaderField.RfcOverhead * 3);

            dynamicTable.Insert(header4.Name, header4.Value);
            dynamicTable.Insert(header3.Name, header3.Value);
            dynamicTable.Insert(_header2.Name, _header2.Value);
            dynamicTable.Insert(_header1.Name, _header1.Value);

            VerifyTableEntries(dynamicTable, _header1, _header2);
        }
 private void OnModelPropertyChanged(object sender, PropertyChangedEventArgs e)
 {
     if (HeaderField != null && HeaderField.Contains(e.PropertyName))
     {
         BeginInvokeInUiThread(SyncHeaderAutomatic);
     }
     if (StatusField != null && StatusField.Contains(e.PropertyName))
     {
         BeginInvokeInUiThread(SyncStatusImageAutomatic);
     }
     if (ColorField != null && ColorField.Contains(e.PropertyName))
     {
         BeginInvokeInUiThread(SyncColorAutomatic);
     }
 }
Example #16
0
        public void SetHeader(HeaderField headerField)
        {
            if (string.IsNullOrEmpty(headerField.Name))
            {
                return;
            }

            var hf = Heads.Where(b => b.Name == headerField.Name).FirstOrDefault();

            if (!string.IsNullOrEmpty(hf.Name))
            {
                Heads.Remove(hf);
            }
            Heads.Add(headerField);
        }
Example #17
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 #18
0
        private void VerifyTableEntries(DynamicTable dynamicTable, params HeaderField[] entries)
        {
            Assert.Equal(entries.Length, dynamicTable.Count);
            Assert.Equal(entries.Sum(e => e.Length), dynamicTable.Size);

            for (int i = 0; i < entries.Length; i++)
            {
                HeaderField headerField = dynamicTable[i];

                Assert.NotSame(entries[i].Name, headerField.Name);
                Assert.Equal(entries[i].Name, headerField.Name);

                Assert.NotSame(entries[i].Value, headerField.Value);
                Assert.Equal(entries[i].Value, headerField.Value);
            }
        }
Example #19
0
 /// <summary>
 /// Add the header field to the dynamic table.
 /// Entries are evicted from the dynamic table until the size of the table
 /// and the new header field is less than or equal to the table's capacity.
 /// If the size of the new entry is larger than the table's capacity,
 /// the dynamic table will be cleared.
 /// </summary>
 /// <param name="header">Header.</param>
 public void Add(HeaderField header)
 {
     var headerSize = header.Size;
     if (headerSize > this.capacity) {
         this.Clear();
         return;
     }
     while(this.size + headerSize > this.capacity) {
         this.Remove();
     }
     this.headerFields[this.head++] = header;
     this.size += header.Size;
     if (this.head == this.headerFields.Length) {
         this.head = 0;
     }
 }
Example #20
0
File: hpack.cs Project: zjmit/go2cs
                        // Size returns the size of an entry per RFC 7541 section 4.1.
                        public static uint Size(this HeaderField hf)
                        {
                            // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
                            // "The size of the dynamic table is the sum of the size of
                            // its entries. The size of an entry is the sum of its name's
                            // length in octets (as defined in Section 5.2), its value's
                            // length in octets (see Section 5.2), plus 32.  The size of
                            // an entry is calculated using the length of the name and
                            // value without any Huffman encoding applied."

                            // This can overflow if somebody makes a large HeaderField
                            // Name and/or Value by hand, but we don't care, because that
                            // won't happen on the wire because the encoding doesn't allow
                            // it.
                            return(uint32(len(hf.Name) + len(hf.Value) + 32L));
                        }
 public HeaderField this[String index]
 {
     get
     {
         HeaderField lResult = BaseGet(index) as HeaderField;
         if (lResult == null)
         {
             lResult = new HeaderField("");
             BaseSet(index, lResult);
         }
         return(lResult);
     }
     set
     {
         BaseSet(index, value);
     }
 }
Example #22
0
        private void HandleDecodeIndexed()
        {
            var idx = this._tasks[0].IntData;

            this.Reset();
            var tableHeader = this._headerTable.GetAt(idx);

            AllowTableSizeUpdates = false;
            Done        = true;
            HeaderField = new HeaderField
            {
                Name      = tableHeader.Name,
                Value     = tableHeader.Value,
                Sensitive = false
            };
            HeaderSize = 32 + tableHeader.NameLen + tableHeader.ValueLen;
        }
Example #23
0
        public async Task <Http2Result> Post(byte[] data)
        {
            var result = new Http2Result();

            var headers = new HeaderField[]
            {
                new HeaderField {
                    Name = ":method", Value = "POST"
                },
                new HeaderField {
                    Name = ":scheme", Value = "http"
                },
                new HeaderField {
                    Name = ":path", Value = _path
                },
                new HeaderField {
                    Name = ":authority", Value = _authority
                },
            };

            var stream = await _conn.CreateStreamAsync(headers, true);

            result.Heads = (await stream.ReadHeadersAsync()).ToList();

            List <byte> list = new List <byte>();

            while (true)
            {
                var buf = new byte[8192];
                var res = await stream.ReadAsync(new ArraySegment <byte>(buf));

                if (res.EndOfStream)
                {
                    break;
                }
                list.AddRange(buf.AsSpan().Slice(0, res.BytesRead).ToArray());
            }
            if (list.Any())
            {
                result.Body = list.ToArray();
            }
            return(result);
        }
        public async Task RespondingInvalidHeadersShouldTriggerAnException()
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await ServerStreamTests.StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);

            var headers = new HeaderField[]
            {
                new HeaderField {
                    Name = "status", Value = "200"
                },
            };
            var ex = await Assert.ThrowsAsync <Exception>(async() =>
                                                          await r.stream.WriteHeadersAsync(headers, false));

            Assert.Equal("ErrorInvalidPseudoHeader", ex.Message);
        }
Example #25
0
        public async Task ItShouldBePossibleToSendInformationalHeaders()
        {
            var inPipe = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var r = await StreamCreator.CreateConnectionAndStream(
                StreamState.Open, loggerProvider, inPipe, outPipe);
            var infoHeaders = new HeaderField[]
            {
                new HeaderField { Name = ":status", Value = "100" },
                new HeaderField { Name = "extension-field", Value = "bar" },
            };
            await r.stream.WriteHeadersAsync(infoHeaders, false);
            await r.stream.WriteHeadersAsync(DefaultStatusHeaders, false);
            await r.stream.WriteAsync(new ArraySegment<byte>(new byte[0]), true);
            await outPipe.ReadAndDiscardHeaders(1, false);
            await outPipe.ReadAndDiscardHeaders(1, false);
            await outPipe.ReadAndDiscardData(1, true, 0);
        }
        public object Parse(string value, object argument)
        {
            var headers = new List<HeaderField>();

            using (var sr = new StringReader(value)) {
                using (var sw = new StringWriter()) {
                    while (true) {
                        var line = sr.ReadLine();

                        // end of block reached, no more headers
                        if (string.IsNullOrEmpty(line)) {
                            break;
                        }

                        sw.Write(line);
                        while (true) {
                            var next = sr.Peek();

                            var isContinuation = next == Characters.Space || next == Characters.Tabulator;
                            if (isContinuation) {
                                var continuation = sr.ReadLine();
                                if (string.IsNullOrEmpty(continuation)) {
                                    break;
                                }
                                sw.Write(continuation.Trim());
                            } else {
                                break;
                            }
                        }

                        var literals = sw.ToString();
                        if (!string.IsNullOrEmpty(literals)) {
                            var header = new HeaderField();
                            sw.Clear();
                            header.Deserialize(literals);
                            headers.Add(header);
                        }
                    }
                }
            }

            return headers;
        }
Example #27
0
        public async Task ReceivingTrailersShouldUnblockDataReceptionAndPresentThem(
            bool isServer)
        {
            var inPipe  = new BufferedPipe(1024);
            var outPipe = new BufferedPipe(1024);

            var res = await StreamCreator.CreateConnectionAndStream(
                isServer, loggerProvider, inPipe, outPipe);

            var readDataTask = res.stream.ReadAllToArrayWithTimeout();

            var fh = new FrameHeader
            {
                Type     = FrameType.Data,
                Length   = 4,
                StreamId = 1,
                Flags    = (byte)0,
            };
            await inPipe.WriteFrameHeader(fh);

            await inPipe.WriteAsync(
                new ArraySegment <byte>(
                    System.Text.Encoding.ASCII.GetBytes("ABCD")));

            var trailers = new HeaderField[] {
                new HeaderField {
                    Name = "trai", Value = "ler"
                },
            };
            await inPipe.WriteHeaders(res.hEncoder, 1, true, trailers);

            var bytes = await readDataTask;

            Assert.Equal(4, bytes.Length);
            Assert.Equal("ABCD", System.Text.Encoding.ASCII.GetString(bytes));
            Assert.Equal(StreamState.HalfClosedRemote, res.stream.State);
            var rcvdTrailers = await res.stream.ReadTrailersAsync();

            Assert.Equal(trailers, rcvdTrailers);
        }
Example #28
0
        public void DynamicTable_WrapsRingBuffer_Success(int targetInsertIndex)
        {
            FieldInfo      insertIndexField = typeof(DynamicTable).GetField("_insertIndex", BindingFlags.NonPublic | BindingFlags.Instance);
            DynamicTable   table            = new DynamicTable(maxSize: 256);
            Stack <byte[]> insertedHeaders  = new Stack <byte[]>();

            // Insert into dynamic table until its insert index into its ring buffer loops back to 0.
            do
            {
                InsertOne();
            }while ((int)insertIndexField.GetValue(table) != 0);

            // Finally loop until the insert index reaches the target.
            while ((int)insertIndexField.GetValue(table) != targetInsertIndex)
            {
                InsertOne();
            }

            void InsertOne()
            {
                byte[] data = Encoding.ASCII.GetBytes($"header-{insertedHeaders.Count}");

                insertedHeaders.Push(data);
                table.Insert(data, data);
            }

            // Now check to see that we can retrieve the remaining headers.
            // Some headers will have been evacuated from the table during this process, so we don't exhaust the entire insertedHeaders stack.
            Assert.True(table.Count > 0);
            Assert.True(table.Count < insertedHeaders.Count);

            for (int i = 0; i < table.Count; ++i)
            {
                HeaderField dynamicField = table[i];
                byte[]      expectedData = insertedHeaders.Pop();

                Assert.True(expectedData.AsSpan().SequenceEqual(dynamicField.Name));
                Assert.True(expectedData.AsSpan().SequenceEqual(dynamicField.Value));
            }
        }
Example #29
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 #30
0
        public void ShouldHandleExampleC2_3OfTheSpecificationCorrectly()
        {
            var encoder = new Encoder(new Encoder.Options {
                HuffmanStrategy = HuffmanStrategy.Never,
            });
            var fields = new HeaderField[] {
                new HeaderField {
                    Name = "password", Value = "secret", Sensitive = true
                }
            };

            var result = new Buffer();

            result.AddHexString("100870617373776f726406736563726574");

            var res = EncodeToTempBuf(encoder, fields, MaxFrameSize);

            Assert.Equal(result.Bytes, res.Bytes);
            Assert.Equal(1, res.FieldCount);
            Assert.Equal(0, encoder.DynamicTableUsedSize);
            Assert.Equal(0, encoder.DynamicTableLength);
        }
Example #31
0
        public void ShouldHandleExampleC2_4OfTheSpecificationCorrectly()
        {
            var encoder = new Encoder(new Encoder.Options {
                HuffmanStrategy = HuffmanStrategy.Never,
            });
            var fields = new HeaderField[] {
                new HeaderField {
                    Name = ":method", Value = "GET", Sensitive = false
                }
            };

            var result = new Buffer();

            result.AddHexString("82");

            var res = EncodeToTempBuf(encoder, fields, MaxFrameSize);

            Assert.Equal(result.Bytes, res.Bytes);
            Assert.Equal(1, res.FieldCount);
            Assert.Equal(0, encoder.DynamicTableUsedSize);
            Assert.Equal(0, encoder.DynamicTableLength);
        }
Example #32
0
        public void Resize(int maxSize)
        {
            // TODO: What would cause us to need to grow the table size? The connection-level limit should prevent this, right?
            // Understand this better. If we do need to resize, we may want a better resize strategy.
            if (maxSize > _maxSize)
            {
                var newBuffer = new HeaderField[maxSize / HeaderField.RfcOverhead];

                for (var i = 0; i < Count; i++)
                {
                    newBuffer[i] = _buffer[i];
                }

                _buffer  = newBuffer;
                _maxSize = maxSize;
            }
            else
            {
                _maxSize = maxSize;
                EnsureAvailable(0);
            }
        }
Example #33
0
 /// <summary>
 /// Add the header field to the dynamic table.
 /// Entries are evicted from the dynamic table until the size of the table
 /// and the new header field is less than or equal to the table's capacity.
 /// If the size of the new entry is larger than the table's capacity,
 /// the dynamic table will be cleared.
 /// </summary>
 /// <param name="header">Header.</param>
 public void Add(HeaderField header)
 {
     int headerSize = header.Size;
     if (headerSize > capacity) {
         this.Clear();
         return;
     }
     while(size + headerSize > capacity) {
         this.Remove();
     }
     headerFields[head++] = header;
     size += header.Size;
     if (head == headerFields.Length) {
         head = 0;
     }
 }
Example #34
0
        /// <summary>
        /// Set the maximum size of the dynamic table.
        /// Entries are evicted from the dynamic table until the size of the table
        /// is less than or equal to the maximum size.
        /// </summary>
        /// <param name="capacity">Capacity.</param>
        public void SetCapacity(int capacity)
        {
            if (capacity < 0) {
                throw new ArgumentException("Illegal Capacity: " + capacity);
            }

            // initially capacity will be -1 so init won't return here
            if (this.capacity == capacity) {
                return;
            }
            this.capacity = capacity;

            if (capacity == 0) {
                this.Clear();
            } else {
                // initially size will be 0 so remove won't be called
                while(this.size > capacity) {
                    this.Remove();
                }
            }

            var maxEntries = capacity / HeaderField.HEADER_ENTRY_OVERHEAD;
            if (capacity % HeaderField.HEADER_ENTRY_OVERHEAD != 0) {
                maxEntries++;
            }

            // check if capacity change requires us to reallocate the array
            if (this.headerFields != null && this.headerFields.Length == maxEntries) {
                return;
            }

            var tmp = new HeaderField[maxEntries];

            // initially length will be 0 so there will be no copy
            var len = this.Length();
            var cursor = this.tail;
            for(var i = 0; i < len; i++) {
                var entry = this.headerFields[cursor++];
                tmp[i] = entry;
                if (cursor == this.headerFields.Length) {
                    cursor = 0;
                }
            }

            this.tail = 0;
            this.head = this.tail + len;
            this.headerFields = tmp;
        }