1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 : */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 // HttpLog.h should generally be included first
8 #include "HttpLog.h"
9 
10 #include "nsHttpConnectionMgr.h"
11 #include "nsHttpConnection.h"
12 #include "HttpConnectionUDP.h"
13 #include "Http2Session.h"
14 #include "nsHttpHandler.h"
15 #include "nsIConsoleService.h"
16 #include "nsHttpRequestHead.h"
17 #include "nsServiceManagerUtils.h"
18 #include "nsSocketTransportService2.h"
19 
20 #include "mozilla/IntegerPrintfMacros.h"
21 
22 namespace mozilla {
23 namespace net {
24 
PrintDiagnostics()25 void nsHttpConnectionMgr::PrintDiagnostics() {
26   nsresult rv =
27       PostEvent(&nsHttpConnectionMgr::OnMsgPrintDiagnostics, 0, nullptr);
28   if (NS_FAILED(rv)) {
29     LOG(
30         ("nsHttpConnectionMgr::PrintDiagnostics\n"
31          "  failed to post OnMsgPrintDiagnostics event"));
32   }
33 }
34 
OnMsgPrintDiagnostics(int32_t,ARefBase *)35 void nsHttpConnectionMgr::OnMsgPrintDiagnostics(int32_t, ARefBase*) {
36   MOZ_ASSERT(OnSocketThread(), "not on socket thread");
37 
38   nsCOMPtr<nsIConsoleService> consoleService =
39       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
40   if (!consoleService) return;
41 
42   mLogData.AppendPrintf("HTTP Connection Diagnostics\n---------------------\n");
43   mLogData.AppendPrintf("IsSpdyEnabled() = %d\n",
44                         gHttpHandler->IsSpdyEnabled());
45   mLogData.AppendPrintf("MaxSocketCount() = %d\n",
46                         gHttpHandler->MaxSocketCount());
47   mLogData.AppendPrintf("mNumActiveConns = %d\n", mNumActiveConns);
48   mLogData.AppendPrintf("mNumIdleConns = %d\n", mNumIdleConns);
49 
50   for (const RefPtr<ConnectionEntry>& ent : mCT.Values()) {
51     mLogData.AppendPrintf(
52         "   AtActiveConnectionLimit = %d\n",
53         AtActiveConnectionLimit(ent, NS_HTTP_ALLOW_KEEPALIVE));
54 
55     ent->PrintDiagnostics(mLogData, MaxPersistConnections(ent));
56   }
57 
58   consoleService->LogStringMessage(NS_ConvertUTF8toUTF16(mLogData).Data());
59   mLogData.Truncate();
60 }
61 
PrintDiagnostics(nsCString & log,uint32_t aMaxPersistConns)62 void ConnectionEntry::PrintDiagnostics(nsCString& log,
63                                        uint32_t aMaxPersistConns) {
64   log.AppendPrintf(" ent host = %s hashkey = %s\n", mConnInfo->Origin(),
65                    mConnInfo->HashKey().get());
66 
67   log.AppendPrintf("   RestrictConnections = %d\n", RestrictConnections());
68   log.AppendPrintf("   Pending Q Length = %zu\n", PendingQueueLength());
69   log.AppendPrintf("   Active Conns Length = %zu\n", mActiveConns.Length());
70   log.AppendPrintf("   Idle Conns Length = %zu\n", mIdleConns.Length());
71   log.AppendPrintf("   DnsAndSock Length = %zu\n",
72                    mDnsAndConnectSockets.Length());
73   log.AppendPrintf("   Coalescing Keys Length = %zu\n",
74                    mCoalescingKeys.Length());
75   log.AppendPrintf("   Spdy using = %d\n", mUsingSpdy);
76 
77   uint32_t i;
78   for (i = 0; i < mActiveConns.Length(); ++i) {
79     log.AppendPrintf("   :: Active Connection #%u\n", i);
80     mActiveConns[i]->PrintDiagnostics(log);
81   }
82   for (i = 0; i < mIdleConns.Length(); ++i) {
83     log.AppendPrintf("   :: Idle Connection #%u\n", i);
84     mIdleConns[i]->PrintDiagnostics(log);
85   }
86   for (i = 0; i < mDnsAndConnectSockets.Length(); ++i) {
87     log.AppendPrintf("   :: Half Open #%u\n", i);
88     mDnsAndConnectSockets[i]->PrintDiagnostics(log);
89   }
90 
91   mPendingQ.PrintDiagnostics(log);
92 
93   for (i = 0; i < mCoalescingKeys.Length(); ++i) {
94     log.AppendPrintf("   :: Coalescing Key #%u %s\n", i,
95                      mCoalescingKeys[i].get());
96   }
97 }
98 
PrintDiagnostics(nsCString & log)99 void PendingTransactionQueue::PrintDiagnostics(nsCString& log) {
100   uint32_t i = 0;
101   for (const auto& entry : mPendingTransactionTable) {
102     log.AppendPrintf("   :: Pending Transactions with Window ID = %" PRIu64
103                      "\n",
104                      entry.GetKey());
105     for (uint32_t j = 0; j < entry.GetData()->Length(); ++j) {
106       log.AppendPrintf("     ::: Pending Transaction #%u\n", i);
107       entry.GetData()->ElementAt(j)->PrintDiagnostics(log);
108       ++i;
109     }
110   }
111 }
112 
PrintDiagnostics(nsCString & log)113 void DnsAndConnectSocket::PrintDiagnostics(nsCString& log) {
114   log.AppendPrintf("     has connected = %d, isSpeculative = %d\n",
115                    HasConnected(), IsSpeculative());
116 
117   TimeStamp now = TimeStamp::Now();
118 
119   if (mPrimaryTransport.mSynStarted.IsNull()) {
120     log.AppendPrintf("    primary not started\n");
121   } else {
122     log.AppendPrintf("    primary started %.2fms ago\n",
123                      (now - mPrimaryTransport.mSynStarted).ToMilliseconds());
124   }
125 
126   if (mBackupTransport.mSynStarted.IsNull()) {
127     log.AppendPrintf("    backup not started\n");
128   } else {
129     log.AppendPrintf("    backup started %.2f ago\n",
130                      (now - mBackupTransport.mSynStarted).ToMilliseconds());
131   }
132 
133   log.AppendPrintf("    primary transport %d, backup transport %d\n",
134                    !!mPrimaryTransport.mSocketTransport,
135                    !!mBackupTransport.mSocketTransport);
136 }
137 
PrintDiagnostics(nsCString & log)138 void nsHttpConnection::PrintDiagnostics(nsCString& log) {
139   log.AppendPrintf("    CanDirectlyActivate = %d\n", CanDirectlyActivate());
140 
141   log.AppendPrintf("    npncomplete = %d  setupSSLCalled = %d\n", mNPNComplete,
142                    mSetupSSLCalled);
143 
144   log.AppendPrintf("    spdyVersion = %d  reportedSpdy = %d everspdy = %d\n",
145                    static_cast<int32_t>(mUsingSpdyVersion), mReportedSpdy,
146                    mEverUsedSpdy);
147 
148   log.AppendPrintf("    iskeepalive = %d  dontReuse = %d isReused = %d\n",
149                    IsKeepAlive(), mDontReuse, mIsReused);
150 
151   log.AppendPrintf("    mTransaction = %d mSpdySession = %d\n", !!mTransaction,
152                    !!mSpdySession);
153 
154   PRIntervalTime now = PR_IntervalNow();
155   log.AppendPrintf("    time since last read = %ums\n",
156                    PR_IntervalToMilliseconds(now - mLastReadTime));
157 
158   log.AppendPrintf("    max-read/read/written %" PRId64 "/%" PRId64 "/%" PRId64
159                    "\n",
160                    mMaxBytesRead, mTotalBytesRead, mTotalBytesWritten);
161 
162   log.AppendPrintf("    rtt = %ums\n", PR_IntervalToMilliseconds(mRtt));
163 
164   log.AppendPrintf("    idlemonitoring = %d transactionCount=%d\n",
165                    mIdleMonitoring, mHttp1xTransactionCount);
166 
167   if (mSpdySession) mSpdySession->PrintDiagnostics(log);
168 }
169 
PrintDiagnostics(nsCString & log)170 void HttpConnectionUDP::PrintDiagnostics(nsCString& log) {
171   log.AppendPrintf("    CanDirectlyActivate = %d\n", CanDirectlyActivate());
172 
173   log.AppendPrintf("    dontReuse = %d isReused = %d\n", mDontReuse, mIsReused);
174 
175   log.AppendPrintf("    read/written %" PRId64 "/%" PRId64 "\n",
176                    mHttp3Session ? mHttp3Session->BytesRead() : 0,
177                    mHttp3Session ? mHttp3Session->GetBytesWritten() : 0);
178 
179   log.AppendPrintf("    rtt = %ums\n", PR_IntervalToMilliseconds(mRtt));
180 }
181 
PrintDiagnostics(nsCString & log)182 void Http2Session::PrintDiagnostics(nsCString& log) {
183   log.AppendPrintf("     ::: HTTP2\n");
184   log.AppendPrintf(
185       "     shouldgoaway = %d mClosed = %d CanReuse = %d nextID=0x%X\n",
186       mShouldGoAway, mClosed, CanReuse(), mNextStreamID);
187 
188   log.AppendPrintf("     concurrent = %d maxconcurrent = %d\n", mConcurrent,
189                    mMaxConcurrent);
190 
191   log.AppendPrintf("     roomformorestreams = %d roomformoreconcurrent = %d\n",
192                    RoomForMoreStreams(), RoomForMoreConcurrent());
193 
194   log.AppendPrintf("     transactionHashCount = %d streamIDHashCount = %d\n",
195                    mStreamTransactionHash.Count(), mStreamIDHash.Count());
196 
197   log.AppendPrintf("     Queued Stream Size = %zu\n", mQueuedStreams.Length());
198 
199   PRIntervalTime now = PR_IntervalNow();
200   log.AppendPrintf("     Ping Threshold = %ums\n",
201                    PR_IntervalToMilliseconds(mPingThreshold));
202   log.AppendPrintf("     Ping Timeout = %ums\n",
203                    PR_IntervalToMilliseconds(gHttpHandler->SpdyPingTimeout()));
204   log.AppendPrintf("     Idle for Any Activity (ping) = %ums\n",
205                    PR_IntervalToMilliseconds(now - mLastReadEpoch));
206   log.AppendPrintf("     Idle for Data Activity = %ums\n",
207                    PR_IntervalToMilliseconds(now - mLastDataReadEpoch));
208   if (mPingSentEpoch) {
209     log.AppendPrintf("     Ping Outstanding (ping) = %ums, expired = %d\n",
210                      PR_IntervalToMilliseconds(now - mPingSentEpoch),
211                      now - mPingSentEpoch >= gHttpHandler->SpdyPingTimeout());
212   } else {
213     log.AppendPrintf("     No Ping Outstanding\n");
214   }
215 }
216 
PrintDiagnostics(nsCString & log)217 void nsHttpTransaction::PrintDiagnostics(nsCString& log) {
218   if (!mRequestHead) return;
219 
220   nsAutoCString requestURI;
221   mRequestHead->RequestURI(requestURI);
222   log.AppendPrintf("       :::: uri = %s\n", requestURI.get());
223   log.AppendPrintf("       caps = 0x%x\n", mCaps);
224   log.AppendPrintf("       priority = %d\n", mPriority);
225   log.AppendPrintf("       restart count = %u\n", mRestartCount);
226 }
227 
PrintDiagnostics(nsCString & log)228 void PendingTransactionInfo::PrintDiagnostics(nsCString& log) {
229   log.AppendPrintf("     ::: Pending transaction\n");
230   mTransaction->PrintDiagnostics(log);
231   RefPtr<DnsAndConnectSocket> dnsAndSock = do_QueryReferent(mDnsAndSock);
232   log.AppendPrintf("     Waiting for half open sock: %p or connection: %p\n",
233                    dnsAndSock.get(), mActiveConn.get());
234 }
235 
236 }  // namespace net
237 }  // namespace mozilla
238