1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
/** @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()
{
if (!this->_source_vio->get_reader()) {
return Http3FrameFactory::create_null_frame();
}
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) {
uint64_t len = std::min(this->_header_block_len - this->_header_block_wrote, UINT64_C(64 * 1024));
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;
}
}
|