blob: b69f298c0924a93384c81bccacc13d8c2b966783 [file] [log] [blame]
/** @file
*
* A brief file description
*
* @section license License
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Http3HeaderFramer.h"
#include "I_VIO.h"
#include "HTTP.h"
#include "HTTP2.h"
#include "Http3Frame.h"
#include "Http3Transaction.h"
Http3HeaderFramer::Http3HeaderFramer(Http3Transaction *transaction, VIO *source, QPACK *qpack, uint64_t stream_id)
: _transaction(transaction), _source_vio(source), _qpack(qpack), _stream_id(stream_id)
{
http_parser_init(&this->_http_parser);
}
Http3FrameUPtr
Http3HeaderFramer::generate_frame(uint16_t max_size)
{
ink_assert(!this->_transaction->is_response_header_sent());
if (!this->_header_block) {
// this->_header_block will be filled if it is ready
this->_generate_header_block();
}
if (this->_header_block) {
// Create frames on demand base on max_size since we don't know how much we can write now
uint64_t len = std::min(this->_header_block_len - this->_header_block_wrote, static_cast<uint64_t>(max_size));
Http3FrameUPtr frame = Http3FrameFactory::create_headers_frame(this->_header_block_reader, len);
this->_header_block_wrote += len;
if (this->_header_block_len == this->_header_block_wrote) {
this->_sent_all_data = true;
}
return frame;
} else {
return Http3FrameFactory::create_null_frame();
}
}
bool
Http3HeaderFramer::is_done() const
{
return this->_sent_all_data;
}
void
Http3HeaderFramer::_convert_header_from_1_1_to_3(HTTPHdr *hdrs)
{
http2_convert_header_from_1_1_to_2(hdrs);
}
void
Http3HeaderFramer::_generate_header_block()
{
// Prase response header and generate header block
int bytes_used = 0;
ParseResult parse_result = PARSE_RESULT_ERROR;
if (this->_transaction->direction() == NET_VCONNECTION_OUT) {
this->_header.create(HTTP_TYPE_REQUEST);
http2_init_pseudo_headers(this->_header);
parse_result = this->_header.parse_req(&this->_http_parser, this->_source_vio->get_reader(), &bytes_used, false);
} else {
this->_header.create(HTTP_TYPE_RESPONSE);
http2_init_pseudo_headers(this->_header);
parse_result = this->_header.parse_resp(&this->_http_parser, this->_source_vio->get_reader(), &bytes_used, false);
}
this->_source_vio->ndone += bytes_used;
switch (parse_result) {
case PARSE_RESULT_DONE: {
this->_convert_header_from_1_1_to_3(&this->_header);
this->_header_block = new_MIOBuffer(BUFFER_SIZE_INDEX_32K);
this->_header_block_reader = this->_header_block->alloc_reader();
this->_qpack->encode(this->_stream_id, this->_header, this->_header_block, this->_header_block_len);
break;
}
case PARSE_RESULT_CONT:
break;
default:
Debug("http3_trans", "Ignore invalid headers");
break;
}
}