blob: 422cb56aca707902a548825a8ae88406d0cefba4 [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.
*/
/****************************************************************************
HdrTSOnly.cc
Description:
IRIX compiler is rather annoying and likes to use symbols from inline
code that is not called in the file. Thus to make our libhdrs.a
library link with traffic_manager and test_header, we can't
include IOBuffer.h in any file where the corresponding object file
gets linked in for these two targets. Thus HdrTSOnly.cc is where
we put the functions that only traffic_server uses since they
need to know about IOBuffers.
****************************************************************************/
#include "tscore/ink_platform.h"
#include "HTTP.h"
#include "P_EventSystem.h"
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
ParseResult
HTTPHdr::parse_req(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof, bool strict_uri_parsing,
size_t max_request_line_size, size_t max_hdr_field_size)
{
const char *start;
const char *tmp;
const char *end;
int used;
ink_assert(valid());
ink_assert(m_http->m_polarity == HTTP_TYPE_REQUEST);
ParseResult state = PARSE_RESULT_CONT;
*bytes_used = 0;
do {
int64_t b_avail = r->block_read_avail();
if (b_avail <= 0 && eof == false) {
break;
}
tmp = start = r->start();
end = start + b_avail;
int heap_slot = m_heap->attach_block(r->get_current_block(), start);
m_heap->lock_ronly_str_heap(heap_slot);
state = http_parser_parse_req(parser, m_heap, m_http, &tmp, end, false, eof, strict_uri_parsing, max_request_line_size,
max_hdr_field_size);
m_heap->set_ronly_str_heap_end(heap_slot, tmp);
m_heap->unlock_ronly_str_heap(heap_slot);
used = static_cast<int>(tmp - start);
r->consume(used);
*bytes_used += used;
} while (state == PARSE_RESULT_CONT);
return state;
}
ParseResult
HTTPHdr::parse_resp(HTTPParser *parser, IOBufferReader *r, int *bytes_used, bool eof)
{
const char *start;
const char *tmp;
const char *end;
int used;
ink_assert(valid());
ink_assert(m_http->m_polarity == HTTP_TYPE_RESPONSE);
ParseResult state = PARSE_RESULT_CONT;
*bytes_used = 0;
do {
int64_t b_avail = r->block_read_avail();
tmp = start = r->start();
// No data currently available.
if (b_avail <= 0) {
if (eof == false) { // more data may arrive later, return CONTINUE state.
break;
} else if (nullptr == start) {
// EOF on empty MIOBuffer - that's a fail, don't bother with parsing.
// (otherwise will attempt to attach_block a non-existent block)
state = PARSE_RESULT_ERROR;
break;
}
}
end = start + b_avail;
int heap_slot = m_heap->attach_block(r->get_current_block(), start);
m_heap->lock_ronly_str_heap(heap_slot);
state = http_parser_parse_resp(parser, m_heap, m_http, &tmp, end, false, eof);
m_heap->set_ronly_str_heap_end(heap_slot, tmp);
m_heap->unlock_ronly_str_heap(heap_slot);
used = static_cast<int>(tmp - start);
r->consume(used);
*bytes_used += used;
} while (state == PARSE_RESULT_CONT);
return state;
}
// void HdrHeap::set_ronly_str_heap_end(int slot)
//
// The end pointer is where the header parser stopped parsing
// so that we don't get extraneous space in the block
// that then has to get marshalled (INKqa07409)
//
// NOTE: the shortening the block relies on the fact that
// IOBuffers are write once. It's therefore not possible
// that a previous call actually used more the block than
// the current call which would mean we can't shorten the block
//
void
HdrHeap::set_ronly_str_heap_end(int slot, const char *end)
{
ink_assert(m_ronly_heap[slot].m_heap_start != nullptr);
ink_assert(m_ronly_heap[slot].m_heap_start <= end);
ink_assert(end <= m_ronly_heap[slot].m_heap_start + m_ronly_heap[slot].m_heap_len);
m_ronly_heap[slot].m_heap_len = static_cast<int>(end - m_ronly_heap[slot].m_heap_start);
}
// void HdrHeap::attach_block(IOBufferBlock* b, const char* use_start)
//
// Attachs data from an IOBuffer block to
// as a read-only string heap. Looks through existing
// to expand an existing string heap entry if necessary
//
// Because the block may contain data at the front of it that
// we don't want (and will end up getting marshalled)
// use_start specificies where we start using the block (INKqa07409)
//
int
HdrHeap::attach_block(IOBufferBlock *b, const char *use_start)
{
ink_assert(m_writeable);
RETRY:
// It's my contention that since heaps are add to the first available slot, one you find an empty
// slot it's not possible that a heap ptr for this block exists in a later slot
for (auto &heap : m_ronly_heap) {
if (heap.m_heap_start == nullptr) {
// Add block to heap in this slot
heap.m_heap_start = static_cast<char const *>(use_start);
heap.m_heap_len = static_cast<int>(b->end() - b->start());
heap.m_ref_count_ptr = b->data.object();
// printf("Attaching block at %X for %d in slot %d\n",
// m_ronly_heap[i].m_heap_start,
// m_ronly_heap[i].m_heap_len,
// i);
return &heap - m_ronly_heap;
} else if (heap.m_heap_start == b->buf()) {
// This block is already on the heap so just extend
// it's range
heap.m_heap_len = static_cast<int>(b->end() - b->buf());
// printf("Extending block at %X to %d in slot %d\n",
// m_ronly_heap[i].m_heap_start,
// m_ronly_heap[i].m_heap_len,
// i);
return &heap - m_ronly_heap;
}
}
// We didn't find an open block slot so we'll have to create one
coalesce_str_heaps();
goto RETRY;
}