| /** @file | |
| 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. | |
| */ | |
| #pragma once | |
| #include "ts/ts.h" | |
| #include "HttpHeader.h" | |
| #include "Range.h" | |
| #include "Stage.h" | |
| #include <netinet/in.h> | |
| #include <string> | |
| #include <unordered_map> | |
| struct Config; | |
| enum BlockState { | |
| Pending, // waiting for response | |
| Active, // processing current block | |
| PendingRef, // waiting for reference refetch response | |
| ActiveRef, // processing current reference refetch | |
| Done, | |
| Passthru, // non 206 response passthru | |
| Fail, | |
| }; | |
| struct Data { | |
| Data(Data const &) = delete; | |
| Data &operator=(Data const &) = delete; | |
| Config *const m_config; | |
| sockaddr_storage m_client_ip; | |
| // cached effective URL for use during async intercept processing | |
| std::string m_effective_url; | |
| // for pristine/effective url coming in | |
| TSMBuffer m_urlbuf{nullptr}; | |
| TSMLoc m_urlloc{nullptr}; | |
| char m_hostname[8192]; | |
| int m_hostlen{0}; | |
| // best identifier headers, initially from reference slice | |
| char m_etag[8192]; | |
| int m_etaglen{0}; | |
| char m_lastmodified[33]; | |
| int m_lastmodifiedlen{0}; | |
| int64_t m_contentlen{-1}; | |
| TSHttpStatus m_statustype{TS_HTTP_STATUS_NONE}; // 200 or 206 | |
| const char *m_method_type{nullptr}; // type of header request | |
| Range m_req_range; // converted to half open interval | |
| int64_t m_blocknum{-1}; // block number to work on, -1 bad/stop | |
| int64_t m_blockexpected{0}; // body bytes expected | |
| int64_t m_blockskip{0}; // number of bytes to skip in this block | |
| int64_t m_blockconsumed{0}; // body bytes consumed | |
| int64_t m_purge_hits{0}; // blocks a purge actually removed | |
| int m_purge_misses{0}; // consecutive uncached blocks the walk has seen | |
| int m_purge_miss_bound{0}; // from the config or the request header | |
| TSHttpStatus m_purge_error{TS_HTTP_STATUS_NONE}; // block failure that ended the walk | |
| BlockState m_blockstate{Pending}; // is there an active slice block | |
| int64_t m_bytestosend{0}; // header + content bytes to send | |
| int64_t m_bytessent{0}; // number of bytes written to the client | |
| // default buffer size and water mark | |
| TSIOBufferSizeIndex m_buffer_index{TS_IOBUFFER_SIZE_INDEX_32K}; | |
| TSIOBufferWaterMark m_buffer_water_mark{TS_IOBUFFER_WATER_MARK_PLUGIN_VC_DEFAULT}; | |
| bool m_server_block_header_parsed{false}; | |
| bool m_server_first_header_parsed{false}; | |
| Stage m_upstream; | |
| Stage m_dnstream; | |
| bool m_prefetchable{false}; | |
| int64_t m_prefetch_hwm{-1}; // highest block this request has scheduled for prefetch | |
| HdrMgr m_req_hdrmgr; // manager for server request | |
| HdrMgr m_resp_hdrmgr; // manager for client response | |
| TSHttpParser m_http_parser{nullptr}; //!< cached for reuse | |
| explicit Data(Config *const config) : m_config(config) | |
| { | |
| m_hostname[0] = '\0'; | |
| m_etag[0] = '\0'; | |
| m_lastmodified[0] = '\0'; | |
| memset(&m_client_ip, 0, sizeof(m_client_ip)); | |
| } | |
| // HEAD only; a purge sends just a header too but never reaches the transfer path | |
| bool | |
| onlyHeader() const | |
| { | |
| return m_method_type == TS_HTTP_METHOD_HEAD; | |
| } | |
| bool | |
| is_purge() const | |
| { | |
| return m_method_type == TS_HTTP_METHOD_PURGE; | |
| } | |
| // The purge range, closed against the object length once known. m_req_range | |
| // stays as sent so a longer extent can widen the walk; a clamp could only shrink. | |
| Range | |
| purge_range() const | |
| { | |
| return (m_contentlen < 0) ? m_req_range : m_req_range.intersectedWith(Range(0, m_contentlen)); | |
| } | |
| ~Data() | |
| { | |
| if (nullptr != m_urlbuf) { | |
| if (nullptr != m_urlloc) { | |
| TSHandleMLocRelease(m_urlbuf, TS_NULL_MLOC, m_urlloc); | |
| m_urlloc = nullptr; | |
| } | |
| TSMBufferDestroy(m_urlbuf); | |
| m_urlbuf = nullptr; | |
| } | |
| if (nullptr != m_http_parser) { | |
| TSHttpParserDestroy(m_http_parser); | |
| m_http_parser = nullptr; | |
| } | |
| } | |
| }; |