1 /* vim:t ts=4 sw=2 sts=2 et cin: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 // HttpLog.h should generally be included first
7 #include "HttpLog.h"
8 
9 #include "PendingTransactionInfo.h"
10 
11 // Log on level :5, instead of default :4.
12 #undef LOG
13 #define LOG(args) LOG5(args)
14 #undef LOG_ENABLED
15 #define LOG_ENABLED() LOG5_ENABLED()
16 
17 namespace mozilla {
18 namespace net {
19 
20 PendingTransactionInfo::~PendingTransactionInfo() {
21   if (mDnsAndSock) {
22     RefPtr<DnsAndConnectSocket> dnsAndSock = do_QueryReferent(mDnsAndSock);
23     LOG(
24         ("PendingTransactionInfo::PendingTransactionInfo "
25          "[trans=%p halfOpen=%p]",
26          mTransaction.get(), dnsAndSock.get()));
27     if (dnsAndSock) {
28       dnsAndSock->Unclaim();
29     }
30     mDnsAndSock = nullptr;
31   } else if (mActiveConn) {
32     RefPtr<HttpConnectionBase> activeConn = do_QueryReferent(mActiveConn);
33     if (activeConn && activeConn->Transaction() &&
34         activeConn->Transaction()->IsNullTransaction()) {
35       NullHttpTransaction* nullTrans =
36           activeConn->Transaction()->QueryNullTransaction();
37       nullTrans->Unclaim();
38       LOG((
39           "PendingTransactionInfo::PendingTransactionInfo - mark %p unclaimed.",
40           activeConn.get()));
41     }
42   }
43 }
44 
45 bool PendingTransactionInfo::IsAlreadyClaimedInitializingConn() {
46   LOG(
47       ("PendingTransactionInfo::IsAlreadyClaimedInitializingConn "
48        "[trans=%p, halfOpen=%p, activeConn=%p]\n",
49        mTransaction.get(), mDnsAndSock.get(), mActiveConn.get()));
50 
51   // When this transaction has already established a half-open
52   // connection, we want to prevent any duplicate half-open
53   // connections from being established and bound to this
54   // transaction. Allow only use of an idle persistent connection
55   // (if found) for transactions referred by a half-open connection.
56   bool alreadyDnsAndSockOrWaitingForTLS = false;
57   if (mDnsAndSock) {
58     MOZ_ASSERT(!mActiveConn);
GetBrowsingContext()59     RefPtr<DnsAndConnectSocket> dnsAndSock = do_QueryReferent(mDnsAndSock);
60     LOG(
61         ("PendingTransactionInfo::IsAlreadyClaimedInitializingConn "
62          "[trans=%p, dnsAndSock=%p]\n",
63          mTransaction.get(), dnsAndSock.get()));
64     if (dnsAndSock) {
65       alreadyDnsAndSockOrWaitingForTLS = true;
66     } else {
67       // If we have not found the halfOpen socket, remove the pointer.
68       mDnsAndSock = nullptr;
69     }
70   } else if (mActiveConn) {
71     MOZ_ASSERT(!mDnsAndSock);
72     RefPtr<HttpConnectionBase> activeConn = do_QueryReferent(mActiveConn);
73     LOG(
74         ("PendingTransactionInfo::IsAlreadyClaimedInitializingConn "
75          "[trans=%p, activeConn=%p]\n",
76          mTransaction.get(), activeConn.get()));
77     // Check if this transaction claimed a connection that is still
78     // performing tls handshake with a NullHttpTransaction or it is between
79     // finishing tls and reclaiming (When nullTrans finishes tls handshake,
80     // httpConnection does not have a transaction any more and a
81     // ReclaimConnection is dispatched). But if an error occurred the
82     // connection will be closed, it will exist but CanReused will be
NS_DEFINE_STATIC_IID_ACCESSOR(ParentChannelListener,PARENT_CHANNEL_LISTENER)83     // false.
84     if (activeConn &&
85         ((activeConn->Transaction() &&
86           activeConn->Transaction()->IsNullTransaction()) ||
87          (!activeConn->Transaction() && activeConn->CanReuse()))) {
88       alreadyDnsAndSockOrWaitingForTLS = true;
89     } else {
90       // If we have not found the connection, remove the pointer.
91       mActiveConn = nullptr;
92     }
93   }
94 
95   return alreadyDnsAndSockOrWaitingForTLS;
96 }
97 
98 nsWeakPtr PendingTransactionInfo::ForgetDnsAndConnectSocketAndActiveConn() {
99   nsWeakPtr dnsAndSock = mDnsAndSock;
100 
101   mDnsAndSock = nullptr;
102   mActiveConn = nullptr;
103   return dnsAndSock;
104 }
105 
106 void PendingTransactionInfo::RememberDnsAndConnectSocket(
107     DnsAndConnectSocket* sock) {
108   mDnsAndSock =
109       do_GetWeakReference(static_cast<nsISupportsWeakReference*>(sock));
110 }
111 
112 bool PendingTransactionInfo::TryClaimingActiveConn(HttpConnectionBase* conn) {
113   nsAHttpTransaction* activeTrans = conn->Transaction();
114   NullHttpTransaction* nullTrans =
115       activeTrans ? activeTrans->QueryNullTransaction() : nullptr;
116   if (nullTrans && nullTrans->Claim()) {
117     mActiveConn =
118         do_GetWeakReference(static_cast<nsISupportsWeakReference*>(conn));
119     return true;
120   }
121   return false;
122 }
123 
124 void PendingTransactionInfo::AddDnsAndConnectSocket(DnsAndConnectSocket* sock) {
125   mDnsAndSock =
126       do_GetWeakReference(static_cast<nsISupportsWeakReference*>(sock));
127 }
128 
129 }  // namespace net
130 }  // namespace mozilla
131