| /** @file |
| |
| Traffic Dump session handling encapsulation. |
| |
| @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. |
| */ |
| |
| #pragma once |
| |
| #include <atomic> |
| #include <cstdlib> |
| #include <mutex> |
| #include <string> |
| #include <string_view> |
| #include <optional> |
| |
| #include "swoc/swoc_file.h" |
| |
| #include "ts/ts.h" |
| #include "tscore/ink_inet.h" |
| |
| namespace traffic_dump |
| { |
| /** The information associated with an individual session. |
| * |
| * This class is responsible for containing the members associated with a |
| * particular session and defines the session handler callback. |
| */ |
| class SessionData |
| { |
| public: |
| /// By default, Traffic Dump logs will go into a directory called "dump". |
| static char const constexpr *const default_log_directory = "dump"; |
| /// By default, 1 out of 1000 sessions will be dumped. |
| static constexpr int64_t default_sample_pool_size = 1000; |
| /// By default, logging will stop after 10 MB have been dumped. |
| static constexpr int64_t default_max_disk_usage = 10 * 1000 * 1000; |
| /// By default, do not enforce disk utilization limits. |
| static constexpr bool default_enforce_disk_limit = false; |
| |
| private: |
| // |
| // Instance Variables |
| // |
| |
| /// Log file descriptor for this session's dump file. |
| int log_fd = -1; |
| /// The count of the currently outstanding AIO operations. |
| int aio_count = 0; |
| /// The offset of the last point written to so for in the dump file for this |
| /// session. |
| int64_t write_offset = 0; |
| /// Whether this session has been closed. |
| bool ssn_closed = false; |
| /// The filename for this session's dump file. |
| swoc::file::path log_name; |
| /// Whether the first transaction in this session has been written. |
| bool has_written_first_transaction = false; |
| /// The HTTP version specified in the client protocol stack, or empty string |
| /// if it was not specified. |
| std::string http_version_in_client_stack; |
| |
| TSCont aio_cont = nullptr; /// AIO continuation callback |
| TSCont txn_cont = nullptr; /// Transaction continuation callback |
| |
| // The following has to be recursive because the stack does not unwind |
| // between event invocations. |
| std::recursive_mutex disk_io_mutex; /// The mutex for guarding IO calls. |
| |
| // |
| // Static Variables |
| // |
| |
| // The index to be used for the TS API for storing this SessionData on a |
| // per-session basis. |
| static int session_arg_index; |
| |
| /// The rate at which to dump sessions. Every one out of sample_pool_size will |
| /// be dumped. |
| static std::atomic<int64_t> sample_pool_size; |
| /// The maximum space logs should take up before stopping the dumping of new |
| /// sessions. This is only enforced if enforce_disk_limit is true. |
| static std::atomic<int64_t> max_disk_usage; |
| /// The amount of bytes currently written to dump files. |
| static std::atomic<int64_t> disk_usage; |
| /// Whether to enforce a disk utilization limit. |
| static std::atomic<bool> enforce_disk_limit; |
| |
| /// The directory into which to put the dump files. |
| static swoc::file::path log_directory; |
| |
| /// Only sessions with this SNI will be dumped (if set). |
| static std::string sni_filter; |
| |
| /// The running counter of all sessions dumped by traffic_dump. |
| static uint64_t session_counter; |
| |
| /// Only addresses with this IP will be dumped (if set). |
| static std::optional<IpAddr> client_ip_filter; |
| |
| public: |
| SessionData(); |
| ~SessionData(); |
| |
| /** The getter for the session_arg_index value. */ |
| static int get_session_arg_index(); |
| |
| /** Initialize the cross-session values of managing sessions. |
| * |
| * @return True if initialization is successful, false otherwise. |
| */ |
| static bool init(std::string_view log_directory, bool enforce_disk_limit, int64_t max_disk_usage, int64_t sample_size, |
| std::string_view ip_filter); |
| static bool init(std::string_view log_directory, bool enforce_disk_limit, int64_t max_disk_usage, int64_t sample_size, |
| std::string_view ip_filter, std::string_view sni_filter); |
| |
| /** Set the sample_pool_size to a new value. |
| * |
| * @param[in] new_sample_size The new value to set for sample_pool_size. |
| */ |
| static void set_sample_pool_size(int64_t new_sample_size); |
| |
| /** Reset the disk usage counter to 0. */ |
| static void reset_disk_usage(); |
| |
| /** Disable disk usage enforcement. |
| * |
| * @param[in] new_max_disk_usage The new value to set for max_disk_usage. |
| */ |
| static void disable_disk_limit_enforcement(); |
| |
| /** Set the max_disk_usage to a new value. |
| * |
| * @param[in] new_max_disk_usage The new value to set for max_disk_usage. |
| */ |
| static void set_max_disk_usage(int64_t new_max_disk_usage); |
| |
| /** Get the JSON string that describes the server session stack. |
| * |
| * The server side protocol description may change on a per-transaction |
| * basis. Therefore we print this for each transaction and take an TSHttpTxn |
| * instead of a TSHttpSsn that the analogous get_client_protocol_description |
| * receives. |
| * |
| * @param[in] txnp The reference to the transaction. |
| * |
| * @return A JSON description of the server protocol stack for the |
| * transaction. |
| */ |
| std::string get_server_protocol_description(TSHttpTxn txnp); |
| |
| /** Write the string to the session's dump file. |
| * |
| * @param[in] content The content to write to the file. |
| * |
| * @return TS_SUCCESS if the write is successfully scheduled with the AIO |
| * system, TS_ERROR otherwise. |
| */ |
| int write_to_disk(std::string_view content); |
| |
| /** Write the transaction to the session's dump file. |
| * |
| * @param[in] content The transaction content to write to the file. |
| * |
| * @return TS_SUCCESS if the write is successfully scheduled with the AIO |
| * system, TS_ERROR otherwise. |
| */ |
| int write_transaction_to_disk(std::string_view content); |
| |
| /** The HTTP version specified in the client-side protocol stack. |
| * |
| * The client protocol stack is obtained at session negotiation, before HTTP |
| * traffic is passed. So it may contain stack information if it was |
| * negotiated in the TLS handshake, as is often the case with HTTP/2, but it |
| * may not. This function returns whether the protocol stack contained HTTP |
| * information or not. |
| * |
| * @return The HTTP version in the client stack or empty string if it was not |
| * specified. |
| */ |
| std::string get_http_version_in_client_stack() const; |
| |
| private: |
| /** Write the string to the session's dump file. |
| * |
| * This assumes that the caller acquired the required AIO lock. |
| * |
| * @param[in] content The content to write to the file. |
| * |
| * @return TS_SUCCESS if the write is successfully scheduled with the AIO |
| * system, TS_ERROR otherwise. |
| */ |
| int write_to_disk_no_lock(std::string_view content); |
| |
| using get_protocol_stack_f = std::function<TSReturnCode(int, const char **, int *)>; |
| using get_tls_description_f = std::function<std::string()>; |
| using handle_http_version_f = std::function<void(std::string_view)>; |
| |
| /** Create the protocol stack for a session. |
| * |
| * This function encapsulates the logic common between the client-side and |
| * server-side logic for populating a protocol stack. |
| * |
| * @param[in] get_protocol_stack The function to use to populate a protocol |
| * stack. |
| * |
| * @param[in] get_tls_node The function to use to populate the tls node. |
| * |
| * @param[in] handle_http_version A function that performs arbitrary logic |
| * given the HTTP/2 protocol version. |
| * |
| * @return The description of the protocol stack and True if the stack |
| * contained an HTTP description, false otherwise. |
| */ |
| std::string get_protocol_stack_helper(const get_protocol_stack_f &get_protocol_stack, const get_tls_description_f &get_tls_node, |
| const handle_http_version_f &handle_http_version); |
| |
| /** Determine whether the user configured IP filter indicates this transaction |
| * should not be dumped. |
| * |
| * @note This also does some validity verification on the IP, making sure it is |
| * v4 or v6, and returns true (i.e., it should be filtered out) if it does not |
| * match these checks. These checks are required in order to perform the IP |
| * filtering logic. This function will only return true if the client has |
| * enabled client filtering. |
| * |
| * @param[in] session_client_ip The session's client address. |
| * |
| * @return True if the provided address should not be dumped per the user's |
| * configuration, false otherwise. |
| */ |
| static bool is_filtered_out(const sockaddr *session_client_ip); |
| |
| /** Get the JSON string that describes the client session stack. |
| * |
| * @param[in] ssnp The reference to the client session. |
| * |
| * @return A description of the client protocol stack and True if the stack |
| * contained an HTTP description, false otherwise. |
| */ |
| std::string get_client_protocol_description(TSHttpSsn ssnp); |
| |
| /** The handler callback for when async IO is done. Used for cleanup. */ |
| static int session_aio_handler(TSCont contp, TSEvent event, void *edata); |
| |
| /** The handler callback for session events. */ |
| static int global_session_handler(TSCont contp, TSEvent event, void *edata); |
| }; |
| |
| } // namespace traffic_dump |