Coverage Report

Created: 2026-10-31 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/http/HttpUserAgent.h
Line
Count
Source
1
/** @file
2
3
  A brief file description
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
 */
23
24
#pragma once
25
26
#include "proxy/http/HttpVCTable.h"
27
#include "proxy/Milestones.h"
28
29
#include "iocore/eventsystem/IOBuffer.h"
30
#include "iocore/net/TLSALPNSupport.h"
31
#include "proxy/ProxyTransaction.h"
32
#include "records/RecHttp.h"
33
#include "iocore/net/TLSBasicSupport.h"
34
#include "iocore/net/TLSEarlyDataSupport.h"
35
#include "iocore/net/TLSSessionResumptionSupport.h"
36
#include "tscore/ink_assert.h"
37
38
#include <string>
39
40
struct ClientTransactionInfo {
41
  int id{-1};
42
  int priority_weight{-1};
43
  int priority_dependence{-1};
44
};
45
46
struct ClientConnectionInfo {
47
  bool tcp_reused{false};
48
  bool ssl_reused{false};
49
  bool connection_is_ssl{false};
50
  int  ssl_resumption_type{0}; // 0=no resumption, 1=session cache, 2=session ticket
51
52
  char const *protocol{"-"};
53
  char const *sec_protocol{"-"};
54
  char const *cipher_suite{"-"};
55
  char const *curve{"-"};
56
  std::string security_group{"-"};
57
58
  int alpn_id{SessionProtocolNameRegistry::INVALID};
59
60
  // TLS handshake bytes (rx = received from client, tx = sent to client)
61
  uint64_t tls_handshake_bytes_rx{0};
62
  uint64_t tls_handshake_bytes_tx{0};
63
  size_t   tls_early_data_len{0};
64
};
65
66
class HttpUserAgent
67
{
68
public:
69
  HttpVCTableEntry *get_entry() const;
70
  void              set_entry(HttpVCTableEntry *entry);
71
72
  IOBufferReader *get_raw_buffer_reader();
73
  void            set_raw_buffer_reader(IOBufferReader *raw_buffer_reader);
74
75
  ProxyTransaction *get_txn() const;
76
  void              set_txn(ProxyTransaction *txn, TransactionMilestones &milestones);
77
78
  int64_t get_client_connection_id() const;
79
80
  int get_client_transaction_id() const;
81
82
  int get_client_transaction_priority_weight() const;
83
84
  int get_client_transaction_priority_dependence() const;
85
86
  bool get_client_tcp_reused() const;
87
88
  bool get_client_ssl_reused() const;
89
90
  int get_client_ssl_resumption_type() const;
91
92
  bool get_client_connection_is_ssl() const;
93
94
  char const *get_client_protocol() const;
95
96
  char const *get_client_sec_protocol() const;
97
98
  char const *get_client_cipher_suite() const;
99
100
  char const *get_client_curve() const;
101
102
  char const *get_client_security_group() const;
103
104
  int get_client_alpn_id() const;
105
106
  uint64_t get_client_tls_handshake_bytes_rx() const;
107
108
  uint64_t get_client_tls_handshake_bytes_tx() const;
109
110
  size_t get_client_tls_early_data_len() const;
111
112
private:
113
  HttpVCTableEntry *m_entry{nullptr};
114
  IOBufferReader   *m_raw_buffer_reader{nullptr};
115
  ProxyTransaction *m_txn{nullptr};
116
117
  ClientConnectionInfo m_conn_info{};
118
119
  int64_t               m_client_connection_id{-1};
120
  ClientTransactionInfo m_txn_info{};
121
122
  void save_transaction_info();
123
};
124
125
inline HttpVCTableEntry *
126
HttpUserAgent::get_entry() const
127
0
{
128
0
  return m_entry;
129
0
}
130
131
inline void
132
HttpUserAgent::set_entry(HttpVCTableEntry *entry)
133
0
{
134
0
  m_entry = entry;
135
0
}
136
137
inline IOBufferReader *
138
HttpUserAgent::get_raw_buffer_reader()
139
0
{
140
0
  return m_raw_buffer_reader;
141
0
}
142
143
inline void
144
HttpUserAgent::set_raw_buffer_reader(IOBufferReader *raw_buffer_reader)
145
0
{
146
0
  m_raw_buffer_reader = raw_buffer_reader;
147
0
}
148
149
inline ProxyTransaction *
150
HttpUserAgent::get_txn() const
151
0
{
152
0
  return m_txn;
153
0
}
154
155
inline void
156
HttpUserAgent::set_txn(ProxyTransaction *txn, TransactionMilestones &milestones)
157
0
{
158
0
  m_txn = txn;
159
160
  // It seems to be possible that the m_txn pointer will go stale before log
161
  // entries for this HTTP transaction are generated. Therefore, collect
162
  // information that may be needed for logging.
163
0
  this->save_transaction_info();
164
0
  if (auto p{txn->get_proxy_ssn()}; p) {
165
0
    m_client_connection_id = p->connection_id();
166
0
  }
167
168
0
  m_conn_info.tcp_reused = !txn->is_first_transaction();
169
170
0
  auto netvc{txn->get_netvc()};
171
172
0
  if (auto tbs = netvc->get_service<TLSBasicSupport>()) {
173
0
    m_conn_info.connection_is_ssl = true;
174
0
    if (auto sec_protocol{tbs->get_tls_protocol_name()}; sec_protocol) {
175
0
      m_conn_info.sec_protocol = sec_protocol;
176
0
    } else {
177
0
      m_conn_info.sec_protocol = "-";
178
0
    }
179
0
    if (auto cipher{tbs->get_tls_cipher_suite()}; cipher) {
180
0
      m_conn_info.cipher_suite = cipher;
181
0
    } else {
182
0
      m_conn_info.cipher_suite = "-";
183
0
    }
184
0
    if (auto curve{tbs->get_tls_curve()}; curve) {
185
0
      m_conn_info.curve = curve;
186
0
    } else {
187
0
      m_conn_info.curve = "-";
188
0
    }
189
190
0
    if (auto group{tbs->get_tls_group()}; !group.empty()) {
191
0
      m_conn_info.security_group = group;
192
0
    } else {
193
0
      m_conn_info.security_group = '-';
194
0
    }
195
196
0
    if (!m_conn_info.tcp_reused) {
197
      // Copy along the TLS handshake timings
198
0
      milestones[TS_MILESTONE_TLS_HANDSHAKE_START] = tbs->get_tls_handshake_begin_time();
199
0
      milestones[TS_MILESTONE_TLS_HANDSHAKE_END]   = tbs->get_tls_handshake_end_time();
200
0
    }
201
0
    tbs->get_tls_handshake_bytes(m_conn_info.tls_handshake_bytes_rx, m_conn_info.tls_handshake_bytes_tx);
202
0
  }
203
204
0
  if (auto eds = netvc->get_service<TLSEarlyDataSupport>()) {
205
0
    m_conn_info.tls_early_data_len = eds->get_early_data_len();
206
0
  }
207
208
0
  if (auto as = netvc->get_service<ALPNSupport>()) {
209
0
    m_conn_info.alpn_id = as->get_negotiated_protocol_id();
210
0
  }
211
212
0
  if (auto tsrs = netvc->get_service<TLSSessionResumptionSupport>()) {
213
0
    m_conn_info.ssl_reused = tsrs->getIsResumedSSLSession();
214
215
0
    if (m_conn_info.ssl_reused) {
216
0
      if (tsrs->getIsResumedFromSessionCache()) {
217
0
        m_conn_info.ssl_resumption_type = 1;
218
0
      } else if (tsrs->getIsResumedFromSessionTicket()) {
219
0
        m_conn_info.ssl_resumption_type = 2;
220
0
      } else {
221
        // This should not happen if ssl_reused is true.
222
0
        ink_assert(!"ssl_resumption_type should be set for an SSL reused session");
223
0
        m_conn_info.ssl_resumption_type = 0;
224
0
      }
225
0
    } else {
226
0
      m_conn_info.ssl_resumption_type = 0;
227
0
    }
228
0
  }
229
230
0
  if (auto protocol_str{txn->get_protocol_string()}; protocol_str) {
231
0
    m_conn_info.protocol = protocol_str;
232
0
  } else {
233
0
    m_conn_info.protocol = "-";
234
0
  }
235
0
}
236
237
inline int64_t
238
HttpUserAgent::get_client_connection_id() const
239
0
{
240
0
  return m_client_connection_id;
241
0
}
242
243
inline int
244
HttpUserAgent::get_client_transaction_id() const
245
0
{
246
0
  return m_txn_info.id;
247
0
}
248
249
inline int
250
HttpUserAgent::get_client_transaction_priority_weight() const
251
0
{
252
0
  return m_txn_info.priority_weight;
253
0
}
254
255
inline int
256
HttpUserAgent::get_client_transaction_priority_dependence() const
257
0
{
258
0
  return m_txn_info.priority_dependence;
259
0
}
260
261
inline bool
262
HttpUserAgent::get_client_tcp_reused() const
263
0
{
264
0
  return m_conn_info.tcp_reused;
265
0
}
266
267
inline bool
268
HttpUserAgent::get_client_ssl_reused() const
269
0
{
270
0
  return m_conn_info.ssl_reused;
271
0
}
272
273
inline int
274
HttpUserAgent::get_client_ssl_resumption_type() const
275
0
{
276
0
  return m_conn_info.ssl_resumption_type;
277
0
}
278
279
inline bool
280
HttpUserAgent::get_client_connection_is_ssl() const
281
0
{
282
0
  return m_conn_info.connection_is_ssl;
283
0
}
284
285
inline char const *
286
HttpUserAgent::get_client_protocol() const
287
0
{
288
0
  return m_conn_info.protocol;
289
0
}
290
291
inline char const *
292
HttpUserAgent::get_client_sec_protocol() const
293
0
{
294
0
  return m_conn_info.sec_protocol;
295
0
}
296
297
inline char const *
298
HttpUserAgent::get_client_cipher_suite() const
299
0
{
300
0
  return m_conn_info.cipher_suite;
301
0
}
302
303
inline char const *
304
HttpUserAgent::get_client_curve() const
305
0
{
306
0
  return m_conn_info.curve;
307
0
}
308
309
inline char const *
310
HttpUserAgent::get_client_security_group() const
311
0
{
312
0
  return m_conn_info.security_group.c_str();
313
0
}
314
315
inline int
316
HttpUserAgent::get_client_alpn_id() const
317
0
{
318
0
  return m_conn_info.alpn_id;
319
0
}
320
321
inline uint64_t
322
HttpUserAgent::get_client_tls_handshake_bytes_rx() const
323
0
{
324
0
  return m_conn_info.tls_handshake_bytes_rx;
325
0
}
326
327
inline uint64_t
328
HttpUserAgent::get_client_tls_handshake_bytes_tx() const
329
0
{
330
0
  return m_conn_info.tls_handshake_bytes_tx;
331
0
}
332
333
inline size_t
334
HttpUserAgent::get_client_tls_early_data_len() const
335
0
{
336
0
  return m_conn_info.tls_early_data_len;
337
0
}
338
339
inline void
340
HttpUserAgent::save_transaction_info()
341
0
{
342
0
  m_txn_info = {m_txn->get_transaction_id(), m_txn->get_transaction_priority_weight(),
343
0
                m_txn->get_transaction_priority_dependence()};
344
0
}