Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.. 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:: ../../../common.defs

.. default-domain:: c

TSHttpTxnClientStreamIdGet
**************************

Synopsis
========

.. code-block:: cpp

#include <ts/ts.h>

.. function:: TSReturnCode TSHttpTxnClientStreamIdGet(TSHttpTxn txnp, uint64_t* stream_id)

Description
===========

Retrieve the stream identification for the HTTP stream of which the provided
transaction is a part. The resultant stream identifier is populated in the
``stream_id`` output parameter.

This interface currently only supports HTTP/2 streams. See RFC 7540 section
5.1.1 for details concerning HTTP/2 stream identifiers.

This API returns an error if the provided transaction is not an HTTP/2
transaction.

See Also
========

:doc:`TSHttpTxnClientStreamPriorityGet.en`
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.. 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:: ../../../common.defs

.. default-domain:: c

TSHttpTxnClientStreamPriorityGet
********************************

Synopsis
========

.. code-block:: cpp

#include <ts/ts.h>

.. function:: TSReturnCode TSHttpTxnClientStreamPriorityGet(TSHttpTxn txnp, TSHttpPriority* priority)

Description
===========

Retrieve the priority information for the HTTP stream associated with the
provided transaction. The resultant priority information is populated in the
``priority`` output variable. The ``TSHttpPriority`` type is designed to be
agnostic of the various HTTP protocol versions that support HTTP streams. The
user should pass a pointer casted to ``TSHttpPriority`` from a previously
allocated ``TSHttp2Priority`` structure. This design anticipates future support
for HTTP versions that support streams, such as HTTP/3.

The ``TSHttp2Priority`` structure has the following declaration:

.. code-block:: cpp

typedef struct {
uint8_t priority_type; /** HTTP_PROTOCOL_TYPE_HTTP_2 */
int32_t stream_dependency;
uint8_t weight;
} TSHttp2Priority;

In a call to ``TSHttpTxnClientStreamPriorityGet``, the dependency and weight
will be populated in the ``stream_dependency`` and ``weight`` members,
respectively. If the stream associated with the given transaction has no
dependency, then the ``stream_dependency`` output parameter will be populated
with ``-1`` and the value of ``weight`` will be meaningless. See RFC 7540
section 5.3 for details concerning HTTP/2 stream priority.

This API returns an error if the provided transaction is not an HTTP/2
transaction.

See Also
========

:doc:`TSHttpTxnClientStreamIdGet.en`
38 changes: 38 additions & 0 deletions include/ts/apidefs.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,44 @@ typedef enum {
TS_USER_ARGS_COUNT ///< Fake enum, # of valid entries.
} TSUserArgType;

/** An enumeration of HTTP version types for the priority functions that behave
* differently across HTTP protocols. */
typedef enum {
HTTP_PRIORITY_TYPE_HTTP_UNSPECIFIED = 1,
HTTP_PRIORITY_TYPE_HTTP_2,
HTTP_PRIORITY_TYPE_HTTP_3,
} TSHttpPriorityType;

/** The abstract type of the various HTTP priority implementations. */
typedef struct {
/** The reference to the concrete HTTP priority implementation. This will be
* a value from TSHttpPriorityType. */
uint8_t priority_type;
/** The space allocated for the concrete priority implementation.
*
* Note that this has to take padding into account. There is a static_assert
* in InkAPI.cc to verify that TSHttpPriority is at least as large as
* TSHttp2Priority. As other structures are added that are represented by
* TSHttpPriority add more static_asserts to verify that TSHttpPriority is as
* large as it needs to be.
*/
uint8_t data[7];
} TSHttpPriority;

/** A structure for HTTP/2 priority.
*
* For an explanation of these terms with respect to HTTP/2, see RFC 7540,
* section 5.3.
*/
typedef struct {
uint8_t priority_type; /** HTTP_PROTOCOL_TYPE_HTTP_2 */
uint8_t weight;
/** The stream dependency. Per spec, see RFC 7540 section 6.2, this is 31
* bits. We use a signed 32 bit stucture to store either a valid dependency
* or -1 if the stream has no dependency. */
int32_t stream_dependency;
} TSHttp2Priority;

typedef struct tsapi_file *TSFile;

typedef struct tsapi_mloc *TSMLoc;
Expand Down
26 changes: 26 additions & 0 deletions include/ts/ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,32 @@ tsapi TSIOBufferReader TSHttpTxnPostBufferReaderGet(TSHttpTxn txnp);
*/
tsapi TSReturnCode TSHttpTxnServerPush(TSHttpTxn txnp, const char *url, int url_len);

/** Retrieve the client side stream id for the stream of which the
* provided transaction is a part.
*
* @param[in] txnp The Transaction for which the stream id should be retrieved.
* @param[out] stream_id The stream id for this transaction.
*
* @return TS_ERROR if a stream id cannot be retrieved for the given
* transaction given its protocol. For instance, if txnp is an HTTP/1.1
* transaction, then a TS_ERROR will be returned because HTTP/1.1 does not
* implement streams.
*/
tsapi TSReturnCode TSHttpTxnClientStreamIdGet(TSHttpTxn txnp, uint64_t *stream_id);

/** Retrieve the client side priority for the stream of which the
* provided transaction is a part.
*
* @param[in] txnp The Transaction for which the stream id should be retrieved.
* @param[out] priority The priority for the stream in this transaction.
*
* @return TS_ERROR if a priority cannot be retrieved for the given
* transaction given its protocol. For instance, if txnp is an HTTP/1.1
* transaction, then a TS_ERROR will be returned because HTTP/1.1 does not
* implement stream priorities.
*/
tsapi TSReturnCode TSHttpTxnClientStreamPriorityGet(TSHttpTxn txnp, TSHttpPriority *priority);

#ifdef __cplusplus
}
#endif /* __cplusplus */
133 changes: 68 additions & 65 deletions plugins/experimental/traffic_dump/session_data.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,27 +46,32 @@ char const constexpr *const json_closing = "]}]}";
/**
* A mapping from IP_PROTO_TAG to the string describing the JSON protocol node.
*/
std::unordered_map<std::string, std::string> tag_to_node = {
{std::string(IP_PROTO_TAG_IPV4), R"("name":"ip","version":"4")"},
{std::string(IP_PROTO_TAG_IPV6), R"("name":"ip","version":"6")"},
std::unordered_map<std::string_view, std::string> tag_to_node = {
{IP_PROTO_TAG_IPV4, R"("name":"ip","version":"4")"},
{IP_PROTO_TAG_IPV6, R"("name":"ip","version":"6")"},

{std::string(IP_PROTO_TAG_TCP), R"("name":"tcp")"},
{std::string(IP_PROTO_TAG_UDP), R"("name":"udp")"},
{IP_PROTO_TAG_TCP, R"("name":"tcp")"},
{IP_PROTO_TAG_UDP, R"("name":"udp")"},

{std::string(IP_PROTO_TAG_QUIC), R"("name:":"quic")"},
{IP_PROTO_TAG_QUIC, R"("name:":"quic")"},

{std::string(IP_PROTO_TAG_TLS_1_0), R"("name":"tls","version":"1.0")"},
{std::string(IP_PROTO_TAG_TLS_1_1), R"("name":"tls","version":"1.1")"},
{std::string(IP_PROTO_TAG_TLS_1_2), R"("name":"tls","version":"1.2")"},
{std::string(IP_PROTO_TAG_TLS_1_3), R"("name":"tls","version":"1.3")"},
{IP_PROTO_TAG_TLS_1_0, R"("name":"tls","version":"1.0")"},
{IP_PROTO_TAG_TLS_1_1, R"("name":"tls","version":"1.1")"},
{IP_PROTO_TAG_TLS_1_2, R"("name":"tls","version":"1.2")"},
{IP_PROTO_TAG_TLS_1_3, R"("name":"tls","version":"1.3")"},

{std::string(IP_PROTO_TAG_HTTP_0_9), R"("name":"http","version":"0.9")"},
{std::string(IP_PROTO_TAG_HTTP_1_0), R"("name":"http","version":"1.0")"},
{std::string(IP_PROTO_TAG_HTTP_1_1), R"("name":"http","version":"1.1")"},
{std::string(IP_PROTO_TAG_HTTP_2_0), R"("name":"http","version":"2")"},
{IP_PROTO_TAG_HTTP_0_9, R"("name":"http","version":"0.9")"},
{IP_PROTO_TAG_HTTP_1_0, R"("name":"http","version":"1.0")"},
{IP_PROTO_TAG_HTTP_1_1, R"("name":"http","version":"1.1")"},
{IP_PROTO_TAG_HTTP_2_0, R"("name":"http","version":"2")"},

{std::string(IP_PROTO_TAG_HTTP_QUIC), R"("name":"http","version":"0.9")"},
{std::string(IP_PROTO_TAG_HTTP_3), R"("name":"http","version":"3")"},
{IP_PROTO_TAG_HTTP_QUIC, R"("name":"http","version":"0.9")"},
{IP_PROTO_TAG_HTTP_3, R"("name":"http","version":"3")"},
};

std::unordered_map<std::string_view, std::string> http_tag_to_version = {
{IP_PROTO_TAG_HTTP_0_9, "0.9"}, {IP_PROTO_TAG_HTTP_1_0, "1.0"}, {IP_PROTO_TAG_HTTP_1_1, "1.1"},
{IP_PROTO_TAG_HTTP_2_0, "2"}, {IP_PROTO_TAG_HTTP_QUIC, "0.9"}, {IP_PROTO_TAG_HTTP_3, "3"},
};

/** Create a TLS characteristics node.
Expand Down Expand Up @@ -137,53 +142,6 @@ get_server_tls_description(TSHttpTxn txnp)
TSVConn server_ssn_vc = TSHttpTxnServerVConnGet(txnp);
return get_tls_description_helper(server_ssn_vc);
}

using get_protocol_stack_f = std::function<TSReturnCode(int, const char **, int *)>;
using get_tls_description_f = std::function<std::string()>;

/** 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.
*
* @return The description of the protocol stack.
*/
std::string
get_protocol_stack_helper(const get_protocol_stack_f &get_protocol_stack, const get_tls_description_f &get_tls_node)
{
std::ostringstream protocol_description;
protocol_description << R"("protocol":[)";
char const *protocol[10];
int count = -1;
TSAssert(TS_SUCCESS == get_protocol_stack(10, protocol, &count));
bool is_first_printed_protocol = true;
for (int i = 0; i < count; ++i) {
std::string_view protocol_string(protocol[i]);
if (!is_first_printed_protocol) {
protocol_description << ",";
}
is_first_printed_protocol = false;
if (protocol_string.find("tls") != std::string::npos) {
protocol_description << '{' << get_tls_node() << '}';
} else {
auto search = tag_to_node.find(std::string(protocol_string));
if (search == tag_to_node.end()) {
// If the tag from get_protocol_stack is not in our list, then our
// tag_to_node has not been updated with the new tag. Update tag_to_node.
TSError("[%s] Missing tag node description: '%.*s'", traffic_dump::debug_tag, static_cast<int>(protocol_string.length()),
protocol_string.data());
protocol_description << R"({"name":")" << protocol_string << R"("})";
} else {
protocol_description << '{' << search->second << '}';
}
}
}
protocol_description << "]"; // Close the "protocol" sequence.
return protocol_description.str();
}
} // namespace

namespace traffic_dump
Expand Down Expand Up @@ -254,6 +212,46 @@ SessionData::init(std::string_view log_directory, int64_t max_disk_usage, int64_
return true;
}

std::string
SessionData::get_protocol_stack_helper(const get_protocol_stack_f &get_protocol_stack, const get_tls_description_f &get_tls_node)
{
std::ostringstream protocol_description;
protocol_description << R"("protocol":[)";
char const *protocol[10];
int count = -1;
TSAssert(TS_SUCCESS == get_protocol_stack(10, protocol, &count));
bool is_first_printed_protocol = true;
for (int i = 0; i < count; ++i) {
std::string_view protocol_string(protocol[i]);
if (!is_first_printed_protocol) {
protocol_description << ",";
}
is_first_printed_protocol = false;
if (protocol_string.find("tls") != std::string::npos) {
protocol_description << '{' << get_tls_node() << '}';
} else {
auto search = tag_to_node.find(std::string(protocol_string));
if (search == tag_to_node.end()) {
// If the tag from get_protocol_stack is not in our list, then our
// tag_to_node has not been updated with the new tag. Update tag_to_node.
TSError("[%s] Missing tag node description: '%.*s'", traffic_dump::debug_tag, static_cast<int>(protocol_string.length()),
protocol_string.data());
protocol_description << R"({"name":")" << protocol_string << R"("})";
} else {
protocol_description << '{' << search->second << '}';
}

// See whether an HTTP version is provided. If so, record it.
auto const it = http_tag_to_version.find(std::string(protocol_string));
if (it != http_tag_to_version.end()) {
this->http_version_in_client_stack = it->second;
}
}
}
protocol_description << "]"; // Close the "protocol" sequence.
return protocol_description.str();
}

std::string
SessionData::get_client_protocol_description(TSHttpSsn client_ssnp)
{
Expand Down Expand Up @@ -342,6 +340,12 @@ SessionData::write_transaction_to_disk(std::string_view content)
return result;
}

std::string
SessionData::get_http_version_in_client_stack() const
{
return http_version_in_client_stack;
}

int
SessionData::session_aio_handler(TSCont contp, TSEvent event, void *edata)
{
Expand Down Expand Up @@ -437,8 +441,7 @@ SessionData::global_session_handler(TSCont contp, TSEvent event, void *edata)

// "protocol":
// This is the protocol stack for the client side of the session.
std::string protocol_description = get_client_protocol_description(ssnp);

std::string protocol_description = ssnData->get_client_protocol_description(ssnp);
std::string beginning = R"({"meta":{"version":"1.0"},"sessions":[{)" + protocol_description + R"(,"connection-time":)" +
std::to_string(start.count()) + R"(,"transactions":[)";

Expand Down
Loading