2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the root directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
12 #include <folly/wangle/ssl/SSLUtil.h>
15 #include <netinet/tcp.h>
22 * A structure that encapsulates byte counters related to the HTTP headers.
24 struct HTTPHeaderSize {
26 * The number of bytes used to represent the header after compression or
27 * before decompression. If header compression is not supported, the value
33 * The number of bytes used to represent the serialized header before
34 * compression or after decompression, in plain-text format.
36 size_t uncompressed{0};
39 struct TransportInfo {
41 * timestamp of when the connection handshake was completed
43 std::chrono::steady_clock::time_point acceptTime{};
46 * connection RTT (Round-Trip Time)
48 std::chrono::microseconds rtt{0};
50 #if defined(__linux__) || defined(__FreeBSD__)
52 * TCP information as fetched from getsockopt(2)
55 #if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 17
56 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 32
58 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 29
59 #endif // __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 17
61 #endif // defined(__linux__) || defined(__FreeBSD__)
64 * time for setting the connection, from the moment in was accepted until it
67 std::chrono::milliseconds setupTime{0};
70 * time for setting up the SSL connection or SSL handshake
72 std::chrono::milliseconds sslSetupTime{0};
75 * The name of the SSL ciphersuite used by the transaction's
76 * transport. Returns null if the transport is not SSL.
78 std::shared_ptr<std::string> sslCipher{nullptr};
81 * The SSL server name used by the transaction's
82 * transport. Returns null if the transport is not SSL.
84 std::shared_ptr<std::string> sslServerName{nullptr};
87 * list of ciphers sent by the client
89 std::shared_ptr<std::string> sslClientCiphers{nullptr};
92 * list of compression methods sent by the client
94 std::shared_ptr<std::string> sslClientComprMethods{nullptr};
97 * list of TLS extensions sent by the client
99 std::shared_ptr<std::string> sslClientExts{nullptr};
102 * hash of all the SSL parameters sent by the client
104 std::shared_ptr<std::string> sslSignature{nullptr};
107 * list of ciphers supported by the server
109 std::shared_ptr<std::string> sslServerCiphers{nullptr};
112 * guessed "(os) (browser)" based on SSL Signature
114 std::shared_ptr<std::string> guessedUserAgent{nullptr};
117 * The result of SSL NPN negotiation.
119 std::shared_ptr<std::string> sslNextProtocol{nullptr};
122 * total number of bytes sent over the connection
124 int64_t totalBytes{0};
127 * If the client passed through one of our L4 proxies (using PROXY Protocol),
128 * then this will contain the IP address of the proxy host.
130 std::shared_ptr<folly::SocketAddress> clientAddrOriginal;
135 HTTPHeaderSize ingressHeader;
138 * header bytes written
140 HTTPHeaderSize egressHeader;
143 * Here is how the timeToXXXByte variables are planned out:
144 * 1. All timeToXXXByte variables are measuring the ByteEvent from reqStart_
145 * 2. You can get the timing between two ByteEvents by calculating their
146 * differences. For example:
147 * timeToLastBodyByteAck - timeToFirstByte
148 * => Total time to deliver the body
149 * 3. The calculation in point (2) is typically done outside acceptor
152 * We should log the timestamps (TimePoints) and allow
153 * the consumer to calculate the latency whatever it
154 * wants instead of calculating them in wangle, for the sake of flexibility.
156 * 1. TimePoint reqStartTimestamp;
157 * 2. TimePoint firstHeaderByteSentTimestamp;
158 * 3. TimePoint firstBodyByteTimestamp;
159 * 3. TimePoint lastBodyByteTimestamp;
160 * 4. TimePoint lastBodyByteAckTimestamp;
164 * time to first header byte written to the kernel send buffer
165 * NOTE: It is not 100% accurate since TAsyncSocket does not do
166 * do callback on partial write.
168 int32_t timeToFirstHeaderByte{-1};
171 * time to first body byte written to the kernel send buffer
173 int32_t timeToFirstByte{-1};
176 * time to last body byte written to the kernel send buffer
178 int32_t timeToLastByte{-1};
181 * time to TCP Ack received for the last written body byte
183 int32_t timeToLastBodyByteAck{-1};
186 * time it took the client to ACK the last byte, from the moment when the
187 * kernel sent the last byte to the client and until it received the ACK
190 int32_t lastByteAckLatency{-1};
193 * time spent inside wangle
195 int32_t proxyLatency{-1};
198 * time between connection accepted and client message headers completed
200 int32_t clientLatency{-1};
203 * latency for communication with the server
205 int32_t serverLatency{-1};
208 * time used to get a usable connection.
210 int32_t connectLatency{-1};
215 uint32_t egressBodySize{0};
218 * value of errno in case of getsockopt() error
223 * bytes read & written during SSL Setup
225 uint32_t sslSetupBytesWritten{0};
226 uint32_t sslSetupBytesRead{0};
231 uint32_t sslError{0};
236 uint32_t ingressBodySize{0};
239 * The SSL version used by the transaction's transport, in
240 * OpenSSL's format: 4 bits for the major version, followed by 4 bits
241 * for the minor version. Returns zero for non-SSL.
243 uint16_t sslVersion{0};
246 * The SSL certificate size.
248 uint16_t sslCertSize{0};
251 * response status code
253 uint16_t statusCode{0};
256 * The SSL mode for the transaction's transport: new session,
257 * resumed session, or neither (non-SSL).
259 SSLResumeEnum sslResume{SSLResumeEnum::NA};
262 * true if the tcpinfo was successfully read from the kernel
264 bool validTcpinfo{false};
267 * true if the connection is SSL, false otherwise
272 * get the RTT value in milliseconds
274 std::chrono::milliseconds getRttMs() const {
275 return std::chrono::duration_cast<std::chrono::milliseconds>(rtt);
279 * initialize the fields related with tcp_info
281 bool initWithSocket(const AsyncSocket* sock);
284 * Get the kernel's estimate of round-trip time (RTT) to the transport's peer
285 * in microseconds. Returns -1 on error.
287 static int64_t readRTT(const AsyncSocket* sock);
289 #if defined(__linux__) || defined(__FreeBSD__)
291 * perform the getsockopt(2) syscall to fetch TCP info for a given socket
293 static bool readTcpInfo(struct tcp_info* tcpinfo,
294 const AsyncSocket* sock);