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); }
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 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++; }
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)); }