c02bac42fbbc5c22f1c062e459641af6507ee4b0
[folly.git] / folly / wangle / acceptor / TransportInfo.h
1 /*
2  *  Copyright (c) 2014, Facebook, Inc.
3  *  All rights reserved.
4  *
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.
8  *
9  */
10 #pragma once
11
12 #include <folly/wangle/ssl/SSLUtil.h>
13
14 #include <chrono>
15 #include <netinet/tcp.h>
16 #include <string>
17
18 namespace folly {
19 class AsyncSocket;
20
21 /**
22  * A structure that encapsulates byte counters related to the HTTP headers.
23  */
24 struct HTTPHeaderSize {
25   /**
26    * The number of bytes used to represent the header after compression or
27    * before decompression. If header compression is not supported, the value
28    * is set to 0.
29    */
30   size_t compressed{0};
31
32   /**
33    * The number of bytes used to represent the serialized header before
34    * compression or after decompression, in plain-text format.
35    */
36   size_t uncompressed{0};
37 };
38
39 struct TransportInfo {
40   /*
41    * timestamp of when the connection handshake was completed
42    */
43   std::chrono::steady_clock::time_point acceptTime{};
44
45   /*
46    * connection RTT (Round-Trip Time)
47    */
48   std::chrono::microseconds rtt{0};
49
50 #if defined(__linux__) || defined(__FreeBSD__)
51   /*
52    * TCP information as fetched from getsockopt(2)
53    */
54   tcp_info tcpinfo {
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
57 #else
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
60   };
61 #endif  // defined(__linux__) || defined(__FreeBSD__)
62
63   /*
64    * time for setting the connection, from the moment in was accepted until it
65    * is established.
66    */
67   std::chrono::milliseconds setupTime{0};
68
69   /*
70    * time for setting up the SSL connection or SSL handshake
71    */
72   std::chrono::milliseconds sslSetupTime{0};
73
74   /*
75    * The name of the SSL ciphersuite used by the transaction's
76    * transport.  Returns null if the transport is not SSL.
77    */
78   std::shared_ptr<std::string> sslCipher{nullptr};
79
80   /*
81    * The SSL server name used by the transaction's
82    * transport.  Returns null if the transport is not SSL.
83    */
84   std::shared_ptr<std::string> sslServerName{nullptr};
85
86   /*
87    * list of ciphers sent by the client
88    */
89   std::shared_ptr<std::string> sslClientCiphers{nullptr};
90
91   /*
92    * list of compression methods sent by the client
93    */
94   std::shared_ptr<std::string> sslClientComprMethods{nullptr};
95
96   /*
97    * list of TLS extensions sent by the client
98    */
99   std::shared_ptr<std::string> sslClientExts{nullptr};
100
101   /*
102    * hash of all the SSL parameters sent by the client
103    */
104   std::shared_ptr<std::string> sslSignature{nullptr};
105
106   /*
107    * list of ciphers supported by the server
108    */
109   std::shared_ptr<std::string> sslServerCiphers{nullptr};
110
111   /*
112    * guessed "(os) (browser)" based on SSL Signature
113    */
114   std::shared_ptr<std::string> guessedUserAgent{nullptr};
115
116   /**
117    * The result of SSL NPN negotiation.
118    */
119   std::shared_ptr<std::string> sslNextProtocol{nullptr};
120
121   /*
122    * total number of bytes sent over the connection
123    */
124   int64_t totalBytes{0};
125
126   /**
127    * header bytes read
128    */
129   HTTPHeaderSize ingressHeader;
130
131   /*
132    * header bytes written
133    */
134   HTTPHeaderSize egressHeader;
135
136   /*
137    * Here is how the timeToXXXByte variables are planned out:
138    * 1. All timeToXXXByte variables are measuring the ByteEvent from reqStart_
139    * 2. You can get the timing between two ByteEvents by calculating their
140    *    differences. For example:
141    *    timeToLastBodyByteAck - timeToFirstByte
142    *    => Total time to deliver the body
143    * 3. The calculation in point (2) is typically done outside acceptor
144    *
145    * Future plan:
146    * We should log the timestamps (TimePoints) and allow
147    * the consumer to calculate the latency whatever it
148    * wants instead of calculating them in wangle, for the sake of flexibility.
149    * For example:
150    * 1. TimePoint reqStartTimestamp;
151    * 2. TimePoint firstHeaderByteSentTimestamp;
152    * 3. TimePoint firstBodyByteTimestamp;
153    * 3. TimePoint lastBodyByteTimestamp;
154    * 4. TimePoint lastBodyByteAckTimestamp;
155    */
156
157   /*
158    * time to first header byte written to the kernel send buffer
159    * NOTE: It is not 100% accurate since TAsyncSocket does not do
160    * do callback on partial write.
161    */
162   int32_t timeToFirstHeaderByte{-1};
163
164   /*
165    * time to first body byte written to the kernel send buffer
166    */
167   int32_t timeToFirstByte{-1};
168
169   /*
170    * time to last body byte written to the kernel send buffer
171    */
172   int32_t timeToLastByte{-1};
173
174   /*
175    * time to TCP Ack received for the last written body byte
176    */
177   int32_t timeToLastBodyByteAck{-1};
178
179   /*
180    * time it took the client to ACK the last byte, from the moment when the
181    * kernel sent the last byte to the client and until it received the ACK
182    * for that byte
183    */
184   int32_t lastByteAckLatency{-1};
185
186   /*
187    * time spent inside wangle
188    */
189   int32_t proxyLatency{-1};
190
191   /*
192    * time between connection accepted and client message headers completed
193    */
194   int32_t clientLatency{-1};
195
196   /*
197    * latency for communication with the server
198    */
199   int32_t serverLatency{-1};
200
201   /*
202    * time used to get a usable connection.
203    */
204   int32_t connectLatency{-1};
205
206   /*
207    * body bytes written
208    */
209   uint32_t egressBodySize{0};
210
211   /*
212    * value of errno in case of getsockopt() error
213    */
214   int tcpinfoErrno{0};
215
216   /*
217    * bytes read & written during SSL Setup
218    */
219   uint32_t sslSetupBytesWritten{0};
220   uint32_t sslSetupBytesRead{0};
221
222   /**
223    * SSL error detail
224    */
225   uint32_t sslError{0};
226
227   /**
228    * body bytes read
229    */
230   uint32_t ingressBodySize{0};
231
232   /*
233    * The SSL version used by the transaction's transport, in
234    * OpenSSL's format: 4 bits for the major version, followed by 4 bits
235    * for the minor version.  Returns zero for non-SSL.
236    */
237   uint16_t sslVersion{0};
238
239   /*
240    * The SSL certificate size.
241    */
242   uint16_t sslCertSize{0};
243
244   /**
245    * response status code
246    */
247   uint16_t statusCode{0};
248
249   /*
250    * The SSL mode for the transaction's transport: new session,
251    * resumed session, or neither (non-SSL).
252    */
253   SSLResumeEnum sslResume{SSLResumeEnum::NA};
254
255   /*
256    * true if the tcpinfo was successfully read from the kernel
257    */
258   bool validTcpinfo{false};
259
260   /*
261    * true if the connection is SSL, false otherwise
262    */
263   bool ssl{false};
264
265   /*
266    * get the RTT value in milliseconds
267    */
268   std::chrono::milliseconds getRttMs() const {
269     return std::chrono::duration_cast<std::chrono::milliseconds>(rtt);
270   }
271
272   /*
273    * initialize the fields related with tcp_info
274    */
275   bool initWithSocket(const AsyncSocket* sock);
276
277   /*
278    * Get the kernel's estimate of round-trip time (RTT) to the transport's peer
279    * in microseconds. Returns -1 on error.
280    */
281   static int64_t readRTT(const AsyncSocket* sock);
282
283 #if defined(__linux__) || defined(__FreeBSD__)
284   /*
285    * perform the getsockopt(2) syscall to fetch TCP info for a given socket
286    */
287   static bool readTcpInfo(struct tcp_info* tcpinfo,
288                           const AsyncSocket* sock);
289 #endif
290 };
291
292 } // folly