Attachment #520642: syn retry v5 for bug #623948

View | Details | Raw Unified | Return to bug 623948
Collapse All | Expand All

(-)a/modules/libpref/src/init/all.js (+5 lines)
Line     Link Here 
 Lines 746-761   pref("network.http.prompt-temp-redirect" Link Here 
746
// for certain services (i.e. EF for VoIP, AF4x for interactive video,
746
// for certain services (i.e. EF for VoIP, AF4x for interactive video,
747
// AF3x for broadcast/streaming video, etc)
747
// AF3x for broadcast/streaming video, etc)
748
748
749
// default value for HTTP
749
// default value for HTTP
750
// in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
750
// in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
751
// Section 4.8 "High-Throughput Data Service Class"
751
// Section 4.8 "High-Throughput Data Service Class"
752
pref("network.http.qos", 0);
752
pref("network.http.qos", 0);
753
753
754
// The number of milliseconds after sending a SYN for an HTTP connection,
755
// to wait before trying a different connection. 0 means do not use a second
756
// connection.
757
pref("network.http.connection-retry-timeout", 250);
758
754
// default values for FTP
759
// default values for FTP
755
// in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
760
// in a DSCP environment this should be 40 (0x28, or AF11), per RFC-4594,
756
// Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22)
761
// Section 4.8 "High-Throughput Data Service Class", and 80 (0x50, or AF22)
757
// per Section 4.7 "Low-Latency Data Service Class".
762
// per Section 4.7 "Low-Latency Data Service Class".
758
pref("network.ftp.data.qos", 0);
763
pref("network.ftp.data.qos", 0);
759
pref("network.ftp.control.qos", 0);
764
pref("network.ftp.control.qos", 0);
760
765
761
// </http>
766
// </http>
(-)a/netwerk/base/src/nsSocketTransport2.cpp (-3 / +15 lines)
Line     Link Here 
 Lines 1773-1791   nsSocketTransport::GetSecurityCallbacks( Link Here 
1773
    nsAutoLock lock(mLock);
1773
    nsAutoLock lock(mLock);
1774
    NS_IF_ADDREF(*callbacks = mCallbacks);
1774
    NS_IF_ADDREF(*callbacks = mCallbacks);
1775
    return NS_OK;
1775
    return NS_OK;
1776
}
1776
}
1777
1777
1778
NS_IMETHODIMP
1778
NS_IMETHODIMP
1779
nsSocketTransport::SetSecurityCallbacks(nsIInterfaceRequestor *callbacks)
1779
nsSocketTransport::SetSecurityCallbacks(nsIInterfaceRequestor *callbacks)
1780
{
1780
{
1781
    nsAutoLock lock(mLock);
1781
    nsCOMPtr<nsISupports> secinfo;
1782
    mCallbacks = callbacks;
1782
    {
1783
    // XXX should we tell PSM about this?
1783
        nsAutoLock lock(mLock);
1784
        mCallbacks = callbacks;
1785
        SOCKET_LOG(("Reset callbacks for secinfo=%p callbacks=%p\n",
1786
                    mSecInfo.get(), mCallbacks.get()));
1787
1788
        secinfo = mSecInfo;
1789
    }
1790
1791
    // don't call into PSM while holding mLock!!
1792
    nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo));
1793
    if (secCtrl)
1794
        secCtrl->SetNotificationCallbacks(callbacks);
1795
1784
    return NS_OK;
1796
    return NS_OK;
1785
}
1797
}
1786
1798
1787
NS_IMETHODIMP
1799
NS_IMETHODIMP
1788
nsSocketTransport::SetEventSink(nsITransportEventSink *sink,
1800
nsSocketTransport::SetEventSink(nsITransportEventSink *sink,
1789
                                nsIEventTarget *target)
1801
                                nsIEventTarget *target)
1790
{
1802
{
1791
    nsCOMPtr<nsITransportEventSink> temp;
1803
    nsCOMPtr<nsITransportEventSink> temp;
(-)a/netwerk/protocol/http/nsAHttpTransaction.h (-2 / +5 lines)
Line     Link Here 
 Lines 39-54    Link Here 
39
#define nsAHttpTransaction_h__
39
#define nsAHttpTransaction_h__
40
40
41
#include "nsISupports.h"
41
#include "nsISupports.h"
42
42
43
class nsAHttpConnection;
43
class nsAHttpConnection;
44
class nsAHttpSegmentReader;
44
class nsAHttpSegmentReader;
45
class nsAHttpSegmentWriter;
45
class nsAHttpSegmentWriter;
46
class nsIInterfaceRequestor;
46
class nsIInterfaceRequestor;
47
class nsIEventTarget;
47
48
48
//----------------------------------------------------------------------------
49
//----------------------------------------------------------------------------
49
// Abstract base class for a HTTP transaction:
50
// Abstract base class for a HTTP transaction:
50
//
51
//
51
// A transaction is a "sink" for the response data.  The connection pushes
52
// A transaction is a "sink" for the response data.  The connection pushes
52
// data to the transaction by writing to it.  The transaction supports
53
// data to the transaction by writing to it.  The transaction supports
53
// WriteSegments and may refuse to accept data if its buffers are full (its
54
// WriteSegments and may refuse to accept data if its buffers are full (its
54
// write function returns NS_BASE_STREAM_WOULD_BLOCK in this case).
55
// write function returns NS_BASE_STREAM_WOULD_BLOCK in this case).
 Lines 57-73   class nsIInterfaceRequestor; Link Here 
57
class nsAHttpTransaction : public nsISupports
58
class nsAHttpTransaction : public nsISupports
58
{
59
{
59
public:
60
public:
60
    // called by the connection when it takes ownership of the transaction.
61
    // called by the connection when it takes ownership of the transaction.
61
    virtual void SetConnection(nsAHttpConnection *) = 0;
62
    virtual void SetConnection(nsAHttpConnection *) = 0;
62
63
63
    // called by the connection to get security callbacks to set on the 
64
    // called by the connection to get security callbacks to set on the 
64
    // socket transport.
65
    // socket transport.
65
    virtual void GetSecurityCallbacks(nsIInterfaceRequestor **) = 0;
66
    virtual void GetSecurityCallbacks(nsIInterfaceRequestor **,
67
                                      nsIEventTarget **) = 0;
66
68
67
    // called to report socket status (see nsITransportEventSink)
69
    // called to report socket status (see nsITransportEventSink)
68
    virtual void OnTransportStatus(nsresult status, PRUint64 progress) = 0;
70
    virtual void OnTransportStatus(nsresult status, PRUint64 progress) = 0;
69
71
70
    // called to check the transaction status.
72
    // called to check the transaction status.
71
    virtual PRBool   IsDone() = 0;
73
    virtual PRBool   IsDone() = 0;
72
    virtual nsresult Status() = 0;
74
    virtual nsresult Status() = 0;
73
75
 Lines 83-99   public: Link Here 
83
                                   PRUint32 count, PRUint32 *countWritten) = 0;
85
                                   PRUint32 count, PRUint32 *countWritten) = 0;
84
86
85
    // called to close the transaction
87
    // called to close the transaction
86
    virtual void Close(nsresult reason) = 0;
88
    virtual void Close(nsresult reason) = 0;
87
};
89
};
88
90
89
#define NS_DECL_NSAHTTPTRANSACTION \
91
#define NS_DECL_NSAHTTPTRANSACTION \
90
    void SetConnection(nsAHttpConnection *); \
92
    void SetConnection(nsAHttpConnection *); \
91
    void GetSecurityCallbacks(nsIInterfaceRequestor **); \
93
    void GetSecurityCallbacks(nsIInterfaceRequestor **, \
94
                              nsIEventTarget **);       \
92
    void OnTransportStatus(nsresult status, PRUint64 progress); \
95
    void OnTransportStatus(nsresult status, PRUint64 progress); \
93
    PRBool   IsDone(); \
96
    PRBool   IsDone(); \
94
    nsresult Status(); \
97
    nsresult Status(); \
95
    PRUint32 Available(); \
98
    PRUint32 Available(); \
96
    nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *); \
99
    nsresult ReadSegments(nsAHttpSegmentReader *, PRUint32, PRUint32 *); \
97
    nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *); \
100
    nsresult WriteSegments(nsAHttpSegmentWriter *, PRUint32, PRUint32 *); \
98
    void     Close(nsresult reason);
101
    void     Close(nsresult reason);
99
102
(-)a/netwerk/protocol/http/nsHttpConnection.cpp (-103 / +93 lines)
Line     Link Here 
 Lines 46-79    Link Here 
46
#include "nsISocketTransportService.h"
46
#include "nsISocketTransportService.h"
47
#include "nsISocketTransport.h"
47
#include "nsISocketTransport.h"
48
#include "nsIServiceManager.h"
48
#include "nsIServiceManager.h"
49
#include "nsISSLSocketControl.h"
49
#include "nsISSLSocketControl.h"
50
#include "nsStringStream.h"
50
#include "nsStringStream.h"
51
#include "netCore.h"
51
#include "netCore.h"
52
#include "nsNetCID.h"
52
#include "nsNetCID.h"
53
#include "nsAutoLock.h"
53
#include "nsAutoLock.h"
54
#include "nsProxyRelease.h"
54
#include "prmem.h"
55
#include "prmem.h"
55
56
56
#ifdef DEBUG
57
#ifdef DEBUG
57
// defined by the socket transport service while active
58
// defined by the socket transport service while active
58
extern PRThread *gSocketThread;
59
extern PRThread *gSocketThread;
59
#endif
60
#endif
60
61
61
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
62
static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID);
62
63
63
//-----------------------------------------------------------------------------
64
//-----------------------------------------------------------------------------
64
// nsHttpConnection <public>
65
// nsHttpConnection <public>
65
//-----------------------------------------------------------------------------
66
//-----------------------------------------------------------------------------
66
67
67
nsHttpConnection::nsHttpConnection()
68
nsHttpConnection::nsHttpConnection()
68
    : mTransaction(nsnull)
69
    : mTransaction(nsnull)
69
    , mConnInfo(nsnull)
70
    , mLastReadTime(0)
70
    , mLastReadTime(0)
71
    , mIdleTimeout(0)
71
    , mIdleTimeout(0)
72
    , mConsiderReusedAfterInterval(0)
73
    , mConsiderReusedAfterEpoch(0)
72
    , mKeepAlive(PR_TRUE) // assume to keep-alive by default
74
    , mKeepAlive(PR_TRUE) // assume to keep-alive by default
73
    , mKeepAliveMask(PR_TRUE)
75
    , mKeepAliveMask(PR_TRUE)
74
    , mSupportsPipelining(PR_FALSE) // assume low-grade server
76
    , mSupportsPipelining(PR_FALSE) // assume low-grade server
75
    , mIsReused(PR_FALSE)
77
    , mIsReused(PR_FALSE)
76
    , mCompletedSSLConnect(PR_FALSE)
78
    , mCompletedSSLConnect(PR_FALSE)
77
    , mLastTransactionExpectedNoContent(PR_FALSE)
79
    , mLastTransactionExpectedNoContent(PR_FALSE)
78
{
80
{
79
    LOG(("Creating nsHttpConnection @%x\n", this));
81
    LOG(("Creating nsHttpConnection @%x\n", this));
 Lines 81-170   nsHttpConnection::nsHttpConnection() Link Here 
81
    // grab a reference to the handler to ensure that it doesn't go away.
83
    // grab a reference to the handler to ensure that it doesn't go away.
82
    nsHttpHandler *handler = gHttpHandler;
84
    nsHttpHandler *handler = gHttpHandler;
83
    NS_ADDREF(handler);
85
    NS_ADDREF(handler);
84
}
86
}
85
87
86
nsHttpConnection::~nsHttpConnection()
88
nsHttpConnection::~nsHttpConnection()
87
{
89
{
88
    LOG(("Destroying nsHttpConnection @%x\n", this));
90
    LOG(("Destroying nsHttpConnection @%x\n", this));
89
 
91
90
    NS_IF_RELEASE(mConnInfo);
92
    if (mCallbacks) {
91
    NS_IF_RELEASE(mTransaction);
93
        nsIInterfaceRequestor *cbs = nsnull;
94
        mCallbacks.swap(cbs);
95
        NS_ProxyRelease(mCallbackTarget, cbs);
96
    }
92
97
93
    // release our reference to the handler
98
    // release our reference to the handler
94
    nsHttpHandler *handler = gHttpHandler;
99
    nsHttpHandler *handler = gHttpHandler;
95
    NS_RELEASE(handler);
100
    NS_RELEASE(handler);
96
}
101
}
97
102
98
nsresult
103
nsresult
99
nsHttpConnection::Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime)
104
nsHttpConnection::Init(nsHttpConnectionInfo *info,
105
                       PRUint16 maxHangTime,
106
                       nsISocketTransport *transport,
107
                       nsIAsyncInputStream *instream,
108
                       nsIAsyncOutputStream *outstream,
109
                       nsIInterfaceRequestor *callbacks,
110
                       nsIEventTarget *callbackTarget)
100
{
111
{
101
    LOG(("nsHttpConnection::Init [this=%x]\n", this));
112
    NS_ABORT_IF_FALSE(transport && instream && outstream,
113
                      "invalid socket information");
114
    LOG(("nsHttpConnection::Init [this=%p "
115
         "transport=%p instream=%p outstream=%p]\n",
116
         this, transport, instream, outstream));
102
117
103
    NS_ENSURE_ARG_POINTER(info);
118
    NS_ENSURE_ARG_POINTER(info);
104
    NS_ENSURE_TRUE(!mConnInfo, NS_ERROR_ALREADY_INITIALIZED);
119
    NS_ENSURE_TRUE(!mConnInfo, NS_ERROR_ALREADY_INITIALIZED);
105
120
106
    mConnInfo = info;
121
    mConnInfo = info;
107
    NS_ADDREF(mConnInfo);
108
109
    mMaxHangTime = maxHangTime;
122
    mMaxHangTime = maxHangTime;
110
    mLastReadTime = NowInSeconds();
123
    mLastReadTime = NowInSeconds();
124
125
    mSocketTransport = transport;
126
    mSocketIn = instream;
127
    mSocketOut = outstream;
128
    nsresult rv = mSocketTransport->SetEventSink(this, nsnull);
129
    NS_ENSURE_SUCCESS(rv, rv);
130
131
    mCallbacks = callbacks;
132
    mCallbackTarget = callbackTarget;
133
    rv = mSocketTransport->SetSecurityCallbacks(this);
134
    NS_ENSURE_SUCCESS(rv, rv);
135
111
    return NS_OK;
136
    return NS_OK;
112
}
137
}
113
138
114
// called on the socket thread
139
// called on the socket thread
115
nsresult
140
nsresult
116
nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps)
141
nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps)
117
{
142
{
118
    nsresult rv;
143
    nsresult rv;
119
144
145
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
120
    LOG(("nsHttpConnection::Activate [this=%x trans=%x caps=%x]\n",
146
    LOG(("nsHttpConnection::Activate [this=%x trans=%x caps=%x]\n",
121
         this, trans, caps));
147
         this, trans, caps));
122
148
123
    NS_ENSURE_ARG_POINTER(trans);
149
    NS_ENSURE_ARG_POINTER(trans);
124
    NS_ENSURE_TRUE(!mTransaction, NS_ERROR_IN_PROGRESS);
150
    NS_ENSURE_TRUE(!mTransaction, NS_ERROR_IN_PROGRESS);
125
151
126
    // take ownership of the transaction
152
    // take ownership of the transaction
127
    mTransaction = trans;
153
    mTransaction = trans;
128
    NS_ADDREF(mTransaction);
129
154
130
    // set mKeepAlive according to what will be requested
155
    // set mKeepAlive according to what will be requested
131
    mKeepAliveMask = mKeepAlive = (caps & NS_HTTP_ALLOW_KEEPALIVE);
156
    mKeepAliveMask = mKeepAlive = (caps & NS_HTTP_ALLOW_KEEPALIVE);
132
157
133
    // if we don't have a socket transport then create a new one
134
    if (!mSocketTransport) {
135
        rv = CreateTransport(caps);
136
        if (NS_FAILED(rv))
137
            goto loser;
138
    }
139
140
    // need to handle SSL proxy CONNECT if this is the first time.
158
    // need to handle SSL proxy CONNECT if this is the first time.
141
    if (mConnInfo->UsingSSL() && mConnInfo->UsingHttpProxy() && !mCompletedSSLConnect) {
159
    if (mConnInfo->UsingSSL() && mConnInfo->UsingHttpProxy() && !mCompletedSSLConnect) {
142
        rv = SetupSSLProxyConnect();
160
        rv = SetupSSLProxyConnect();
143
        if (NS_FAILED(rv))
161
        if (NS_FAILED(rv))
144
            goto loser;
162
            goto failed_activation;
145
    }
163
    }
146
164
147
    // wait for the output stream to be readable
165
    rv = OnOutputStreamReady(mSocketOut);
148
    rv = mSocketOut->AsyncWait(this, 0, 0, nsnull);
166
    
149
    if (NS_SUCCEEDED(rv))
167
failed_activation:
150
        return rv;
168
    if (NS_FAILED(rv)) {
169
        mTransaction = nsnull;
170
    }
151
171
152
loser:
153
    NS_RELEASE(mTransaction);
154
    return rv;
172
    return rv;
155
}
173
}
156
174
157
void
175
void
158
nsHttpConnection::Close(nsresult reason)
176
nsHttpConnection::Close(nsresult reason)
159
{
177
{
160
    LOG(("nsHttpConnection::Close [this=%x reason=%x]\n", this, reason));
178
    LOG(("nsHttpConnection::Close [this=%x reason=%x]\n", this, reason));
161
179
162
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
180
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
163
181
164
    if (NS_FAILED(reason)) {
182
    if (NS_FAILED(reason)) {
165
        if (mSocketTransport) {
183
        if (mSocketTransport) {
166
            mSocketTransport->SetSecurityCallbacks(nsnull);
184
            mSocketTransport->SetSecurityCallbacks(nsnull);
167
            mSocketTransport->SetEventSink(nsnull, nsnull);
185
            mSocketTransport->SetEventSink(nsnull, nsnull);
168
            mSocketTransport->Close(reason);
186
            mSocketTransport->Close(reason);
169
        }
187
        }
170
        mKeepAlive = PR_FALSE;
188
        mKeepAlive = PR_FALSE;
 Lines 188-205   nsHttpConnection::ProxyStartSSL() Link Here 
188
    if (NS_FAILED(rv)) return rv;
206
    if (NS_FAILED(rv)) return rv;
189
207
190
    return ssl->ProxyStartSSL();
208
    return ssl->ProxyStartSSL();
191
}
209
}
192
210
193
PRBool
211
PRBool
194
nsHttpConnection::CanReuse()
212
nsHttpConnection::CanReuse()
195
{
213
{
196
    return IsKeepAlive() && (NowInSeconds() - mLastReadTime < mIdleTimeout)
214
    PRBool canReuse = IsKeepAlive() &&
197
                         && IsAlive();
215
        (NowInSeconds() - mLastReadTime < mIdleTimeout) &&
216
        IsAlive();
217
    
218
    // An idle persistent connection should not have data waiting to be read
219
    // before a request is sent. Data here is likely a 408 timeout response
220
    // which we would deal with later on through the restart logic, but that
221
    // path is more expensive than just closing the socket now. SSL check can
222
    // be removed with fixing of 631801
223
224
    PRUint32 dataSize;
225
    if (canReuse && mSocketIn && !mConnInfo->UsingSSL() &&
226
        NS_SUCCEEDED(mSocketIn->Available(&dataSize)) && dataSize) {
227
        LOG(("nsHttpConnection::CanReuse %p %s"
228
             "Socket not reusable because read data pending (%d) on it.\n",
229
             this, mConnInfo->Host(), dataSize));
230
        canReuse = PR_FALSE;
231
    }
232
    return canReuse;
198
}
233
}
199
234
200
PRUint32 nsHttpConnection::TimeToLive()
235
PRUint32 nsHttpConnection::TimeToLive()
201
{
236
{
202
    PRInt32 tmp = mIdleTimeout - (NowInSeconds() - mLastReadTime);
237
    PRInt32 tmp = mIdleTimeout - (NowInSeconds() - mLastReadTime);
203
    if (0 > tmp)
238
    if (0 > tmp)
204
        tmp = 0;
239
        tmp = 0;
205
240
 Lines 382-405   nsHttpConnection::OnHeadersAvailable(nsA Link Here 
382
            NS_ASSERTION(NS_SUCCEEDED(rv), "mSocketOut->AsyncWait failed");
417
            NS_ASSERTION(NS_SUCCEEDED(rv), "mSocketOut->AsyncWait failed");
383
        }
418
        }
384
        else {
419
        else {
385
            LOG(("SSL proxy CONNECT failed!\n"));
420
            LOG(("SSL proxy CONNECT failed!\n"));
386
            // NOTE: this cast is valid since this connection cannot be
421
            // NOTE: this cast is valid since this connection cannot be
387
            // processing a transaction pipeline until after the first HTTP/1.1
422
            // processing a transaction pipeline until after the first HTTP/1.1
388
            // response.
423
            // response.
389
            nsHttpTransaction *trans =
424
            nsHttpTransaction *trans =
390
                    static_cast<nsHttpTransaction *>(mTransaction);
425
                    static_cast<nsHttpTransaction *>(mTransaction.get());
391
            trans->SetSSLConnectFailed();
426
            trans->SetSSLConnectFailed();
392
        }
427
        }
393
    }
428
    }
394
429
395
    return NS_OK;
430
    return NS_OK;
396
}
431
}
397
432
433
PRBool
434
nsHttpConnection::IsReused()
435
{
436
    if (mIsReused) return PR_TRUE;
437
    if (!mConsiderReusedAfterInterval) return PR_FALSE;
438
    
439
    // ReusedAfter allows a socket to be consider reused only after a certain
440
    // interval of time has passed
441
    return (PR_IntervalNow() - mConsiderReusedAfterEpoch) >=
442
        mConsiderReusedAfterInterval;
443
}
444
445
void
446
nsHttpConnection::SetIsReusedAfter(PRUint32 afterMilliseconds)
447
{
448
    mConsiderReusedAfterEpoch = PR_IntervalNow();
449
    mConsiderReusedAfterInterval = PR_MillisecondsToInterval(afterMilliseconds);
450
}
451
398
void
452
void
399
nsHttpConnection::GetSecurityInfo(nsISupports **secinfo)
453
nsHttpConnection::GetSecurityInfo(nsISupports **secinfo)
400
{
454
{
401
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
455
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
402
456
403
    if (mSocketTransport) {
457
    if (mSocketTransport) {
404
        if (NS_FAILED(mSocketTransport->GetSecurityInfo(secinfo)))
458
        if (NS_FAILED(mSocketTransport->GetSecurityInfo(secinfo)))
405
            *secinfo = nsnull;
459
            *secinfo = nsnull;
 Lines 433-528   nsHttpConnection::ResumeRecv() Link Here 
433
    NS_NOTREACHED("no socket input stream");
487
    NS_NOTREACHED("no socket input stream");
434
    return NS_ERROR_UNEXPECTED;
488
    return NS_ERROR_UNEXPECTED;
435
}
489
}
436
490
437
//-----------------------------------------------------------------------------
491
//-----------------------------------------------------------------------------
438
// nsHttpConnection <private>
492
// nsHttpConnection <private>
439
//-----------------------------------------------------------------------------
493
//-----------------------------------------------------------------------------
440
494
441
nsresult
442
nsHttpConnection::CreateTransport(PRUint8 caps)
443
{
444
    nsresult rv;
445
446
    NS_PRECONDITION(!mSocketTransport, "unexpected");
447
448
    nsCOMPtr<nsISocketTransportService> sts =
449
            do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
450
    if (NS_FAILED(rv)) return rv;
451
452
    // configure the socket type based on the connection type requested.
453
    const char* types[1];
454
455
    if (mConnInfo->UsingSSL())
456
        types[0] = "ssl";
457
    else
458
        types[0] = gHttpHandler->DefaultSocketType();
459
460
    nsCOMPtr<nsISocketTransport> strans;
461
    PRUint32 typeCount = (types[0] != nsnull);
462
463
    rv = sts->CreateTransport(types, typeCount,
464
                              nsDependentCString(mConnInfo->Host()),
465
                              mConnInfo->Port(),
466
                              mConnInfo->ProxyInfo(),
467
                              getter_AddRefs(strans));
468
    if (NS_FAILED(rv)) return rv;
469
470
    PRUint32 tmpFlags = 0;
471
    if (caps & NS_HTTP_REFRESH_DNS)
472
        tmpFlags = nsISocketTransport::BYPASS_CACHE;
473
    
474
    if (caps & NS_HTTP_LOAD_ANONYMOUS)
475
        tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT;
476
    
477
    strans->SetConnectionFlags(tmpFlags); 
478
479
    strans->SetQoSBits(gHttpHandler->GetQoSBits());
480
481
    // NOTE: these create cyclical references, which we break inside
482
    //       nsHttpConnection::Close
483
    rv = strans->SetEventSink(this, nsnull);
484
    if (NS_FAILED(rv)) return rv;
485
    rv = strans->SetSecurityCallbacks(this);
486
    if (NS_FAILED(rv)) return rv;
487
488
    // next open the socket streams
489
    nsCOMPtr<nsIOutputStream> sout;
490
    rv = strans->OpenOutputStream(nsITransport::OPEN_UNBUFFERED, 0, 0,
491
                                  getter_AddRefs(sout));
492
    if (NS_FAILED(rv)) return rv;
493
    nsCOMPtr<nsIInputStream> sin;
494
    rv = strans->OpenInputStream(nsITransport::OPEN_UNBUFFERED, 0, 0,
495
                                 getter_AddRefs(sin));
496
    if (NS_FAILED(rv)) return rv;
497
498
    mSocketTransport = strans;
499
    mSocketIn = do_QueryInterface(sin);
500
    mSocketOut = do_QueryInterface(sout);
501
    return NS_OK;
502
}
503
504
void
495
void
505
nsHttpConnection::CloseTransaction(nsAHttpTransaction *trans, nsresult reason)
496
nsHttpConnection::CloseTransaction(nsAHttpTransaction *trans, nsresult reason)
506
{
497
{
507
    LOG(("nsHttpConnection::CloseTransaction[this=%x trans=%x reason=%x]\n",
498
    LOG(("nsHttpConnection::CloseTransaction[this=%x trans=%x reason=%x]\n",
508
        this, trans, reason));
499
        this, trans, reason));
509
500
510
    NS_ASSERTION(trans == mTransaction, "wrong transaction");
501
    NS_ASSERTION(trans == mTransaction, "wrong transaction");
511
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
502
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
512
503
513
    // mask this error code because its not a real error.
504
    // mask this error code because its not a real error.
514
    if (reason == NS_BASE_STREAM_CLOSED)
505
    if (reason == NS_BASE_STREAM_CLOSED)
515
        reason = NS_OK;
506
        reason = NS_OK;
516
507
517
    mTransaction->Close(reason);
508
    mTransaction->Close(reason);
518
509
    mTransaction = nsnull;
519
    NS_RELEASE(mTransaction);
520
    mTransaction = 0;
521
510
522
    if (NS_FAILED(reason))
511
    if (NS_FAILED(reason))
523
        Close(reason);
512
        Close(reason);
524
513
525
    // flag the connection as reused here for convenience sake.  certainly
514
    // flag the connection as reused here for convenience sake.  certainly
526
    // it might be going away instead ;-)
515
    // it might be going away instead ;-)
527
    mIsReused = PR_TRUE;
516
    mIsReused = PR_TRUE;
528
}
517
}
 Lines 723-739   nsHttpConnection::SetupSSLProxyConnect() Link Here 
723
    request.SetRequestURI(buf);
712
    request.SetRequestURI(buf);
724
    request.SetHeader(nsHttp::User_Agent, gHttpHandler->UserAgent());
713
    request.SetHeader(nsHttp::User_Agent, gHttpHandler->UserAgent());
725
714
726
    // send this header for backwards compatibility.
715
    // send this header for backwards compatibility.
727
    request.SetHeader(nsHttp::Proxy_Connection, NS_LITERAL_CSTRING("keep-alive"));
716
    request.SetHeader(nsHttp::Proxy_Connection, NS_LITERAL_CSTRING("keep-alive"));
728
717
729
    // NOTE: this cast is valid since this connection cannot be processing a
718
    // NOTE: this cast is valid since this connection cannot be processing a
730
    // transaction pipeline until after the first HTTP/1.1 response.
719
    // transaction pipeline until after the first HTTP/1.1 response.
731
    nsHttpTransaction *trans = static_cast<nsHttpTransaction *>(mTransaction);
720
    nsHttpTransaction *trans =
721
        static_cast<nsHttpTransaction *>(mTransaction.get());
732
    
722
    
733
    val = trans->RequestHead()->PeekHeader(nsHttp::Host);
723
    val = trans->RequestHead()->PeekHeader(nsHttp::Host);
734
    if (val) {
724
    if (val) {
735
        // all HTTP/1.1 requests must include a Host header (even though it
725
        // all HTTP/1.1 requests must include a Host header (even though it
736
        // may seem redundant in this case; see bug 82388).
726
        // may seem redundant in this case; see bug 82388).
737
        request.SetHeader(nsHttp::Host, nsDependentCString(val));
727
        request.SetHeader(nsHttp::Host, nsDependentCString(val));
738
    }
728
    }
739
729
 Lines 787-804   nsHttpConnection::OnInputStreamReady(nsI Link Here 
787
777
788
//-----------------------------------------------------------------------------
778
//-----------------------------------------------------------------------------
789
// nsHttpConnection::nsIOutputStreamCallback
779
// nsHttpConnection::nsIOutputStreamCallback
790
//-----------------------------------------------------------------------------
780
//-----------------------------------------------------------------------------
791
781
792
NS_IMETHODIMP
782
NS_IMETHODIMP
793
nsHttpConnection::OnOutputStreamReady(nsIAsyncOutputStream *out)
783
nsHttpConnection::OnOutputStreamReady(nsIAsyncOutputStream *out)
794
{
784
{
795
    NS_ASSERTION(out == mSocketOut, "unexpected stream");
785
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
796
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
786
    NS_ABORT_IF_FALSE(out == mSocketOut, "unexpected socket");
797
787
798
    // if the transaction was dropped...
788
    // if the transaction was dropped...
799
    if (!mTransaction) {
789
    if (!mTransaction) {
800
        LOG(("  no transaction; ignoring event\n"));
790
        LOG(("  no transaction; ignoring event\n"));
801
        return NS_OK;
791
        return NS_OK;
802
    }
792
    }
803
793
804
    nsresult rv = OnSocketWritable();
794
    nsresult rv = OnSocketWritable();
 Lines 830-848   nsHttpConnection::OnTransportStatus(nsIT Link Here 
830
// not called on the socket transport thread
820
// not called on the socket transport thread
831
NS_IMETHODIMP
821
NS_IMETHODIMP
832
nsHttpConnection::GetInterface(const nsIID &iid, void **result)
822
nsHttpConnection::GetInterface(const nsIID &iid, void **result)
833
{
823
{
834
    // NOTE: This function is only called on the UI thread via sync proxy from
824
    // NOTE: This function is only called on the UI thread via sync proxy from
835
    //       the socket transport thread.  If that weren't the case, then we'd
825
    //       the socket transport thread.  If that weren't the case, then we'd
836
    //       have to worry about the possibility of mTransaction going away
826
    //       have to worry about the possibility of mTransaction going away
837
    //       part-way through this function call.  See CloseTransaction.
827
    //       part-way through this function call.  See CloseTransaction.
828
829
    // NOTE - there is a bug here, the call to getinterface is proxied off the
830
    // nss thread, not the ui thread as the above comment says. So there is
831
    // indeed a chance of mTransaction going away. bug 615342
832
838
    NS_ASSERTION(PR_GetCurrentThread() != gSocketThread, "wrong thread");
833
    NS_ASSERTION(PR_GetCurrentThread() != gSocketThread, "wrong thread");
839
 
840
    if (mTransaction) {
841
        nsCOMPtr<nsIInterfaceRequestor> callbacks;
842
        mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
843
        if (callbacks)
844
            return callbacks->GetInterface(iid, result);
845
    }
846
834
835
    if (mCallbacks)
836
        return mCallbacks->GetInterface(iid, result);
847
    return NS_ERROR_NO_INTERFACE;
837
    return NS_ERROR_NO_INTERFACE;
848
}
838
}
(-)a/netwerk/protocol/http/nsHttpConnection.h (-5 / +19 lines)
Line     Link Here 
 Lines 42-63    Link Here 
42
#include "nsHttp.h"
42
#include "nsHttp.h"
43
#include "nsHttpConnectionInfo.h"
43
#include "nsHttpConnectionInfo.h"
44
#include "nsAHttpConnection.h"
44
#include "nsAHttpConnection.h"
45
#include "nsAHttpTransaction.h"
45
#include "nsAHttpTransaction.h"
46
#include "nsXPIDLString.h"
46
#include "nsXPIDLString.h"
47
#include "nsCOMPtr.h"
47
#include "nsCOMPtr.h"
48
#include "prlock.h"
48
#include "prlock.h"
49
#include "nsAutoPtr.h"
49
#include "nsAutoPtr.h"
50
#include "prinrval.h"
50
51
51
#include "nsIStreamListener.h"
52
#include "nsIStreamListener.h"
52
#include "nsISocketTransport.h"
53
#include "nsISocketTransport.h"
53
#include "nsIAsyncInputStream.h"
54
#include "nsIAsyncInputStream.h"
54
#include "nsIAsyncOutputStream.h"
55
#include "nsIAsyncOutputStream.h"
55
#include "nsIInterfaceRequestor.h"
56
#include "nsIInterfaceRequestor.h"
57
#include "nsIEventTarget.h"
56
58
57
//-----------------------------------------------------------------------------
59
//-----------------------------------------------------------------------------
58
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
60
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
59
//
61
//
60
// NOTE: this objects lives on the socket thread only.  it should not be
62
// NOTE: this objects lives on the socket thread only.  it should not be
61
// accessed from any other thread.
63
// accessed from any other thread.
62
//-----------------------------------------------------------------------------
64
//-----------------------------------------------------------------------------
63
65
 Lines 80-96   public: Link Here 
80
    nsHttpConnection();
82
    nsHttpConnection();
81
    virtual ~nsHttpConnection();
83
    virtual ~nsHttpConnection();
82
84
83
    // Initialize the connection:
85
    // Initialize the connection:
84
    //  info        - specifies the connection parameters.
86
    //  info        - specifies the connection parameters.
85
    //  maxHangTime - limits the amount of time this connection can spend on a
87
    //  maxHangTime - limits the amount of time this connection can spend on a
86
    //                single transaction before it should no longer be kept 
88
    //                single transaction before it should no longer be kept 
87
    //                alive.  a value of 0xffff indicates no limit.
89
    //                alive.  a value of 0xffff indicates no limit.
88
    nsresult Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime);
90
    nsresult Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime,
91
                  nsISocketTransport *, nsIAsyncInputStream *,
92
                  nsIAsyncOutputStream *, nsIInterfaceRequestor *,
93
                  nsIEventTarget *);
89
94
90
    // Activate causes the given transaction to be processed on this
95
    // Activate causes the given transaction to be processed on this
91
    // connection.  It fails if there is already an existing transaction.
96
    // connection.  It fails if there is already an existing transaction.
92
    nsresult Activate(nsAHttpTransaction *, PRUint8 caps);
97
    nsresult Activate(nsAHttpTransaction *, PRUint8 caps);
93
98
94
    // Close the underlying socket transport.
99
    // Close the underlying socket transport.
95
    void Close(nsresult reason);
100
    void Close(nsresult reason);
96
101
 Lines 123-151   public: Link Here 
123
    nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
128
    nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
124
129
125
    // nsAHttpConnection compatible methods (non-virtual):
130
    // nsAHttpConnection compatible methods (non-virtual):
126
    nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, PRBool *reset);
131
    nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpRequestHead *, nsHttpResponseHead *, PRBool *reset);
127
    void     CloseTransaction(nsAHttpTransaction *, nsresult reason);
132
    void     CloseTransaction(nsAHttpTransaction *, nsresult reason);
128
    void     GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnInfo); }
133
    void     GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnInfo); }
129
    void     GetSecurityInfo(nsISupports **);
134
    void     GetSecurityInfo(nsISupports **);
130
    PRBool   IsPersistent() { return IsKeepAlive(); }
135
    PRBool   IsPersistent() { return IsKeepAlive(); }
131
    PRBool   IsReused() { return mIsReused; }
136
    PRBool   IsReused();
137
    void     SetIsReusedAfter(PRUint32 afterMilliseconds);
138
    void     SetIdleTimeout(PRUint16 val) {mIdleTimeout = val;}
132
    nsresult PushBack(const char *data, PRUint32 length) { NS_NOTREACHED("PushBack"); return NS_ERROR_UNEXPECTED; }
139
    nsresult PushBack(const char *data, PRUint32 length) { NS_NOTREACHED("PushBack"); return NS_ERROR_UNEXPECTED; }
133
    nsresult ResumeSend();
140
    nsresult ResumeSend();
134
    nsresult ResumeRecv();
141
    nsresult ResumeRecv();
135
142
136
    static NS_METHOD ReadFromStream(nsIInputStream *, void *, const char *,
143
    static NS_METHOD ReadFromStream(nsIInputStream *, void *, const char *,
137
                                    PRUint32, PRUint32, PRUint32 *);
144
                                    PRUint32, PRUint32, PRUint32 *);
138
145
139
private:
146
private:
140
    // called to cause the underlying socket to start speaking SSL
147
    // called to cause the underlying socket to start speaking SSL
141
    nsresult ProxyStartSSL();
148
    nsresult ProxyStartSSL();
142
149
143
    nsresult CreateTransport(PRUint8 caps);
144
    nsresult OnTransactionDone(nsresult reason);
150
    nsresult OnTransactionDone(nsresult reason);
145
    nsresult OnSocketWritable();
151
    nsresult OnSocketWritable();
146
    nsresult OnSocketReadable();
152
    nsresult OnSocketReadable();
147
153
148
    nsresult SetupSSLProxyConnect();
154
    nsresult SetupSSLProxyConnect();
149
155
150
    PRBool   IsAlive();
156
    PRBool   IsAlive();
151
    PRBool   SupportsPipelining(nsHttpResponseHead *);
157
    PRBool   SupportsPipelining(nsHttpResponseHead *);
 Lines 156-177   private: Link Here 
156
    nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
162
    nsCOMPtr<nsIAsyncOutputStream>  mSocketOut;
157
163
158
    nsresult                        mSocketInCondition;
164
    nsresult                        mSocketInCondition;
159
    nsresult                        mSocketOutCondition;
165
    nsresult                        mSocketOutCondition;
160
166
161
    nsCOMPtr<nsIInputStream>        mSSLProxyConnectStream;
167
    nsCOMPtr<nsIInputStream>        mSSLProxyConnectStream;
162
    nsCOMPtr<nsIInputStream>        mRequestStream;
168
    nsCOMPtr<nsIInputStream>        mRequestStream;
163
169
164
    nsAHttpTransaction             *mTransaction; // hard ref
170
    // mTransaction only points to the HTTP Transaction callbacks if the
165
    nsHttpConnectionInfo           *mConnInfo;    // hard ref
171
    // transaction is open, otherwise it is null.
172
    nsRefPtr<nsAHttpTransaction>    mTransaction;
173
174
    nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
175
    nsCOMPtr<nsIEventTarget>        mCallbackTarget;
176
177
    nsRefPtr<nsHttpConnectionInfo> mConnInfo;
166
178
167
    PRUint32                        mLastReadTime;
179
    PRUint32                        mLastReadTime;
168
    PRUint16                        mMaxHangTime;    // max download time before dropping keep-alive status
180
    PRUint16                        mMaxHangTime;    // max download time before dropping keep-alive status
169
    PRUint16                        mIdleTimeout;    // value of keep-alive: timeout=
181
    PRUint16                        mIdleTimeout;    // value of keep-alive: timeout=
182
    PRIntervalTime                  mConsiderReusedAfterInterval;
183
    PRIntervalTime                  mConsiderReusedAfterEpoch;
170
184
171
    PRPackedBool                    mKeepAlive;
185
    PRPackedBool                    mKeepAlive;
172
    PRPackedBool                    mKeepAliveMask;
186
    PRPackedBool                    mKeepAliveMask;
173
    PRPackedBool                    mSupportsPipelining;
187
    PRPackedBool                    mSupportsPipelining;
174
    PRPackedBool                    mIsReused;
188
    PRPackedBool                    mIsReused;
175
    PRPackedBool                    mCompletedSSLConnect;
189
    PRPackedBool                    mCompletedSSLConnect;
176
    PRPackedBool                    mLastTransactionExpectedNoContent;
190
    PRPackedBool                    mLastTransactionExpectedNoContent;
177
};
191
};
(-)a/netwerk/protocol/http/nsHttpConnectionMgr.cpp (-44 / +417 lines)
Line     Link Here 
 Lines 395-428   nsHttpConnectionMgr::ProcessOneTransacti Link Here 
395
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
395
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
396
396
397
    if (self->ProcessPendingQForEntry(ent))
397
    if (self->ProcessPendingQForEntry(ent))
398
        return kHashEnumerateStop;
398
        return kHashEnumerateStop;
399
399
400
    return kHashEnumerateNext;
400
    return kHashEnumerateNext;
401
}
401
}
402
402
403
// If the global number of idle connections is preventing the opening of
404
// new connections to a host without idle connections, then
405
// close them regardless of their TTL
403
PRIntn
406
PRIntn
404
nsHttpConnectionMgr::PurgeOneIdleConnectionCB(nsHashKey *key, void *data, void *closure)
407
nsHttpConnectionMgr::PurgeExcessIdleConnectionsCB(nsHashKey *key,
408
                                                  void *data, void *closure)
405
{
409
{
406
    nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
410
    nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
407
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
411
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
408
412
409
    if (ent->mIdleConns.Length() > 0) {
413
    while (self->mNumIdleConns + self->mNumActiveConns + 1 >= self->mMaxConns) {
414
        if (!ent->mIdleConns.Length()) {
415
            // There are no idle conns left in this connection entry
416
            return kHashEnumerateNext;
417
        }
410
        nsHttpConnection *conn = ent->mIdleConns[0];
418
        nsHttpConnection *conn = ent->mIdleConns[0];
411
        ent->mIdleConns.RemoveElementAt(0);
419
        ent->mIdleConns.RemoveElementAt(0);
412
        conn->Close(NS_ERROR_ABORT);
420
        conn->Close(NS_ERROR_ABORT);
413
        NS_RELEASE(conn);
421
        NS_RELEASE(conn);
414
        self->mNumIdleConns--;
422
        self->mNumIdleConns--;
415
        if (0 == self->mNumIdleConns)
423
        if (0 == self->mNumIdleConns)
416
            self->StopPruneDeadConnectionsTimer();
424
            self->StopPruneDeadConnectionsTimer();
417
        return kHashEnumerateStop;
418
    }
425
    }
419
426
    return kHashEnumerateStop;
420
    return kHashEnumerateNext;
421
}
427
}
422
428
423
PRIntn
429
PRIntn
424
nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *closure)
430
nsHttpConnectionMgr::PruneDeadConnectionsCB(nsHashKey *key, void *data, void *closure)
425
{
431
{
426
    nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
432
    nsHttpConnectionMgr *self = (nsHttpConnectionMgr *) closure;
427
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
433
    nsConnectionEntry *ent = (nsConnectionEntry *) data;
428
434
 Lines 469-484   nsHttpConnectionMgr::PruneDeadConnection Link Here 
469
            LOG(("    active conn [%x] with trans [%x]\n", conn, conn->Transaction()));
475
            LOG(("    active conn [%x] with trans [%x]\n", conn, conn->Transaction()));
470
        }
476
        }
471
    }
477
    }
472
#endif
478
#endif
473
479
474
    // if this entry is empty, then we can remove it.
480
    // if this entry is empty, then we can remove it.
475
    if (ent->mIdleConns.Length()   == 0 &&
481
    if (ent->mIdleConns.Length()   == 0 &&
476
        ent->mActiveConns.Length() == 0 &&
482
        ent->mActiveConns.Length() == 0 &&
483
        ent->mHalfOpens.Length()   == 0 &&
477
        ent->mPendingQ.Length()    == 0) {
484
        ent->mPendingQ.Length()    == 0) {
478
        LOG(("    removing empty connection entry\n"));
485
        LOG(("    removing empty connection entry\n"));
479
        delete ent;
486
        delete ent;
480
        return kHashEnumerateRemove;
487
        return kHashEnumerateRemove;
481
    }
488
    }
482
489
483
    // else, use this opportunity to compact our arrays...
490
    // else, use this opportunity to compact our arrays...
484
    ent->mIdleConns.Compact();
491
    ent->mIdleConns.Compact();
 Lines 528-543   nsHttpConnectionMgr::ShutdownPassCB(nsHa Link Here 
528
        trans = ent->mPendingQ[0];
535
        trans = ent->mPendingQ[0];
529
536
530
        ent->mPendingQ.RemoveElementAt(0);
537
        ent->mPendingQ.RemoveElementAt(0);
531
538
532
        trans->Close(NS_ERROR_ABORT);
539
        trans->Close(NS_ERROR_ABORT);
533
        NS_RELEASE(trans);
540
        NS_RELEASE(trans);
534
    }
541
    }
535
542
543
    // close all half open tcp connections
544
    for (PRInt32 i = ((PRInt32) ent->mHalfOpens.Length()) - 1; i >= 0; i--)
545
        ent->mHalfOpens[i]->Abandon();
546
536
    delete ent;
547
    delete ent;
537
    return kHashEnumerateRemove;
548
    return kHashEnumerateRemove;
538
}
549
}
539
550
540
//-----------------------------------------------------------------------------
551
//-----------------------------------------------------------------------------
541
552
542
PRBool
553
PRBool
543
nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent)
554
nsHttpConnectionMgr::ProcessPendingQForEntry(nsConnectionEntry *ent)
 Lines 547-563   nsHttpConnectionMgr::ProcessPendingQForE Link Here 
547
558
548
    PRInt32 i, count = ent->mPendingQ.Length();
559
    PRInt32 i, count = ent->mPendingQ.Length();
549
    if (count > 0) {
560
    if (count > 0) {
550
        LOG(("  pending-count=%u\n", count));
561
        LOG(("  pending-count=%u\n", count));
551
        nsHttpTransaction *trans = nsnull;
562
        nsHttpTransaction *trans = nsnull;
552
        nsHttpConnection *conn = nsnull;
563
        nsHttpConnection *conn = nsnull;
553
        for (i=0; i<count; ++i) {
564
        for (i=0; i<count; ++i) {
554
            trans = ent->mPendingQ[i];
565
            trans = ent->mPendingQ[i];
555
            GetConnection(ent, trans->Caps(), &conn);
566
            GetConnection(ent, trans, &conn);
556
            if (conn)
567
            if (conn)
557
                break;
568
                break;
558
        }
569
        }
559
        if (conn) {
570
        if (conn) {
560
            LOG(("  dispatching pending transaction...\n"));
571
            LOG(("  dispatching pending transaction...\n"));
561
572
562
            // remove pending transaction
573
            // remove pending transaction
563
            ent->mPendingQ.RemoveElementAt(i);
574
            ent->mPendingQ.RemoveElementAt(i);
 Lines 587-604   nsHttpConnectionMgr::ProcessPendingQForE Link Here 
587
PRBool
598
PRBool
588
nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps)
599
nsHttpConnectionMgr::AtActiveConnectionLimit(nsConnectionEntry *ent, PRUint8 caps)
589
{
600
{
590
    nsHttpConnectionInfo *ci = ent->mConnInfo;
601
    nsHttpConnectionInfo *ci = ent->mConnInfo;
591
602
592
    LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
603
    LOG(("nsHttpConnectionMgr::AtActiveConnectionLimit [ci=%s caps=%x]\n",
593
        ci->HashKey().get(), caps));
604
        ci->HashKey().get(), caps));
594
605
595
    // If we have more active connections than the limit, then we're done --
606
    // If there are more active connections than the global limit, then we're
596
    // purging idle connections won't get us below it.
607
    // done. Purging idle connections won't get us below it.
597
    if (mNumActiveConns >= mMaxConns) {
608
    if (mNumActiveConns >= mMaxConns) {
598
        LOG(("  num active conns == max conns\n"));
609
        LOG(("  num active conns == max conns\n"));
599
        return PR_TRUE;
610
        return PR_TRUE;
600
    }
611
    }
601
612
602
    nsHttpConnection *conn;
613
    nsHttpConnection *conn;
603
    PRInt32 i, totalCount, persistCount = 0;
614
    PRInt32 i, totalCount, persistCount = 0;
604
    
615
    
 Lines 606-621   nsHttpConnectionMgr::AtActiveConnectionL Link Here 
606
617
607
    // count the number of persistent connections
618
    // count the number of persistent connections
608
    for (i=0; i<totalCount; ++i) {
619
    for (i=0; i<totalCount; ++i) {
609
        conn = ent->mActiveConns[i];
620
        conn = ent->mActiveConns[i];
610
        if (conn->IsKeepAlive()) // XXX make sure this is thread-safe
621
        if (conn->IsKeepAlive()) // XXX make sure this is thread-safe
611
            persistCount++;
622
            persistCount++;
612
    }
623
    }
613
624
625
    // Add in the in-progress tcp connections, we will assume they are
626
    // keepalive enabled.
627
    totalCount += ent->mHalfOpens.Length();
628
    persistCount += ent->mHalfOpens.Length();
629
    
614
    LOG(("   total=%d, persist=%d\n", totalCount, persistCount));
630
    LOG(("   total=%d, persist=%d\n", totalCount, persistCount));
615
631
616
    PRUint16 maxConns;
632
    PRUint16 maxConns;
617
    PRUint16 maxPersistConns;
633
    PRUint16 maxPersistConns;
618
634
619
    if (ci->UsingHttpProxy() && !ci->UsingSSL()) {
635
    if (ci->UsingHttpProxy() && !ci->UsingSSL()) {
620
        maxConns = mMaxConnsPerProxy;
636
        maxConns = mMaxConnsPerProxy;
621
        maxPersistConns = mMaxPersistConnsPerProxy;
637
        maxPersistConns = mMaxPersistConnsPerProxy;
 Lines 626-653   nsHttpConnectionMgr::AtActiveConnectionL Link Here 
626
    }
642
    }
627
643
628
    // use >= just to be safe
644
    // use >= just to be safe
629
    return (totalCount >= maxConns) || ( (caps & NS_HTTP_ALLOW_KEEPALIVE) &&
645
    return (totalCount >= maxConns) || ( (caps & NS_HTTP_ALLOW_KEEPALIVE) &&
630
                                         (persistCount >= maxPersistConns) );
646
                                         (persistCount >= maxPersistConns) );
631
}
647
}
632
648
633
void
649
void
634
nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent, PRUint8 caps,
650
nsHttpConnectionMgr::GetConnection(nsConnectionEntry *ent,
651
                                   nsHttpTransaction *trans,
635
                                   nsHttpConnection **result)
652
                                   nsHttpConnection **result)
636
{
653
{
637
    LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n",
654
    LOG(("nsHttpConnectionMgr::GetConnection [ci=%s caps=%x]\n",
638
        ent->mConnInfo->HashKey().get(), PRUint32(caps)));
655
        ent->mConnInfo->HashKey().get(), PRUint32(trans->Caps())));
656
657
    // First, see if an idle persistent connection may be reused instead of
658
    // establishing a new socket. We do not need to check the connection limits
659
    // yet as they govern the maximum number of open connections and reusing
660
    // an old connection never increases that.
639
661
640
    *result = nsnull;
662
    *result = nsnull;
641
663
642
    nsHttpConnection *conn = nsnull;
664
    nsHttpConnection *conn = nsnull;
643
665
644
    if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
666
    if (trans->Caps() & NS_HTTP_ALLOW_KEEPALIVE) {
645
        // search the idle connection list
667
        // search the idle connection list. Each element in the list
668
        // has a reference, so if we remove it from the list into a local
669
        // ptr, that ptr now owns the reference
646
        while (!conn && (ent->mIdleConns.Length() > 0)) {
670
        while (!conn && (ent->mIdleConns.Length() > 0)) {
647
            conn = ent->mIdleConns[0];
671
            conn = ent->mIdleConns[0];
648
            // we check if the connection can be reused before even checking if
672
            // we check if the connection can be reused before even checking if
649
            // it is a "matching" connection.
673
            // it is a "matching" connection.
650
            if (!conn->CanReuse()) {
674
            if (!conn->CanReuse()) {
651
                LOG(("   dropping stale connection: [conn=%x]\n", conn));
675
                LOG(("   dropping stale connection: [conn=%x]\n", conn));
652
                conn->Close(NS_ERROR_ABORT);
676
                conn->Close(NS_ERROR_ABORT);
653
                NS_RELEASE(conn);
677
                NS_RELEASE(conn);
 Lines 667-707   nsHttpConnectionMgr::GetConnection(nsCon Link Here 
667
    if (!conn) {
691
    if (!conn) {
668
        // Check if we need to purge an idle connection. Note that we may have
692
        // Check if we need to purge an idle connection. Note that we may have
669
        // removed one above; if so, this will be a no-op. We do this before
693
        // removed one above; if so, this will be a no-op. We do this before
670
        // checking the active connection limit to catch the case where we do
694
        // checking the active connection limit to catch the case where we do
671
        // have an idle connection, but the purge timer hasn't fired yet.
695
        // have an idle connection, but the purge timer hasn't fired yet.
672
        // XXX this just purges a random idle connection.  we should instead
696
        // XXX this just purges a random idle connection.  we should instead
673
        // enumerate the entire hash table to find the eldest idle connection.
697
        // enumerate the entire hash table to find the eldest idle connection.
674
        if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns)
698
        if (mNumIdleConns && mNumIdleConns + mNumActiveConns + 1 >= mMaxConns)
675
            mCT.Enumerate(PurgeOneIdleConnectionCB, this);
699
            mCT.Enumerate(PurgeExcessIdleConnectionsCB, this);
676
700
677
        // Need to make a new TCP connection. First, we check if we've hit
701
        // Need to make a new TCP connection. First, we check if we've hit
678
        // either the maximum connection limit globally or for this particular
702
        // either the maximum connection limit globally or for this particular
679
        // host or proxy. If we have, we're done.
703
        // host or proxy. If we have, we're done.
680
        if (AtActiveConnectionLimit(ent, caps)) {
704
        if (AtActiveConnectionLimit(ent, trans->Caps())) {
681
            LOG(("  at active connection limit!\n"));
705
            LOG(("nsHttpConnectionMgr::GetConnection [ci = %s]"
706
                 "at active connection limit - will queue\n",
707
                 ent->mConnInfo->HashKey().get()));
682
            return;
708
            return;
683
        }
709
        }
684
710
685
        conn = new nsHttpConnection();
711
        nsresult rv = CreateTransport(ent, trans);
686
        if (!conn)
712
        if (NS_FAILED(rv))
687
            return;
713
            trans->Close(rv);
688
        NS_ADDREF(conn);
714
        return;
689
690
        nsresult rv = conn->Init(ent->mConnInfo, mMaxRequestDelay);
691
        if (NS_FAILED(rv)) {
692
            NS_RELEASE(conn);
693
            return;
694
        }
695
    }
715
    }
696
716
717
    // hold an owning ref to this connection
718
    ent->mActiveConns.AppendElement(conn);
719
    mNumActiveConns++;
720
    NS_ADDREF(conn);
721
697
    *result = conn;
722
    *result = conn;
698
}
723
}
699
724
725
void
726
nsHttpConnectionMgr::AddActiveConn(nsHttpConnection *conn,
727
                                   nsConnectionEntry *ent)
728
{
729
    NS_ADDREF(conn);
730
    ent->mActiveConns.AppendElement(conn);
731
    mNumActiveConns++;
732
}
733
734
void
735
nsHttpConnectionMgr::StartedConnect()
736
{
737
    mNumActiveConns++;
738
}
739
740
void
741
nsHttpConnectionMgr::RecvdConnect()
742
{
743
    mNumActiveConns--;
744
}
745
746
nsresult
747
nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent,
748
                                     nsHttpTransaction *trans)
749
{
750
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
751
752
    nsRefPtr<nsHalfOpenSocket> sock = new nsHalfOpenSocket(ent, trans);
753
    nsresult rv = sock->SetupPrimaryStreams();
754
    NS_ENSURE_SUCCESS(rv, rv);
755
756
    sock->SetupBackupTimer();
757
    ent->mHalfOpens.AppendElement(sock);
758
    return NS_OK;
759
}
760
700
nsresult
761
nsresult
701
nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
762
nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent,
702
                                         nsAHttpTransaction *trans,
763
                                         nsAHttpTransaction *trans,
703
                                         PRUint8 caps,
764
                                         PRUint8 caps,
704
                                         nsHttpConnection *conn)
765
                                         nsHttpConnection *conn)
705
{
766
{
706
    LOG(("nsHttpConnectionMgr::DispatchTransaction [ci=%s trans=%x caps=%x conn=%x]\n",
767
    LOG(("nsHttpConnectionMgr::DispatchTransaction [ci=%s trans=%x caps=%x conn=%x]\n",
707
        ent->mConnInfo->HashKey().get(), trans, caps, conn));
768
        ent->mConnInfo->HashKey().get(), trans, caps, conn));
 Lines 713-733   nsHttpConnectionMgr::DispatchTransaction Link Here 
713
774
714
    nsHttpPipeline *pipeline = nsnull;
775
    nsHttpPipeline *pipeline = nsnull;
715
    if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) {
776
    if (conn->SupportsPipelining() && (caps & NS_HTTP_ALLOW_PIPELINING)) {
716
        LOG(("  looking to build pipeline...\n"));
777
        LOG(("  looking to build pipeline...\n"));
717
        if (BuildPipeline(ent, trans, &pipeline))
778
        if (BuildPipeline(ent, trans, &pipeline))
718
            trans = pipeline;
779
            trans = pipeline;
719
    }
780
    }
720
781
721
    // hold an owning ref to this connection
722
    ent->mActiveConns.AppendElement(conn);
723
    mNumActiveConns++;
724
    NS_ADDREF(conn);
725
726
    // give the transaction the indirect reference to the connection.
782
    // give the transaction the indirect reference to the connection.
727
    trans->SetConnection(handle);
783
    trans->SetConnection(handle);
728
784
729
    nsresult rv = conn->Activate(trans, caps);
785
    nsresult rv = conn->Activate(trans, caps);
730
786
731
    if (NS_FAILED(rv)) {
787
    if (NS_FAILED(rv)) {
732
        LOG(("  conn->Activate failed [rv=%x]\n", rv));
788
        LOG(("  conn->Activate failed [rv=%x]\n", rv));
733
        ent->mActiveConns.RemoveElement(conn);
789
        ent->mActiveConns.RemoveElement(conn);
 Lines 790-805   nsHttpConnectionMgr::BuildPipeline(nsCon Link Here 
790
    LOG(("  pipelined %u transactions\n", numAdded));
846
    LOG(("  pipelined %u transactions\n", numAdded));
791
    NS_ADDREF(*result = pipeline);
847
    NS_ADDREF(*result = pipeline);
792
    return PR_TRUE;
848
    return PR_TRUE;
793
}
849
}
794
850
795
nsresult
851
nsresult
796
nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
852
nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans)
797
{
853
{
854
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
855
798
    // since "adds" and "cancels" are processed asynchronously and because
856
    // since "adds" and "cancels" are processed asynchronously and because
799
    // various events might trigger an "add" directly on the socket thread,
857
    // various events might trigger an "add" directly on the socket thread,
800
    // we must take care to avoid dispatching a transaction that has already
858
    // we must take care to avoid dispatching a transaction that has already
801
    // been canceled (see bug 190001).
859
    // been canceled (see bug 190001).
802
    if (NS_FAILED(trans->Status())) {
860
    if (NS_FAILED(trans->Status())) {
803
        LOG(("  transaction was canceled... dropping event!\n"));
861
        LOG(("  transaction was canceled... dropping event!\n"));
804
        return NS_OK;
862
        return NS_OK;
805
    }
863
    }
 Lines 832-859   nsHttpConnectionMgr::ProcessNewTransacti Link Here 
832
890
833
        // steal reference from connection handle.
891
        // steal reference from connection handle.
834
        // XXX prevent SetConnection(nsnull) from calling ReclaimConnection
892
        // XXX prevent SetConnection(nsnull) from calling ReclaimConnection
835
        conn = handle->mConn;
893
        conn = handle->mConn;
836
        handle->mConn = nsnull;
894
        handle->mConn = nsnull;
837
895
838
        // destroy connection handle.
896
        // destroy connection handle.
839
        trans->SetConnection(nsnull);
897
        trans->SetConnection(nsnull);
840
841
        // remove sticky connection from active connection list; we'll add it
842
        // right back in DispatchTransaction.
843
        if (ent->mActiveConns.RemoveElement(conn))
844
            mNumActiveConns--;
845
        else {
846
            NS_ERROR("sticky connection not found in active list");
847
            return NS_ERROR_UNEXPECTED;
848
        }
849
    }
898
    }
850
    else
899
    else
851
        GetConnection(ent, caps, &conn);
900
        GetConnection(ent, trans, &conn);
852
901
853
    nsresult rv;
902
    nsresult rv;
854
    if (!conn) {
903
    if (!conn) {
855
        LOG(("  adding transaction to pending queue [trans=%x pending-count=%u]\n",
904
        LOG(("  adding transaction to pending queue [trans=%x pending-count=%u]\n",
856
            trans, ent->mPendingQ.Length()+1));
905
            trans, ent->mPendingQ.Length()+1));
857
        // put this transaction on the pending queue...
906
        // put this transaction on the pending queue...
858
        InsertTransactionSorted(ent->mPendingQ, trans);
907
        InsertTransactionSorted(ent->mPendingQ, trans);
859
        NS_ADDREF(trans);
908
        NS_ADDREF(trans);
 Lines 993-1030   nsHttpConnectionMgr::OnMsgReclaimConnect Link Here 
993
    nsHttpConnectionInfo *ci = conn->ConnectionInfo();
1042
    nsHttpConnectionInfo *ci = conn->ConnectionInfo();
994
    NS_ADDREF(ci);
1043
    NS_ADDREF(ci);
995
1044
996
    nsCStringKey key(ci->HashKey());
1045
    nsCStringKey key(ci->HashKey());
997
    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
1046
    nsConnectionEntry *ent = (nsConnectionEntry *) mCT.Get(&key);
998
1047
999
    NS_ASSERTION(ent, "no connection entry");
1048
    NS_ASSERTION(ent, "no connection entry");
1000
    if (ent) {
1049
    if (ent) {
1001
        ent->mActiveConns.RemoveElement(conn);
1050
        // If the connection is in the active list, remove that entry
1002
        mNumActiveConns--;
1051
        // and the reference held by the mActiveConns list.
1052
        // This is never the final reference on conn as the event context
1053
        // is also holding one that is released at the end of this function.
1054
        if (ent->mActiveConns.RemoveElement(conn)) {
1055
            nsHttpConnection *temp = conn;
1056
            NS_RELEASE(temp);
1057
            mNumActiveConns--;
1058
        }
1059
1003
        if (conn->CanReuse()) {
1060
        if (conn->CanReuse()) {
1004
            LOG(("  adding connection to idle list\n"));
1061
            LOG(("  adding connection to idle list\n"));
1005
            // hold onto this connection in the idle list.  we push it to
1062
            // hold onto this connection in the idle list.  we push it to
1006
            // the end of the list so as to ensure that we'll visit older
1063
            // the end of the list so as to ensure that we'll visit older
1007
            // connections first before getting to this one.
1064
            // connections first before getting to this one.
1065
            NS_ADDREF(conn);
1008
            ent->mIdleConns.AppendElement(conn);
1066
            ent->mIdleConns.AppendElement(conn);
1009
            mNumIdleConns++;
1067
            mNumIdleConns++;
1010
            // If the added connection was first idle connection or has shortest
1068
            // If the added connection was first idle connection or has shortest
1011
            // time to live among the idle connections, pruning dead
1069
            // time to live among the idle connections, pruning dead
1012
            // connections needs to be done when it can't be reused anymore.
1070
            // connections needs to be done when it can't be reused anymore.
1013
            PRUint32 timeToLive = conn->TimeToLive();
1071
            PRUint32 timeToLive = conn->TimeToLive();
1014
            if(!mTimer || NowInSeconds() + timeToLive < mTimeOfNextWakeUp)
1072
            if(!mTimer || NowInSeconds() + timeToLive < mTimeOfNextWakeUp)
1015
                PruneDeadConnectionsAfter(timeToLive);
1073
                PruneDeadConnectionsAfter(timeToLive);
1016
        }
1074
        }
1017
        else {
1075
        else {
1018
            LOG(("  connection cannot be reused; closing connection\n"));
1076
            LOG(("  connection cannot be reused; closing connection\n"));
1019
            // make sure the connection is closed and release our reference.
1077
            // make sure the connection is closed and release our reference.
1020
            conn->Close(NS_ERROR_ABORT);
1078
            conn->Close(NS_ERROR_ABORT);
1021
            nsHttpConnection *temp = conn;
1022
            NS_RELEASE(temp);
1023
        }
1079
        }
1024
    }
1080
    }
1025
 
1081
 
1026
    OnMsgProcessPendingQ(NS_OK, ci); // releases |ci|
1082
    OnMsgProcessPendingQ(NS_OK, ci); // releases |ci|
1027
    NS_RELEASE(conn);
1083
    NS_RELEASE(conn);
1028
}
1084
}
1029
1085
1030
void
1086
void
 Lines 1125-1140   nsHttpConnectionMgr::nsConnectionHandle: Link Here 
1125
}
1181
}
1126
1182
1127
nsresult
1183
nsresult
1128
nsHttpConnectionMgr::nsConnectionHandle::PushBack(const char *buf, PRUint32 bufLen)
1184
nsHttpConnectionMgr::nsConnectionHandle::PushBack(const char *buf, PRUint32 bufLen)
1129
{
1185
{
1130
    return mConn->PushBack(buf, bufLen);
1186
    return mConn->PushBack(buf, bufLen);
1131
}
1187
}
1132
1188
1189
1190
//////////////////////// nsHalfOpenSocket
1191
1192
1193
NS_IMPL_THREADSAFE_ISUPPORTS4(nsHttpConnectionMgr::nsHalfOpenSocket,
1194
                              nsIOutputStreamCallback,
1195
                              nsITransportEventSink,
1196
                              nsIInterfaceRequestor,
1197
                              nsITimerCallback)
1198
1199
nsHttpConnectionMgr::
1200
nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent,
1201
                                   nsHttpTransaction *trans)
1202
    : mEnt(ent),
1203
      mTransaction(trans)
1204
{
1205
    NS_ABORT_IF_FALSE(ent && trans, "constructor with null arguments");
1206
    LOG(("Creating nsHalfOpenSocket [this=%p trans=%p ent=%s]\n",
1207
         this, trans, ent->mConnInfo->Host()));
1208
}
1209
1210
nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket()
1211
{
1212
    NS_ABORT_IF_FALSE(!mStreamOut, "streamout not null");
1213
    NS_ABORT_IF_FALSE(!mBackupStreamOut, "backupstreamout not null");
1214
    NS_ABORT_IF_FALSE(!mSynTimer, "syntimer not null");
1215
    LOG(("Destroying nsHalfOpenSocket [this=%p]\n", this));
1216
    
1217
    if (mEnt) {
1218
        PRInt32 index = mEnt->mHalfOpens.IndexOf(this);
1219
        NS_ABORT_IF_FALSE(index != -1, "half open complete but no item");
1220
        mEnt->mHalfOpens.RemoveElementAt(index);
1221
    }
1222
}
1223
1224
nsresult
1225
nsHttpConnectionMgr::
1226
nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
1227
                               nsIAsyncInputStream **instream,
1228
                               nsIAsyncOutputStream **outstream)
1229
{
1230
    nsresult rv;
1231
1232
    const char* types[1];
1233
    types[0] = (mEnt->mConnInfo->UsingSSL()) ?
1234
        "ssl" : gHttpHandler->DefaultSocketType();
1235
    PRUint32 typeCount = (types[0] != nsnull);
1236
1237
    nsCOMPtr<nsISocketTransport> socketTransport;
1238
    nsCOMPtr<nsISocketTransportService> sts;
1239
1240
    sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
1241
    NS_ENSURE_SUCCESS(rv, rv);
1242
1243
    rv = sts->CreateTransport(types, typeCount,
1244
                              nsDependentCString(mEnt->mConnInfo->Host()),
1245
                              mEnt->mConnInfo->Port(),
1246
                              mEnt->mConnInfo->ProxyInfo(),
1247
                              getter_AddRefs(socketTransport));
1248
    NS_ENSURE_SUCCESS(rv, rv);
1249
    
1250
    PRUint32 tmpFlags = 0;
1251
    if (mTransaction->Caps() & NS_HTTP_REFRESH_DNS)
1252
        tmpFlags = nsISocketTransport::BYPASS_CACHE;
1253
1254
    if (mTransaction->Caps() & NS_HTTP_LOAD_ANONYMOUS)
1255
        tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT;
1256
1257
    socketTransport->SetConnectionFlags(tmpFlags);
1258
1259
    socketTransport->SetQoSBits(gHttpHandler->GetQoSBits());
1260
1261
    rv = socketTransport->SetEventSink(this, nsnull);
1262
    NS_ENSURE_SUCCESS(rv, rv);
1263
1264
    rv = socketTransport->SetSecurityCallbacks(this);
1265
    NS_ENSURE_SUCCESS(rv, rv);
1266
1267
    nsCOMPtr<nsIOutputStream> sout;
1268
    rv = socketTransport->OpenOutputStream(nsITransport::OPEN_UNBUFFERED,
1269
                                            0, 0,
1270
                                            getter_AddRefs(sout));
1271
    NS_ENSURE_SUCCESS(rv, rv);
1272
1273
    nsCOMPtr<nsIInputStream> sin;
1274
    rv = socketTransport->OpenInputStream(nsITransport::OPEN_UNBUFFERED,
1275
                                           0, 0,
1276
                                           getter_AddRefs(sin));
1277
    NS_ENSURE_SUCCESS(rv, rv);
1278
1279
    socketTransport.forget(transport);
1280
    CallQueryInterface(sin, instream);
1281
    CallQueryInterface(sout, outstream);
1282
1283
    rv = (*outstream)->AsyncWait(this, 0, 0, nsnull);
1284
    if (NS_SUCCEEDED(rv))
1285
        gHttpHandler->ConnMgr()->StartedConnect();
1286
1287
    return rv;
1288
}
1289
1290
nsresult
1291
nsHttpConnectionMgr::nsHalfOpenSocket::SetupPrimaryStreams()
1292
{
1293
    nsresult rv = SetupStreams(getter_AddRefs(mSocketTransport),
1294
                               getter_AddRefs(mStreamIn),
1295
                               getter_AddRefs(mStreamOut));
1296
    LOG(("nsHalfOpenSocket::SetupPrimaryStream [this=%p ent=%s rv=%x]",
1297
         this, mEnt->mConnInfo->Host(), rv));
1298
    if (NS_FAILED(rv)) {
1299
        if (mStreamOut)
1300
            mStreamOut->AsyncWait(nsnull, 0, 0, nsnull);
1301
        mStreamOut = nsnull;
1302
        mStreamIn = nsnull;
1303
        mSocketTransport = nsnull;
1304
    }
1305
    return rv;
1306
}
1307
1308
nsresult
1309
nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupStreams()
1310
{
1311
    nsresult rv = SetupStreams(getter_AddRefs(mBackupTransport),
1312
                               getter_AddRefs(mBackupStreamIn),
1313
                               getter_AddRefs(mBackupStreamOut));
1314
    LOG(("nsHalfOpenSocket::SetupBackupStream [this=%p ent=%s rv=%x]",
1315
         this, mEnt->mConnInfo->Host(), rv));
1316
    if (NS_FAILED(rv)) {
1317
        if (mBackupStreamOut)
1318
            mBackupStreamOut->AsyncWait(nsnull, 0, 0, nsnull);
1319
        mBackupStreamOut = nsnull;
1320
        mBackupStreamIn = nsnull;
1321
        mBackupTransport = nsnull;
1322
    }
1323
    return rv;
1324
}
1325
1326
void
1327
nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupTimer()
1328
{
1329
    PRUint16 timeout = gHttpHandler->GetIdleSynTimeout();
1330
    NS_ABORT_IF_FALSE(!mSynTimer, "timer already initd");
1331
    if (timeout) {
1332
        // Setup the timer that will establish a backup socket
1333
        // if we do not get a writable event on the main one.
1334
        // We do this because a lost SYN takes a very long time
1335
        // to repair at the TCP level.
1336
        //
1337
        // Failure to setup the timer is something we can live with,
1338
        // so don't return an error in that case.
1339
        nsresult rv;
1340
        mSynTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
1341
        if (NS_SUCCEEDED(rv))
1342
            mSynTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
1343
    }
1344
}
1345
1346
void
1347
nsHttpConnectionMgr::nsHalfOpenSocket::Abandon()
1348
{
1349
    LOG(("nsHalfOpenSocket::Abandon [this=%p ent=%s]",
1350
         this, mEnt->mConnInfo->Host()));
1351
    nsRefPtr<nsHalfOpenSocket> deleteProtector(this);
1352
1353
    if (mStreamOut) {
1354
        gHttpHandler->ConnMgr()->RecvdConnect();
1355
        mStreamOut->AsyncWait(nsnull, 0, 0, nsnull);
1356
        mStreamOut = nsnull;
1357
    }
1358
    if (mBackupStreamOut) {
1359
        gHttpHandler->ConnMgr()->RecvdConnect();
1360
        mBackupStreamOut->AsyncWait(nsnull, 0, 0, nsnull);
1361
        mBackupStreamOut = nsnull;
1362
    }
1363
    if (mSynTimer) {
1364
        mSynTimer->Cancel();
1365
        mSynTimer = nsnull;
1366
    }
1367
1368
    mEnt = nsnull;
1369
}
1370
1371
NS_IMETHODIMP // method for nsITimerCallback
1372
nsHttpConnectionMgr::nsHalfOpenSocket::Notify(nsITimer *timer)
1373
{
1374
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
1375
    NS_ABORT_IF_FALSE(timer == mSynTimer, "wrong timer");
1376
1377
    mSynTimer = nsnull;
1378
    if (!gHttpHandler->ConnMgr()->
1379
        AtActiveConnectionLimit(mEnt, mTransaction->Caps())) {
1380
        SetupBackupStreams();
1381
    }
1382
    return NS_OK;
1383
}
1384
1385
// method for nsIAsyncOutputStreamCallback
1386
NS_IMETHODIMP
1387
nsHttpConnectionMgr::
1388
nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
1389
{
1390
    NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
1391
    NS_ABORT_IF_FALSE(out == mStreamOut ||
1392
                      out == mBackupStreamOut, "stream mismatch");
1393
    LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n", 
1394
         this, mEnt->mConnInfo->Host(),
1395
         out == mStreamOut ? "primary" : "backup"));
1396
    PRInt32 index;
1397
    nsresult rv;
1398
    
1399
    gHttpHandler->ConnMgr()->RecvdConnect();
1400
1401
    // If the syntimer is still armed, we can cancel it because no backup
1402
    // socket should be formed at this point
1403
    if (mSynTimer) {
1404
        NS_ABORT_IF_FALSE (out == mStreamOut, "timer for non existant stream");
1405
        LOG(("nsHalfOpenSocket::OnOutputStreamReady "
1406
             "Backup connection timer canceled\n"));
1407
        mSynTimer->Cancel();
1408
        mSynTimer = nsnull;
1409
    }
1410
1411
    // assign the new socket to the http connection
1412
    nsRefPtr<nsHttpConnection> conn = new nsHttpConnection();
1413
    LOG(("nsHalfOpenSocket::OnOutputStreamReady "
1414
         "Created new nshttpconnection %p\n", conn));
1415
1416
    nsCOMPtr<nsIInterfaceRequestor> callbacks;
1417
    nsCOMPtr<nsIEventTarget>        callbackTarget;
1418
    mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks),
1419
                                       getter_AddRefs(callbackTarget));
1420
    if (out == mStreamOut) {
1421
        rv = conn->Init(mEnt->mConnInfo,
1422
                        gHttpHandler->ConnMgr()->mMaxRequestDelay,
1423
                        mSocketTransport, mStreamIn, mStreamOut,
1424
                        callbacks, callbackTarget);
1425
1426
        // The nsHttpConnection object now owns these streams and sockets
1427
        mStreamOut = nsnull;
1428
        mStreamIn = nsnull;
1429
        mSocketTransport = nsnull;
1430
    }
1431
    else {
1432
        rv = conn->Init(mEnt->mConnInfo,
1433
                        gHttpHandler->ConnMgr()->mMaxRequestDelay,
1434
                        mBackupTransport, mBackupStreamIn, mBackupStreamOut,
1435
                        callbacks, callbackTarget);
1436
1437
        // The nsHttpConnection object now owns these streams and sockets
1438
        mBackupStreamOut = nsnull;
1439
        mBackupStreamIn = nsnull;
1440
        mBackupTransport = nsnull;
1441
    }
1442
1443
    if (NS_FAILED(rv)) {
1444
        LOG(("nsHalfOpenSocket::OnOutputStreamReady "
1445
             "conn->init (%p) failed %x\n", conn, rv));
1446
        return rv;
1447
    }
1448
1449
    // if this is still in the pending list, remove it and dispatch it
1450
    index = mEnt->mPendingQ.IndexOf(mTransaction);
1451
    if (index != -1) {
1452
        mEnt->mPendingQ.RemoveElementAt(index);
1453
        nsHttpTransaction *temp = mTransaction;
1454
        NS_RELEASE(temp);
1455
        gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt);
1456
        rv = gHttpHandler->ConnMgr()->DispatchTransaction(mEnt, mTransaction,
1457
                                                          mTransaction->Caps(),
1458
                                                          conn);
1459
    }
1460
    else {
1461
        // this transaction was dispatched off the pending q before all the
1462
        // sockets established themselves.
1463
1464
        // We need to establish a small non-zero idle timeout so the connection
1465
        // mgr perceives this socket as suitable for persistent connection reuse
1466
        conn->SetIdleTimeout(NS_MIN((PRUint16) 5, gHttpHandler->IdleTimeout()));
1467
1468
        // After about 1 second allow for the possibility of restarting a
1469
        // transaction due to server close. Keep at sub 1 second as that is the
1470
        // minimum granularity we can expect a server to be timing out with.
1471
        conn->SetIsReusedAfter(950);
1472
1473
        NS_ADDREF(conn);  // because onmsg*() expects to drop a reference
1474
        gHttpHandler->ConnMgr()->OnMsgReclaimConnection(NS_OK, conn);
1475
    }
1476
1477
    return rv;
1478
}
1479
1480
// method for nsITransportEventSink
1481
NS_IMETHODIMP
1482
nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans,
1483
                                                         nsresult status,
1484
                                                         PRUint64 progress,
1485
                                                         PRUint64 progressMax)
1486
{
1487
    if (mTransaction)
1488
        mTransaction->OnTransportStatus(status, progress);
1489
    return NS_OK;
1490
}
1491
1492
// method for nsIInterfaceRequestor
1493
NS_IMETHODIMP
1494
nsHttpConnectionMgr::nsHalfOpenSocket::GetInterface(const nsIID &iid,
1495
                                                    void **result)
1496
{
1497
    if (mTransaction) {
1498
        nsCOMPtr<nsIInterfaceRequestor> callbacks;
1499
        mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), nsnull);
1500
        if (callbacks)
1501
            return callbacks->GetInterface(iid, result);
1502
    }
1503
    return NS_ERROR_NO_INTERFACE;
1504
}
1505
1133
PRBool
1506
PRBool
1134
nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent()
1507
nsHttpConnectionMgr::nsConnectionHandle::LastTransactionExpectedNoContent()
1135
{
1508
{
1136
    return mConn->LastTransactionExpectedNoContent();
1509
    return mConn->LastTransactionExpectedNoContent();
1137
}
1510
}
1138
1511
1139
void
1512
void
1140
nsHttpConnectionMgr::
1513
nsHttpConnectionMgr::
(-)a/netwerk/protocol/http/nsHttpConnectionMgr.h (-5 / +55 lines)
Line     Link Here 
 Lines 42-57    Link Here 
42
#include "nsHttpConnectionInfo.h"
42
#include "nsHttpConnectionInfo.h"
43
#include "nsHttpConnection.h"
43
#include "nsHttpConnection.h"
44
#include "nsHttpTransaction.h"
44
#include "nsHttpTransaction.h"
45
#include "nsTArray.h"
45
#include "nsTArray.h"
46
#include "nsThreadUtils.h"
46
#include "nsThreadUtils.h"
47
#include "nsHashtable.h"
47
#include "nsHashtable.h"
48
#include "nsAutoPtr.h"
48
#include "nsAutoPtr.h"
49
#include "prmon.h"
49
#include "prmon.h"
50
#include "nsISocketTransportService.h"
50
51
51
#include "nsIObserver.h"
52
#include "nsIObserver.h"
52
#include "nsITimer.h"
53
#include "nsITimer.h"
53
54
54
class nsHttpPipeline;
55
class nsHttpPipeline;
55
56
56
//-----------------------------------------------------------------------------
57
//-----------------------------------------------------------------------------
57
58
 Lines 134-150   public: Link Here 
134
    void AddTransactionToPipeline(nsHttpPipeline *);
135
    void AddTransactionToPipeline(nsHttpPipeline *);
135
136
136
    // called to force the transaction queue to be processed once more, giving
137
    // called to force the transaction queue to be processed once more, giving
137
    // preference to the specified connection.
138
    // preference to the specified connection.
138
    nsresult ProcessPendingQ(nsHttpConnectionInfo *);
139
    nsresult ProcessPendingQ(nsHttpConnectionInfo *);
139
140
140
private:
141
private:
141
    virtual ~nsHttpConnectionMgr();
142
    virtual ~nsHttpConnectionMgr();
142
143
    class nsHalfOpenSocket;
144
    
143
    // nsConnectionEntry
145
    // nsConnectionEntry
144
    //
146
    //
145
    // mCT maps connection info hash key to nsConnectionEntry object, which
147
    // mCT maps connection info hash key to nsConnectionEntry object, which
146
    // contains list of active and idle connections as well as the list of
148
    // contains list of active and idle connections as well as the list of
147
    // pending transactions.
149
    // pending transactions.
148
    //
150
    //
149
    struct nsConnectionEntry
151
    struct nsConnectionEntry
150
    {
152
    {
 Lines 154-169   private: Link Here 
154
            NS_ADDREF(mConnInfo);
156
            NS_ADDREF(mConnInfo);
155
        }
157
        }
156
       ~nsConnectionEntry() { NS_RELEASE(mConnInfo); }
158
       ~nsConnectionEntry() { NS_RELEASE(mConnInfo); }
157
159
158
        nsHttpConnectionInfo        *mConnInfo;
160
        nsHttpConnectionInfo        *mConnInfo;
159
        nsTArray<nsHttpTransaction*> mPendingQ;    // pending transaction queue
161
        nsTArray<nsHttpTransaction*> mPendingQ;    // pending transaction queue
160
        nsTArray<nsHttpConnection*>  mActiveConns; // active connections
162
        nsTArray<nsHttpConnection*>  mActiveConns; // active connections
161
        nsTArray<nsHttpConnection*>  mIdleConns;   // idle persistent connections
163
        nsTArray<nsHttpConnection*>  mIdleConns;   // idle persistent connections
164
        nsTArray<nsHalfOpenSocket*>  mHalfOpens;
162
    };
165
    };
163
166
164
    // nsConnectionHandle
167
    // nsConnectionHandle
165
    //
168
    //
166
    // thin wrapper around a real connection, used to keep track of references
169
    // thin wrapper around a real connection, used to keep track of references
167
    // to the connection to determine when the connection may be reused.  the
170
    // to the connection to determine when the connection may be reused.  the
168
    // transaction (or pipeline) owns a reference to this handle.  this extra
171
    // transaction (or pipeline) owns a reference to this handle.  this extra
169
    // layer of indirection greatly simplifies consumer code, avoiding the
172
    // layer of indirection greatly simplifies consumer code, avoiding the
 Lines 177-192   private: Link Here 
177
        NS_DECL_NSAHTTPCONNECTION
180
        NS_DECL_NSAHTTPCONNECTION
178
181
179
        nsConnectionHandle(nsHttpConnection *conn) { NS_ADDREF(mConn = conn); }
182
        nsConnectionHandle(nsHttpConnection *conn) { NS_ADDREF(mConn = conn); }
180
        virtual ~nsConnectionHandle();
183
        virtual ~nsConnectionHandle();
181
184
182
        nsHttpConnection *mConn;
185
        nsHttpConnection *mConn;
183
    };
186
    };
184
187
188
    // nsHalfOpenSocket is used to hold the state of an opening TCP socket
189
    // while we wait for it to establish and bind it to a connection
190
191
    class nsHalfOpenSocket : public nsIOutputStreamCallback,
192
                             public nsITransportEventSink,
193
                             public nsIInterfaceRequestor,
194
                             public nsITimerCallback
195
    {
196
    public:
197
        NS_DECL_ISUPPORTS
198
        NS_DECL_NSIOUTPUTSTREAMCALLBACK
199
        NS_DECL_NSITRANSPORTEVENTSINK
200
        NS_DECL_NSIINTERFACEREQUESTOR
201
        NS_DECL_NSITIMERCALLBACK
202
203
        nsHalfOpenSocket(nsConnectionEntry *ent,
204
                         nsHttpTransaction *trans);
205
        ~nsHalfOpenSocket();
206
        
207
        nsresult SetupStreams(nsISocketTransport **,
208
                              nsIAsyncInputStream **,
209
                              nsIAsyncOutputStream **);
210
        nsresult SetupPrimaryStreams();
211
        nsresult SetupBackupStreams();
212
        void     SetupBackupTimer();
213
        void     Abandon();
214
        
215
    private:
216
        nsConnectionEntry              *mEnt;
217
        nsRefPtr<nsHttpTransaction>    mTransaction;
218
        nsCOMPtr<nsISocketTransport>   mSocketTransport;
219
        nsCOMPtr<nsIAsyncOutputStream> mStreamOut;
220
        nsCOMPtr<nsIAsyncInputStream>  mStreamIn;
221
222
        // for syn retry
223
        nsCOMPtr<nsITimer>             mSynTimer;
224
        nsCOMPtr<nsISocketTransport>   mBackupTransport;
225
        nsCOMPtr<nsIAsyncOutputStream> mBackupStreamOut;
226
        nsCOMPtr<nsIAsyncInputStream>  mBackupStreamIn;
227
    };
228
    friend class nsHalfOpenSocket;
229
185
    //-------------------------------------------------------------------------
230
    //-------------------------------------------------------------------------
186
    // NOTE: these members may be accessed from any thread (use mMonitor)
231
    // NOTE: these members may be accessed from any thread (use mMonitor)
187
    //-------------------------------------------------------------------------
232
    //-------------------------------------------------------------------------
188
233
189
    PRInt32                      mRef;
234
    PRInt32                      mRef;
190
    PRMonitor                   *mMonitor;
235
    PRMonitor                   *mMonitor;
191
    nsCOMPtr<nsIEventTarget>     mSocketThreadTarget;
236
    nsCOMPtr<nsIEventTarget>     mSocketThreadTarget;
192
237
 Lines 201-229   private: Link Here 
201
246
202
    PRPackedBool mIsShuttingDown;
247
    PRPackedBool mIsShuttingDown;
203
248
204
    //-------------------------------------------------------------------------
249
    //-------------------------------------------------------------------------
205
    // NOTE: these members are only accessed on the socket transport thread
250
    // NOTE: these members are only accessed on the socket transport thread
206
    //-------------------------------------------------------------------------
251
    //-------------------------------------------------------------------------
207
252
208
    static PRIntn ProcessOneTransactionCB(nsHashKey *, void *, void *);
253
    static PRIntn ProcessOneTransactionCB(nsHashKey *, void *, void *);
209
    static PRIntn PurgeOneIdleConnectionCB(nsHashKey *, void *, void *);
254
210
    static PRIntn PruneDeadConnectionsCB(nsHashKey *, void *, void *);
255
    static PRIntn PruneDeadConnectionsCB(nsHashKey *, void *, void *);
211
    static PRIntn ShutdownPassCB(nsHashKey *, void *, void *);
256
    static PRIntn ShutdownPassCB(nsHashKey *, void *, void *);
212
257
    static PRIntn PurgeExcessIdleConnectionsCB(nsHashKey *, void *, void *);
213
    PRBool   ProcessPendingQForEntry(nsConnectionEntry *);
258
    PRBool   ProcessPendingQForEntry(nsConnectionEntry *);
214
    PRBool   AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
259
    PRBool   AtActiveConnectionLimit(nsConnectionEntry *, PRUint8 caps);
215
    void     GetConnection(nsConnectionEntry *, PRUint8 caps, nsHttpConnection **);
260
    void     GetConnection(nsConnectionEntry *, nsHttpTransaction *,
261
                           nsHttpConnection **);
216
    nsresult DispatchTransaction(nsConnectionEntry *, nsAHttpTransaction *,
262
    nsresult DispatchTransaction(nsConnectionEntry *, nsAHttpTransaction *,
217
                                 PRUint8 caps, nsHttpConnection *);
263
                                 PRUint8 caps, nsHttpConnection *);
218
    PRBool   BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
264
    PRBool   BuildPipeline(nsConnectionEntry *, nsAHttpTransaction *, nsHttpPipeline **);
219
    nsresult ProcessNewTransaction(nsHttpTransaction *);
265
    nsresult ProcessNewTransaction(nsHttpTransaction *);
220
    nsresult EnsureSocketThreadTargetIfOnline();
266
    nsresult EnsureSocketThreadTargetIfOnline();
221
267
    nsresult CreateTransport(nsConnectionEntry *, nsHttpTransaction *);
268
    void     AddActiveConn(nsHttpConnection *, nsConnectionEntry *);
269
    void     StartedConnect();
270
    void     RecvdConnect();
271
    
222
    // message handlers have this signature
272
    // message handlers have this signature
223
    typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(PRInt32, void *);
273
    typedef void (nsHttpConnectionMgr:: *nsConnEventHandler)(PRInt32, void *);
224
274
225
    // nsConnEvent
275
    // nsConnEvent
226
    //
276
    //
227
    // subclass of nsRunnable used to marshall events to the socket transport
277
    // subclass of nsRunnable used to marshall events to the socket transport
228
    // thread.  this class is used to implement PostEvent.
278
    // thread.  this class is used to implement PostEvent.
229
    //
279
    //
(-)a/netwerk/protocol/http/nsHttpHandler.cpp (+7 lines)
Line     Link Here 
 Lines 174-189   nsHttpHandler::nsHttpHandler() Link Here 
174
    , mHttpVersion(NS_HTTP_VERSION_1_1)
174
    , mHttpVersion(NS_HTTP_VERSION_1_1)
175
    , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
175
    , mProxyHttpVersion(NS_HTTP_VERSION_1_1)
176
    , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
176
    , mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
177
    , mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
177
    , mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
178
    , mReferrerLevel(0xff) // by default we always send a referrer
178
    , mReferrerLevel(0xff) // by default we always send a referrer
179
    , mIdleTimeout(10)
179
    , mIdleTimeout(10)
180
    , mMaxRequestAttempts(10)
180
    , mMaxRequestAttempts(10)
181
    , mMaxRequestDelay(10)
181
    , mMaxRequestDelay(10)
182
    , mIdleSynTimeout(250)
182
    , mMaxConnections(24)
183
    , mMaxConnections(24)
183
    , mMaxConnectionsPerServer(8)
184
    , mMaxConnectionsPerServer(8)
184
    , mMaxPersistentConnectionsPerServer(2)
185
    , mMaxPersistentConnectionsPerServer(2)
185
    , mMaxPersistentConnectionsPerProxy(4)
186
    , mMaxPersistentConnectionsPerProxy(4)
186
    , mMaxPipelinedRequests(2)
187
    , mMaxPipelinedRequests(2)
187
    , mRedirectionLimit(10)
188
    , mRedirectionLimit(10)
188
    , mPhishyUserPassLength(1)
189
    , mPhishyUserPassLength(1)
189
    , mQoSBits(0x00)
190
    , mQoSBits(0x00)
 Lines 923-938   nsHttpHandler::PrefsChanged(nsIPrefBranc Link Here 
923
    }
924
    }
924
925
925
    if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
926
    if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
926
        rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
927
        rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
927
        if (NS_SUCCEEDED(rv))
928
        if (NS_SUCCEEDED(rv))
928
            mRedirectionLimit = (PRUint8) NS_CLAMP(val, 0, 0xff);
929
            mRedirectionLimit = (PRUint8) NS_CLAMP(val, 0, 0xff);
929
    }
930
    }
930
931
932
    if (PREF_CHANGED(HTTP_PREF("connection-retry-timeout"))) {
933
        rv = prefs->GetIntPref(HTTP_PREF("connection-retry-timeout"), &val);
934
        if (NS_SUCCEEDED(rv))
935
            mIdleSynTimeout = (PRUint16) NS_CLAMP(val, 0, 3000);
936
    }
937
931
    if (PREF_CHANGED(HTTP_PREF("version"))) {
938
    if (PREF_CHANGED(HTTP_PREF("version"))) {
932
        nsXPIDLCString httpVersion;
939
        nsXPIDLCString httpVersion;
933
        prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
940
        prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));
934
        if (httpVersion) {
941
        if (httpVersion) {
935
            if (!PL_strcmp(httpVersion, "1.1"))
942
            if (!PL_strcmp(httpVersion, "1.1"))
936
                mHttpVersion = NS_HTTP_VERSION_1_1;
943
                mHttpVersion = NS_HTTP_VERSION_1_1;
937
            else if (!PL_strcmp(httpVersion, "0.9"))
944
            else if (!PL_strcmp(httpVersion, "0.9"))
938
                mHttpVersion = NS_HTTP_VERSION_0_9;
945
                mHttpVersion = NS_HTTP_VERSION_0_9;
(-)a/netwerk/protocol/http/nsHttpHandler.h (+2 lines)
Line     Link Here 
 Lines 102-117   public: Link Here 
102
    PRBool         SendSecureXSiteReferrer() { return mSendSecureXSiteReferrer; }
102
    PRBool         SendSecureXSiteReferrer() { return mSendSecureXSiteReferrer; }
103
    PRUint8        RedirectionLimit()        { return mRedirectionLimit; }
103
    PRUint8        RedirectionLimit()        { return mRedirectionLimit; }
104
    PRUint16       IdleTimeout()             { return mIdleTimeout; }
104
    PRUint16       IdleTimeout()             { return mIdleTimeout; }
105
    PRUint16       MaxRequestAttempts()      { return mMaxRequestAttempts; }
105
    PRUint16       MaxRequestAttempts()      { return mMaxRequestAttempts; }
106
    const char    *DefaultSocketType()       { return mDefaultSocketType.get(); /* ok to return null */ }
106
    const char    *DefaultSocketType()       { return mDefaultSocketType.get(); /* ok to return null */ }
107
    nsIIDNService *IDNConverter()            { return mIDNConverter; }
107
    nsIIDNService *IDNConverter()            { return mIDNConverter; }
108
    PRUint32       PhishyUserPassLength()    { return mPhishyUserPassLength; }
108
    PRUint32       PhishyUserPassLength()    { return mPhishyUserPassLength; }
109
    PRUint8        GetQoSBits()              { return mQoSBits; }
109
    PRUint8        GetQoSBits()              { return mQoSBits; }
110
    PRUint16       GetIdleSynTimeout()       { return mIdleSynTimeout; }
110
    
111
    
111
    PRBool         IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
112
    PRBool         IsPersistentHttpsCachingEnabled() { return mEnablePersistentHttpsCaching; }
112
113
113
    PRBool         PromptTempRedirect()      { return mPromptTempRedirect; }
114
    PRBool         PromptTempRedirect()      { return mPromptTempRedirect; }
114
115
115
    nsHttpAuthCache     *AuthCache() { return &mAuthCache; }
116
    nsHttpAuthCache     *AuthCache() { return &mAuthCache; }
116
    nsHttpConnectionMgr *ConnMgr()   { return mConnMgr; }
117
    nsHttpConnectionMgr *ConnMgr()   { return mConnMgr; }
117
118
 Lines 258-273   private: Link Here 
258
    PRUint8  mProxyHttpVersion;
259
    PRUint8  mProxyHttpVersion;
259
    PRUint8  mCapabilities;
260
    PRUint8  mCapabilities;
260
    PRUint8  mProxyCapabilities;
261
    PRUint8  mProxyCapabilities;
261
    PRUint8  mReferrerLevel;
262
    PRUint8  mReferrerLevel;
262
263
263
    PRUint16 mIdleTimeout;
264
    PRUint16 mIdleTimeout;
264
    PRUint16 mMaxRequestAttempts;
265
    PRUint16 mMaxRequestAttempts;
265
    PRUint16 mMaxRequestDelay;
266
    PRUint16 mMaxRequestDelay;
267
    PRUint16 mIdleSynTimeout;
266
268
267
    PRUint16 mMaxConnections;
269
    PRUint16 mMaxConnections;
268
    PRUint8  mMaxConnectionsPerServer;
270
    PRUint8  mMaxConnectionsPerServer;
269
    PRUint8  mMaxPersistentConnectionsPerServer;
271
    PRUint8  mMaxPersistentConnectionsPerServer;
270
    PRUint8  mMaxPersistentConnectionsPerProxy;
272
    PRUint8  mMaxPersistentConnectionsPerProxy;
271
    PRUint8  mMaxPipelinedRequests;
273
    PRUint8  mMaxPipelinedRequests;
272
274
273
    PRUint8  mRedirectionLimit;
275
    PRUint8  mRedirectionLimit;
(-)a/netwerk/protocol/http/nsHttpPipeline.cpp (-3 / +7 lines)
Line     Link Here 
 Lines 319-344   nsHttpPipeline::SetConnection(nsAHttpCon Link Here 
319
    NS_IF_ADDREF(mConnection = conn);
319
    NS_IF_ADDREF(mConnection = conn);
320
320
321
    PRInt32 i, count = mRequestQ.Length();
321
    PRInt32 i, count = mRequestQ.Length();
322
    for (i=0; i<count; ++i)
322
    for (i=0; i<count; ++i)
323
        Request(i)->SetConnection(this);
323
        Request(i)->SetConnection(this);
324
}
324
}
325
325
326
void
326
void
327
nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result)
327
nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result,
328
                                     nsIEventTarget        **target)
328
{
329
{
329
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
330
    NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
330
331
331
    // return security callbacks from first request
332
    // return security callbacks from first request
332
    nsAHttpTransaction *trans = Request(0);
333
    nsAHttpTransaction *trans = Request(0);
333
    if (trans)
334
    if (trans)
334
        trans->GetSecurityCallbacks(result);
335
        trans->GetSecurityCallbacks(result, target);
335
    else
336
    else {
336
        *result = nsnull;
337
        *result = nsnull;
338
        if (target)
339
            *target = nsnull;
340
    }
337
}
341
}
338
342
339
void
343
void
340
nsHttpPipeline::OnTransportStatus(nsresult status, PRUint64 progress)
344
nsHttpPipeline::OnTransportStatus(nsresult status, PRUint64 progress)
341
{
345
{
342
    LOG(("nsHttpPipeline::OnStatus [this=%x status=%x progress=%llu]\n",
346
    LOG(("nsHttpPipeline::OnStatus [this=%x status=%x progress=%llu]\n",
343
        this, status, progress));
347
        this, status, progress));
344
348
(-)a/netwerk/protocol/http/nsHttpTransaction.cpp (-1 / +4 lines)
Line     Link Here 
 Lines 328-346   nsHttpTransaction::TakeResponseHead() Link Here 
328
void
328
void
329
nsHttpTransaction::SetConnection(nsAHttpConnection *conn)
329
nsHttpTransaction::SetConnection(nsAHttpConnection *conn)
330
{
330
{
331
    NS_IF_RELEASE(mConnection);
331
    NS_IF_RELEASE(mConnection);
332
    NS_IF_ADDREF(mConnection = conn);
332
    NS_IF_ADDREF(mConnection = conn);
333
}
333
}
334
334
335
void
335
void
336
nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb)
336
nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb,
337
                                        nsIEventTarget        **target)
337
{
338
{
338
    NS_IF_ADDREF(*cb = mCallbacks);
339
    NS_IF_ADDREF(*cb = mCallbacks);
340
    if (target)
341
        NS_IF_ADDREF(*target = mConsumerTarget);
339
}
342
}
340
343
341
void
344
void
342
nsHttpTransaction::OnTransportStatus(nsresult status, PRUint64 progress)
345
nsHttpTransaction::OnTransportStatus(nsresult status, PRUint64 progress)
343
{
346
{
344
    LOG(("nsHttpTransaction::OnSocketStatus [this=%x status=%x progress=%llu]\n",
347
    LOG(("nsHttpTransaction::OnSocketStatus [this=%x status=%x progress=%llu]\n",
345
        this, status, progress));
348
        this, status, progress));
346
349

Return to bug 623948