зеркало из https://github.com/mozilla/gecko-dev.git
fixes bug 92224 "8.2.4 Client Behavior if Server Prematurely Closes Connection"
r=bbaetz, sr=mscott
This commit is contained in:
Родитель
fda1d4c471
Коммит
1dd2cdfb3a
|
@ -44,21 +44,28 @@
|
||||||
extern PRLogModuleInfo *gHttpLog;
|
extern PRLogModuleInfo *gHttpLog;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// http logging
|
||||||
#define LOG1(args) PR_LOG(gHttpLog, 1, args)
|
#define LOG1(args) PR_LOG(gHttpLog, 1, args)
|
||||||
#define LOG2(args) PR_LOG(gHttpLog, 2, args)
|
#define LOG2(args) PR_LOG(gHttpLog, 2, args)
|
||||||
#define LOG3(args) PR_LOG(gHttpLog, 3, args)
|
#define LOG3(args) PR_LOG(gHttpLog, 3, args)
|
||||||
#define LOG4(args) PR_LOG(gHttpLog, 4, args)
|
#define LOG4(args) PR_LOG(gHttpLog, 4, args)
|
||||||
#define LOG(args) LOG4(args)
|
#define LOG(args) LOG4(args)
|
||||||
|
|
||||||
|
// http default buffer geometry
|
||||||
#define NS_HTTP_SEGMENT_SIZE 4096
|
#define NS_HTTP_SEGMENT_SIZE 4096
|
||||||
#define NS_HTTP_BUFFER_SIZE 4096*4 // 16k maximum
|
#define NS_HTTP_BUFFER_SIZE 4096*4 // 16k maximum
|
||||||
|
|
||||||
enum nsHttpVersion {
|
// http version codes
|
||||||
NS_HTTP_VERSION_UNKNOWN,
|
#define NS_HTTP_VERSION_UNKNOWN 0
|
||||||
NS_HTTP_VERSION_0_9,
|
#define NS_HTTP_VERSION_0_9 9
|
||||||
NS_HTTP_VERSION_1_0,
|
#define NS_HTTP_VERSION_1_0 10
|
||||||
NS_HTTP_VERSION_1_1
|
#define NS_HTTP_VERSION_1_1 11
|
||||||
};
|
|
||||||
|
typedef PRUint8 nsHttpVersion;
|
||||||
|
|
||||||
|
// http connection capabilities
|
||||||
|
#define NS_HTTP_ALLOW_KEEPALIVE (1<<0)
|
||||||
|
#define NS_HTTP_ALLOW_PIPELINING (1<<1)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// http atoms...
|
// http atoms...
|
||||||
|
@ -117,4 +124,8 @@ PRTimeToSeconds(PRTime t_usec)
|
||||||
|
|
||||||
#define NowInSeconds() PRTimeToSeconds(PR_Now())
|
#define NowInSeconds() PRTimeToSeconds(PR_Now())
|
||||||
|
|
||||||
#endif
|
// ripped from glib.h
|
||||||
|
#undef CLAMP
|
||||||
|
#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
|
||||||
|
|
||||||
|
#endif // nsHttp_h__
|
||||||
|
|
|
@ -52,8 +52,8 @@ nsHttpChannel::nsHttpChannel()
|
||||||
, mPrevTransaction(nsnull)
|
, mPrevTransaction(nsnull)
|
||||||
, mConnectionInfo(nsnull)
|
, mConnectionInfo(nsnull)
|
||||||
, mLoadFlags(LOAD_NORMAL)
|
, mLoadFlags(LOAD_NORMAL)
|
||||||
, mCapabilities(0)
|
|
||||||
, mStatus(NS_OK)
|
, mStatus(NS_OK)
|
||||||
|
, mCapabilities(0)
|
||||||
, mReferrerType(REFERRER_NONE)
|
, mReferrerType(REFERRER_NONE)
|
||||||
, mCachedResponseHead(nsnull)
|
, mCachedResponseHead(nsnull)
|
||||||
, mCacheAccess(0)
|
, mCacheAccess(0)
|
||||||
|
@ -98,7 +98,7 @@ nsHttpChannel::~nsHttpChannel()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpChannel::Init(nsIURI *uri,
|
nsHttpChannel::Init(nsIURI *uri,
|
||||||
PRUint32 caps,
|
PRUint8 caps,
|
||||||
const char *proxyHost,
|
const char *proxyHost,
|
||||||
PRInt32 proxyPort,
|
PRInt32 proxyPort,
|
||||||
const char *proxyType)
|
const char *proxyType)
|
||||||
|
@ -171,8 +171,7 @@ nsHttpChannel::Init(nsIURI *uri,
|
||||||
PRBool useProxy = (proxyHost && !PL_strcmp(proxyType, "http"));
|
PRBool useProxy = (proxyHost && !PL_strcmp(proxyType, "http"));
|
||||||
|
|
||||||
rv = nsHttpHandler::get()->AddStandardRequestHeaders(&mRequestHead.Headers(),
|
rv = nsHttpHandler::get()->AddStandardRequestHeaders(&mRequestHead.Headers(),
|
||||||
caps,
|
caps, useProxy);
|
||||||
useProxy);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// check to see if authorization headers should be included
|
// check to see if authorization headers should be included
|
||||||
|
@ -1922,7 +1921,7 @@ nsHttpChannel::SetReferrer(nsIURI *referrer, PRUint32 referrerType)
|
||||||
mReferrer = referrer;
|
mReferrer = referrer;
|
||||||
|
|
||||||
// save a copy of the referrer type for redirects
|
// save a copy of the referrer type for redirects
|
||||||
mReferrerType = referrerType;
|
mReferrerType = (PRUint8) referrerType;
|
||||||
|
|
||||||
// clear the old referer first
|
// clear the old referer first
|
||||||
mRequestHead.SetHeader(nsHttp::Referer, nsnull);
|
mRequestHead.SetHeader(nsHttp::Referer, nsnull);
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
virtual ~nsHttpChannel();
|
virtual ~nsHttpChannel();
|
||||||
|
|
||||||
nsresult Init(nsIURI *uri,
|
nsresult Init(nsIURI *uri,
|
||||||
PRUint32 capabilities,
|
PRUint8 capabilities,
|
||||||
const char *proxyHost=0,
|
const char *proxyHost=0,
|
||||||
PRInt32 proxyPort=-1,
|
PRInt32 proxyPort=-1,
|
||||||
const char *proxyType=0);
|
const char *proxyType=0);
|
||||||
|
@ -133,9 +133,9 @@ private:
|
||||||
nsXPIDLCString mSpec;
|
nsXPIDLCString mSpec;
|
||||||
|
|
||||||
PRUint32 mLoadFlags;
|
PRUint32 mLoadFlags;
|
||||||
PRUint32 mCapabilities;
|
|
||||||
PRUint32 mStatus;
|
PRUint32 mStatus;
|
||||||
PRUint32 mReferrerType;
|
PRUint8 mCapabilities;
|
||||||
|
PRUint8 mReferrerType;
|
||||||
|
|
||||||
// cache specific data
|
// cache specific data
|
||||||
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;
|
||||||
|
|
|
@ -47,10 +47,8 @@ nsHttpConnection::nsHttpConnection()
|
||||||
: mTransaction(0)
|
: mTransaction(0)
|
||||||
, mConnectionInfo(0)
|
, mConnectionInfo(0)
|
||||||
, mLock(nsnull)
|
, mLock(nsnull)
|
||||||
, mReuseCount(0)
|
|
||||||
, mMaxReuseCount(0)
|
|
||||||
, mIdleTimeout(0)
|
|
||||||
, mLastActiveTime(0)
|
, mLastActiveTime(0)
|
||||||
|
, mIdleTimeout(0)
|
||||||
, mKeepAlive(0)
|
, mKeepAlive(0)
|
||||||
, mWriteDone(0)
|
, mWriteDone(0)
|
||||||
, mReadDone(0)
|
, mReadDone(0)
|
||||||
|
@ -166,30 +164,20 @@ nsHttpConnection::OnHeadersAvailable(nsHttpTransaction *trans, PRBool *reset)
|
||||||
// if this connection is persistent, then the server may send a "Keep-Alive"
|
// if this connection is persistent, then the server may send a "Keep-Alive"
|
||||||
// header specifying the maximum number of times the connection can be
|
// header specifying the maximum number of times the connection can be
|
||||||
// reused as well as the maximum amount of time the connection can be idle
|
// reused as well as the maximum amount of time the connection can be idle
|
||||||
// before the server will close it. If this header is not present, then we
|
// before the server will close it. we ignore the max reuse count, because
|
||||||
// pick a suitably large number. Technically, any number > 0 will do, since
|
// a "keep-alive" connection is by definition capable of being reused, and
|
||||||
// we reset this each time, and with HTTP/1.1 connections continue until we
|
// we only care about being able to reuse it once. if a timeout is not
|
||||||
// get a {Proxy-,}Connection: close header. Don't just use 1 though, because
|
// specified then we use our advertized timeout value.
|
||||||
// of pipelining
|
|
||||||
if (mKeepAlive) {
|
if (mKeepAlive) {
|
||||||
val = trans->ResponseHead()->PeekHeader(nsHttp::Keep_Alive);
|
val = trans->ResponseHead()->PeekHeader(nsHttp::Keep_Alive);
|
||||||
|
|
||||||
LOG(("val = [%s]\n", val));
|
const char *cp = PL_strcasestr(val, "timeout=");
|
||||||
|
|
||||||
const char *cp = PL_strcasestr(val, "max=");
|
|
||||||
if (cp)
|
|
||||||
mMaxReuseCount = (PRUint32) atoi(cp + 4);
|
|
||||||
else
|
|
||||||
mMaxReuseCount = 100;
|
|
||||||
|
|
||||||
cp = PL_strcasestr(val, "timeout=");
|
|
||||||
if (cp)
|
if (cp)
|
||||||
mIdleTimeout = (PRUint32) atoi(cp + 8);
|
mIdleTimeout = (PRUint32) atoi(cp + 8);
|
||||||
else
|
else
|
||||||
mIdleTimeout = nsHttpHandler::get()->IdleTimeout();
|
mIdleTimeout = nsHttpHandler::get()->IdleTimeout();
|
||||||
|
|
||||||
LOG(("Connection can be reused [this=%x max-reuse=%u "
|
LOG(("Connection can be reused [this=%x idle-timeout=%u\n", this, mIdleTimeout));
|
||||||
"keep-alive-timeout=%u\n", this, mMaxReuseCount, mIdleTimeout));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're doing an SSL proxy connect, then we need to check whether or not
|
// if we're doing an SSL proxy connect, then we need to check whether or not
|
||||||
|
@ -302,8 +290,8 @@ nsHttpConnection::ProxyStepUp()
|
||||||
PRBool
|
PRBool
|
||||||
nsHttpConnection::CanReuse()
|
nsHttpConnection::CanReuse()
|
||||||
{
|
{
|
||||||
return mKeepAlive && (mReuseCount < mMaxReuseCount) &&
|
return mKeepAlive && (NowInSeconds() - mLastActiveTime < mIdleTimeout)
|
||||||
(NowInSeconds() - mLastActiveTime < mIdleTimeout) && IsAlive();
|
&& IsAlive();
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
|
|
@ -86,13 +86,9 @@ public:
|
||||||
PRBool CanReuse(); // can this connection be reused?
|
PRBool CanReuse(); // can this connection be reused?
|
||||||
PRBool IsAlive();
|
PRBool IsAlive();
|
||||||
PRBool IsKeepAlive() { return mKeepAlive; }
|
PRBool IsKeepAlive() { return mKeepAlive; }
|
||||||
PRUint32 ReuseCount() { return mReuseCount; }
|
PRUint16 IdleTimeout() { return mIdleTimeout; }
|
||||||
PRUint32 MaxReuseCount() { return mMaxReuseCount; }
|
|
||||||
PRUint32 IdleTimeout() { return mIdleTimeout; }
|
|
||||||
|
|
||||||
void DontReuse() { mKeepAlive = PR_FALSE;
|
void DontReuse() { mKeepAlive = PR_FALSE;
|
||||||
mReuseCount = 0;
|
|
||||||
mMaxReuseCount = 0;
|
|
||||||
mIdleTimeout = 0; }
|
mIdleTimeout = 0; }
|
||||||
|
|
||||||
void DropTransaction();
|
void DropTransaction();
|
||||||
|
@ -126,10 +122,8 @@ private:
|
||||||
|
|
||||||
PRLock *mLock;
|
PRLock *mLock;
|
||||||
|
|
||||||
PRUint32 mReuseCount;
|
|
||||||
PRUint32 mMaxReuseCount; // value of keep-alive: max=
|
|
||||||
PRUint32 mIdleTimeout; // value of keep-alive: timeout=
|
|
||||||
PRUint32 mLastActiveTime;
|
PRUint32 mLastActiveTime;
|
||||||
|
PRUint16 mIdleTimeout; // value of keep-alive: timeout=
|
||||||
|
|
||||||
PRPackedBool mKeepAlive;
|
PRPackedBool mKeepAlive;
|
||||||
PRPackedBool mWriteDone;
|
PRPackedBool mWriteDone;
|
||||||
|
|
|
@ -86,16 +86,13 @@ nsHttpHandler *nsHttpHandler::mGlobalInstance = 0;
|
||||||
nsHttpHandler::nsHttpHandler()
|
nsHttpHandler::nsHttpHandler()
|
||||||
: mAuthCache(nsnull)
|
: mAuthCache(nsnull)
|
||||||
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
, mHttpVersion(NS_HTTP_VERSION_1_1)
|
||||||
, mReferrerLevel(PRUint32(-1)) // by default we always send a referrer
|
, mReferrerLevel(0xff) // by default we always send a referrer
|
||||||
, mCapabilities(ALLOW_KEEPALIVE)
|
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
||||||
, mProxyCapabilities(ALLOW_KEEPALIVE)
|
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
|
||||||
, mProxySSLConnectAllowed(PR_TRUE)
|
|
||||||
, mConnectTimeout(30)
|
|
||||||
, mRequestTimeout(30)
|
|
||||||
, mIdleTimeout(10)
|
, mIdleTimeout(10)
|
||||||
|
, mMaxRequestAttempts(10)
|
||||||
, mMaxConnections(16)
|
, mMaxConnections(16)
|
||||||
, mMaxConnectionsPerServer(8)
|
, mMaxConnectionsPerServer(8)
|
||||||
, mMaxIdleConnections(16)
|
|
||||||
, mMaxIdleConnectionsPerServer(4)
|
, mMaxIdleConnectionsPerServer(4)
|
||||||
, mActiveConnections(0)
|
, mActiveConnections(0)
|
||||||
, mIdleConnections(0)
|
, mIdleConnections(0)
|
||||||
|
@ -243,7 +240,7 @@ nsHttpHandler::Init()
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
||||||
PRUint32 caps,
|
PRUint8 caps,
|
||||||
PRBool useProxy)
|
PRBool useProxy)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
@ -275,15 +272,16 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
||||||
// and "Keep-alive" request headers should not be sent by HTTP/1.1
|
// and "Keep-alive" request headers should not be sent by HTTP/1.1
|
||||||
// user-agents. Otherwise, problems with proxy servers (especially
|
// user-agents. Otherwise, problems with proxy servers (especially
|
||||||
// transparent proxies) can result.
|
// transparent proxies) can result.
|
||||||
|
//
|
||||||
// However, we need to send something so that we can use keepalive
|
// However, we need to send something so that we can use keepalive
|
||||||
// with HTTP/1.0 servers/proxies. We use Proxy-Connection: when we're
|
// with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
|
||||||
// talking to an http proxy, and Connection: otherwise
|
// we're talking to an http proxy, and "Connection:" otherwise
|
||||||
|
|
||||||
const char* connectionType = "close";
|
const char* connectionType = "close";
|
||||||
if (caps & ALLOW_KEEPALIVE) {
|
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
|
||||||
PR_snprintf(buf, sizeof(buf), "%d", mIdleTimeout);
|
PR_snprintf(buf, sizeof(buf), "%u", (PRUintn) mIdleTimeout);
|
||||||
|
|
||||||
rv = request->SetHeader(nsHttp::Keep_Alive, buf);
|
rv = request->SetHeader(nsHttp::Keep_Alive, buf);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
@ -294,8 +292,9 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
|
||||||
request->SetHeader(nsHttp::Connection, "close");
|
request->SetHeader(nsHttp::Connection, "close");
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsHttpAtom& connAtom = useProxy ? nsHttp::Proxy_Connection : nsHttp::Connection;
|
const nsHttpAtom &header =
|
||||||
return request->SetHeader(connAtom, connectionType);
|
useProxy ? nsHttp::Proxy_Connection : nsHttp::Connection;
|
||||||
|
return request->SetHeader(header, connectionType);
|
||||||
}
|
}
|
||||||
|
|
||||||
PRBool
|
PRBool
|
||||||
|
@ -632,7 +631,7 @@ nsHttpHandler::ProcessTransactionQ()
|
||||||
|
|
||||||
PRInt32 i;
|
PRInt32 i;
|
||||||
for (i=0; (i < mTransactionQ.Count()) &&
|
for (i=0; (i < mTransactionQ.Count()) &&
|
||||||
(mActiveConnections.Count() < mMaxConnections); ++i) {
|
(mActiveConnections.Count() < PRInt32(mMaxConnections)); ++i) {
|
||||||
|
|
||||||
pt = (nsPendingTransaction *) mTransactionQ[i];
|
pt = (nsPendingTransaction *) mTransactionQ[i];
|
||||||
|
|
||||||
|
@ -677,8 +676,8 @@ nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
|
||||||
|
|
||||||
LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy));
|
LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy));
|
||||||
|
|
||||||
if ((mActiveConnections.Count() == mMaxConnections) ||
|
if ((mActiveConnections.Count() == PRInt32(mMaxConnections)) ||
|
||||||
(CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) {
|
(CountActiveConnections(ci) == mMaxConnectionsPerServer)) {
|
||||||
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
|
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
|
||||||
if (failIfBusy) return NS_ERROR_FAILURE;
|
if (failIfBusy) return NS_ERROR_FAILURE;
|
||||||
return EnqueueTransaction(trans, ci);
|
return EnqueueTransaction(trans, ci);
|
||||||
|
@ -775,10 +774,10 @@ nsHttpHandler::RemovePendingTransaction(nsHttpTransaction *trans)
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32
|
PRUint8
|
||||||
nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
|
nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
|
||||||
{
|
{
|
||||||
PRUint32 count = 0;
|
PRUint8 count = 0;
|
||||||
nsHttpConnection *conn = 0;
|
nsHttpConnection *conn = 0;
|
||||||
|
|
||||||
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n",
|
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n",
|
||||||
|
@ -792,14 +791,14 @@ nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("found count=%u\n", count));
|
LOG(("found count=%u\n", (PRUintn) count));
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRUint32
|
PRUint8
|
||||||
nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
|
nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
|
||||||
{
|
{
|
||||||
PRUint32 count = 0;
|
PRUint8 count = 0;
|
||||||
nsHttpConnection *conn = 0;
|
nsHttpConnection *conn = 0;
|
||||||
|
|
||||||
if (!ci)
|
if (!ci)
|
||||||
|
@ -824,7 +823,7 @@ nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(("found count=%u\n", count));
|
LOG(("found count=%u\n", (PRUintn) count));
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,18 +1048,51 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
PRInt32 val;
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.timeout") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.timeout") == 0) {
|
||||||
mPrefs->GetIntPref("network.http.keep-alive.timeout", &mIdleTimeout);
|
rv = mPrefs->GetIntPref("network.http.keep-alive.timeout", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mIdleTimeout = (PRUint16) CLAMP(val, 1, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.request.max-attempts") == 0) {
|
||||||
mPrefs->GetIntPref("network.http.max-connections", &mMaxConnections);
|
rv = mPrefs->GetIntPref("network.http.request.max-attempts", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mMaxRequestAttempts = (PRUint16) CLAMP(val, 1, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections-per-server") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections") == 0) {
|
||||||
mPrefs->GetIntPref("network.http.max-connections-per-server", &mMaxConnectionsPerServer);
|
rv = mPrefs->GetIntPref("network.http.max-connections", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mMaxConnections = (PRUint16) CLAMP(val, 1, 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.sendRefererHeader") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections-per-server") == 0) {
|
||||||
mPrefs->GetIntPref("network.http.sendRefererHeader", (PRInt32 *) &mReferrerLevel);
|
rv = mPrefs->GetIntPref("network.http.max-connections-per-server", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mMaxConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections") == 0) {
|
||||||
|
rv = mPrefs->GetIntPref("network.http.keep-alive.max-connections", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mMaxIdleConnections = (PRUint16) CLAMP(val, 1, 0xffff);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections-per-server") == 0) {
|
||||||
|
rv = mPrefs->GetIntPref("network.http.keep-alive.max-connections-per-server", &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mMaxIdleConnectionsPerServer = (PRUint8) CLAMP(val, 1, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bChangedAll || PL_strcmp(pref, "network.http.sendRefererHeader") == 0) {
|
||||||
|
rv = mPrefs->GetIntPref("network.http.sendRefererHeader", (PRInt32 *) &val);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mReferrerLevel = (PRUint8) CLAMP(val, 0, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.version") == 0) {
|
if (bChangedAll || PL_strcmp(pref, "network.http.version") == 0) {
|
||||||
nsXPIDLCString httpVersion;
|
nsXPIDLCString httpVersion;
|
||||||
|
@ -1076,8 +1108,8 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHttpVersion == NS_HTTP_VERSION_1_1) {
|
if (mHttpVersion == NS_HTTP_VERSION_1_1) {
|
||||||
mCapabilities = ALLOW_KEEPALIVE;
|
mCapabilities = NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
mProxyCapabilities = ALLOW_KEEPALIVE;
|
mProxyCapabilities = NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mCapabilities = 0;
|
mCapabilities = 0;
|
||||||
|
@ -1091,9 +1123,9 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
rv = mPrefs->GetBoolPref("network.http.keep-alive", &cVar);
|
rv = mPrefs->GetBoolPref("network.http.keep-alive", &cVar);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
if (cVar)
|
if (cVar)
|
||||||
mCapabilities |= ALLOW_KEEPALIVE;
|
mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
else
|
else
|
||||||
mCapabilities &= ~ALLOW_KEEPALIVE;
|
mCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,9 +1133,9 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
rv = mPrefs->GetBoolPref("network.http.proxy.keep-alive", &cVar);
|
rv = mPrefs->GetBoolPref("network.http.proxy.keep-alive", &cVar);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
if (cVar)
|
if (cVar)
|
||||||
mProxyCapabilities |= ALLOW_KEEPALIVE;
|
mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
else
|
else
|
||||||
mProxyCapabilities &= ~ALLOW_KEEPALIVE;
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_KEEPALIVE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1111,9 +1143,9 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
rv = mPrefs->GetBoolPref("network.http.pipelining", &cVar);
|
rv = mPrefs->GetBoolPref("network.http.pipelining", &cVar);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
if (cVar)
|
if (cVar)
|
||||||
mCapabilities |= ALLOW_PIPELINING;
|
mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
||||||
else
|
else
|
||||||
mCapabilities &= ~ALLOW_PIPELINING;
|
mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,26 +1161,27 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
rv = mPrefs->GetBoolPref("network.http.proxy.pipelining", &cVar);
|
rv = mPrefs->GetBoolPref("network.http.proxy.pipelining", &cVar);
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
if (cVar)
|
if (cVar)
|
||||||
mProxyCapabilities |= ALLOW_PIPELINING;
|
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
|
||||||
else
|
else
|
||||||
mProxyCapabilities &= ~ALLOW_PIPELINING;
|
mProxyCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.proxy.ssl.connect") == 0)
|
/*
|
||||||
mPrefs->GetBoolPref("network.http.proxy.ssl.connect", &mProxySSLConnectAllowed);
|
if (bChangedAll || PL_strcmp(pref, "network.http.proxy.ssl.connect") == 0) {
|
||||||
|
rv = mPrefs->GetBoolPref("network.http.proxy.ssl.connect", &cVar);
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
|
mProxySSLConnectAllowed = (cVar != 0);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.connect.timeout") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.connect.timeout") == 0)
|
||||||
mPrefs->GetIntPref("network.http.connect.timeout", &mConnectTimeout);
|
mPrefs->GetIntPref("network.http.connect.timeout", &mConnectTimeout);
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.request.timeout") == 0)
|
if (bChangedAll || PL_strcmp(pref, "network.http.request.timeout") == 0)
|
||||||
mPrefs->GetIntPref("network.http.request.timeout", &mRequestTimeout);
|
mPrefs->GetIntPref("network.http.request.timeout", &mRequestTimeout);
|
||||||
|
*/
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections") == 0)
|
|
||||||
mPrefs->GetIntPref("network.http.keep-alive.max-connections", &mMaxIdleConnections);
|
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.max-connections-per-server") == 0)
|
|
||||||
mPrefs->GetIntPref("network.http.keep-alive.max-connections-per-server", &mMaxIdleConnectionsPerServer);
|
|
||||||
|
|
||||||
if (bChangedAll || PL_strcmp(pref, INTL_ACCEPT_LANGUAGES) == 0) {
|
if (bChangedAll || PL_strcmp(pref, INTL_ACCEPT_LANGUAGES) == 0) {
|
||||||
nsXPIDLString acceptLanguages;
|
nsXPIDLString acceptLanguages;
|
||||||
|
@ -1168,9 +1201,8 @@ nsHttpHandler::PrefsChanged(const char *pref)
|
||||||
|
|
||||||
// general.useragent.override
|
// general.useragent.override
|
||||||
if (bChangedAll || PL_strcmp(pref, UA_PREF_PREFIX "override") == 0) {
|
if (bChangedAll || PL_strcmp(pref, UA_PREF_PREFIX "override") == 0) {
|
||||||
char* temp = 0;
|
char *temp = 0;
|
||||||
rv = mPrefs->CopyCharPref(UA_PREF_PREFIX "override",
|
rv = mPrefs->CopyCharPref(UA_PREF_PREFIX "override", &temp);
|
||||||
&temp);
|
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
mUserAgentOverride.Adopt(temp);
|
mUserAgentOverride.Adopt(temp);
|
||||||
temp = 0;
|
temp = 0;
|
||||||
|
@ -1589,7 +1621,6 @@ nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = NewProxyChannel(uri,
|
rv = NewProxyChannel(uri,
|
||||||
|
|
||||||
nsnull,
|
nsnull,
|
||||||
-1,
|
-1,
|
||||||
nsnull,
|
nsnull,
|
||||||
|
@ -1627,10 +1658,10 @@ nsHttpHandler::NewProxyChannel(nsIURI *uri,
|
||||||
NS_ADDREF(httpChannel);
|
NS_ADDREF(httpChannel);
|
||||||
|
|
||||||
nsresult rv = httpChannel->Init(uri,
|
nsresult rv = httpChannel->Init(uri,
|
||||||
mCapabilities,
|
mCapabilities,
|
||||||
proxyHost,
|
proxyHost,
|
||||||
proxyPort,
|
proxyPort,
|
||||||
proxyType);
|
proxyType);
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
rv = httpChannel->
|
rv = httpChannel->
|
||||||
|
|
|
@ -64,11 +64,6 @@ public:
|
||||||
NS_DECL_NSIHTTPPROTOCOLHANDLER
|
NS_DECL_NSIHTTPPROTOCOLHANDLER
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
|
||||||
enum {
|
|
||||||
ALLOW_KEEPALIVE = 1 << 0,
|
|
||||||
ALLOW_PIPELINING = 1 << 1
|
|
||||||
};
|
|
||||||
|
|
||||||
nsHttpHandler();
|
nsHttpHandler();
|
||||||
virtual ~nsHttpHandler();
|
virtual ~nsHttpHandler();
|
||||||
|
|
||||||
|
@ -81,15 +76,15 @@ public:
|
||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *,
|
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *,
|
||||||
PRUint32 capabilities,
|
PRUint8 capabilities,
|
||||||
PRBool useProxy);
|
PRBool useProxy);
|
||||||
PRBool IsAcceptableEncoding(const char *encoding);
|
PRBool IsAcceptableEncoding(const char *encoding);
|
||||||
|
|
||||||
const char *UserAgent();
|
const char *UserAgent();
|
||||||
nsHttpVersion DefaultVersion() { return (nsHttpVersion) mHttpVersion; }
|
nsHttpVersion DefaultVersion() { return mHttpVersion; }
|
||||||
PRUint32 ReferrerLevel() { return mReferrerLevel; }
|
PRUint8 ReferrerLevel() { return mReferrerLevel; }
|
||||||
|
PRUint16 IdleTimeout() { return mIdleTimeout; }
|
||||||
PRUint32 IdleTimeout() { return mIdleTimeout; }
|
PRUint16 MaxRequestAttempts() { return mMaxRequestAttempts; }
|
||||||
|
|
||||||
nsHttpAuthCache *AuthCache() { return mAuthCache; }
|
nsHttpAuthCache *AuthCache() { return mAuthCache; }
|
||||||
|
|
||||||
|
@ -173,8 +168,8 @@ private:
|
||||||
|
|
||||||
nsresult RemovePendingTransaction(nsHttpTransaction *);
|
nsresult RemovePendingTransaction(nsHttpTransaction *);
|
||||||
|
|
||||||
PRUint32 CountActiveConnections(nsHttpConnectionInfo *);
|
PRUint8 CountActiveConnections(nsHttpConnectionInfo *);
|
||||||
PRUint32 CountIdleConnections(nsHttpConnectionInfo *);
|
PRUint8 CountIdleConnections(nsHttpConnectionInfo *);
|
||||||
|
|
||||||
void DropConnections(nsVoidArray &);
|
void DropConnections(nsVoidArray &);
|
||||||
|
|
||||||
|
@ -213,20 +208,17 @@ private:
|
||||||
// prefs
|
// prefs
|
||||||
//
|
//
|
||||||
|
|
||||||
PRUint32 mHttpVersion;
|
PRUint8 mHttpVersion;
|
||||||
PRUint32 mReferrerLevel;
|
PRUint8 mReferrerLevel;
|
||||||
PRUint32 mCapabilities;
|
PRUint8 mCapabilities;
|
||||||
PRUint32 mProxyCapabilities;
|
PRUint8 mProxyCapabilities;
|
||||||
PRBool mProxySSLConnectAllowed;
|
|
||||||
|
|
||||||
PRInt32 mConnectTimeout;
|
PRUint16 mIdleTimeout;
|
||||||
PRInt32 mRequestTimeout;
|
PRUint16 mMaxRequestAttempts;
|
||||||
PRInt32 mIdleTimeout;
|
|
||||||
|
|
||||||
PRInt32 mMaxConnections;
|
PRUint16 mMaxConnections;
|
||||||
PRInt32 mMaxConnectionsPerServer;
|
PRUint8 mMaxConnectionsPerServer;
|
||||||
PRInt32 mMaxIdleConnections;
|
PRUint8 mMaxIdleConnectionsPerServer;
|
||||||
PRInt32 mMaxIdleConnectionsPerServer;
|
|
||||||
|
|
||||||
nsCString mAccept;
|
nsCString mAccept;
|
||||||
nsCString mAcceptLanguages;
|
nsCString mAcceptLanguages;
|
||||||
|
|
|
@ -57,7 +57,7 @@ nsHttpResponseHead::Flatten(nsACString &buf, PRBool pruneTransients)
|
||||||
buf.Append("1.0 ");
|
buf.Append("1.0 ");
|
||||||
|
|
||||||
char b[32];
|
char b[32];
|
||||||
PR_snprintf(b, sizeof(b), "%d", mStatus);
|
PR_snprintf(b, sizeof(b), "%u", PRUintn(mStatus));
|
||||||
|
|
||||||
buf.Append(b);
|
buf.Append(b);
|
||||||
buf.Append(' ');
|
buf.Append(' ');
|
||||||
|
@ -144,28 +144,26 @@ nsHttpResponseHead::ParseStatusLine(char *line)
|
||||||
if ((mVersion == NS_HTTP_VERSION_0_9) || !(line = PL_strchr(line, ' '))) {
|
if ((mVersion == NS_HTTP_VERSION_0_9) || !(line = PL_strchr(line, ' '))) {
|
||||||
mStatus = 200;
|
mStatus = 200;
|
||||||
mStatusText.Adopt(nsCRT::strdup("OK"));
|
mStatusText.Adopt(nsCRT::strdup("OK"));
|
||||||
LOG(("Have status line [version=%d status=%d statusText=%s]\n",
|
|
||||||
mVersion, mStatus, mStatusText.get()));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
// Status-Code
|
// Status-Code
|
||||||
mStatus = atoi(++line);
|
mStatus = (PRUint16) atoi(++line);
|
||||||
if (mStatus == 0) {
|
if (mStatus == 0) {
|
||||||
LOG(("mal-formed response status; assuming status = 200\n"));
|
LOG(("mal-formed response status; assuming status = 200\n"));
|
||||||
mStatus = 200;
|
mStatus = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reason-Phrase is whatever is remaining of the line
|
||||||
|
if (!(line = PL_strchr(line, ' '))) {
|
||||||
|
LOG(("mal-formed response status line; assuming statusText = 'OK'\n"));
|
||||||
|
mStatusText.Adopt(nsCRT::strdup("OK"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mStatusText.Adopt(nsCRT::strdup(++line));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reason-Phrase is whatever is remaining of the line
|
LOG(("Have status line [version=%u status=%u statusText=%s]\n",
|
||||||
if (!(line = PL_strchr(line, ' '))) {
|
PRUintn(mVersion), PRUintn(mStatus), mStatusText.get()));
|
||||||
LOG(("mal-formed response status line; assuming statusText = 'OK'\n"));
|
|
||||||
mStatusText.Adopt(nsCRT::strdup("OK"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mStatusText.Adopt(nsCRT::strdup(++line));
|
|
||||||
|
|
||||||
LOG(("Have status line [version=%d status=%d statusText=%s]\n",
|
|
||||||
mVersion, mStatus, mStatusText.get()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
|
|
||||||
nsHttpHeaderArray &Headers() { return mHeaders; }
|
nsHttpHeaderArray &Headers() { return mHeaders; }
|
||||||
nsHttpVersion Version() { return mVersion; }
|
nsHttpVersion Version() { return mVersion; }
|
||||||
PRUint32 Status() { return mStatus; }
|
PRUint16 Status() { return mStatus; }
|
||||||
const char *StatusText() { return mStatusText; }
|
const char *StatusText() { return mStatusText; }
|
||||||
PRInt32 ContentLength() { return mContentLength; }
|
PRInt32 ContentLength() { return mContentLength; }
|
||||||
const char *ContentType() { return mContentType; }
|
const char *ContentType() { return mContentType; }
|
||||||
|
@ -98,7 +98,7 @@ private:
|
||||||
private:
|
private:
|
||||||
nsHttpHeaderArray mHeaders;
|
nsHttpHeaderArray mHeaders;
|
||||||
nsHttpVersion mVersion;
|
nsHttpVersion mVersion;
|
||||||
PRUint32 mStatus;
|
PRUint16 mStatus;
|
||||||
nsXPIDLCString mStatusText;
|
nsXPIDLCString mStatusText;
|
||||||
PRInt32 mContentLength;
|
PRInt32 mContentLength;
|
||||||
nsXPIDLCString mContentType;
|
nsXPIDLCString mContentType;
|
||||||
|
|
|
@ -48,6 +48,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
|
||||||
, mChunkedDecoder(nsnull)
|
, mChunkedDecoder(nsnull)
|
||||||
, mTransactionDone(0)
|
, mTransactionDone(0)
|
||||||
, mStatus(NS_OK)
|
, mStatus(NS_OK)
|
||||||
|
, mRestartCount(0)
|
||||||
, mHaveStatusLine(PR_FALSE)
|
, mHaveStatusLine(PR_FALSE)
|
||||||
, mHaveAllHeaders(PR_FALSE)
|
, mHaveAllHeaders(PR_FALSE)
|
||||||
, mFiredOnStart(PR_FALSE)
|
, mFiredOnStart(PR_FALSE)
|
||||||
|
@ -182,6 +183,12 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is)
|
||||||
|
|
||||||
// check if this transaction needs to be restarted
|
// check if this transaction needs to be restarted
|
||||||
if (mPrematureEOF) {
|
if (mPrematureEOF) {
|
||||||
|
// limit the number of restart attempts - bug 92224
|
||||||
|
if (++mRestartCount >= nsHttpHandler::get()->MaxRequestAttempts()) {
|
||||||
|
LOG(("reached max request attempts, failing transaction @%x\n", this));
|
||||||
|
return NS_BINDING_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
mPrematureEOF = PR_FALSE;
|
mPrematureEOF = PR_FALSE;
|
||||||
|
|
||||||
LOG(("restarting transaction @%x\n", this));
|
LOG(("restarting transaction @%x\n", this));
|
||||||
|
@ -474,8 +481,10 @@ nsHttpTransaction::HandleContent(char *buf,
|
||||||
// headers. So, unless the connection is keep-alive, we must make
|
// headers. So, unless the connection is keep-alive, we must make
|
||||||
// allowances for a possibly invalid Content-Length header. Thus, if
|
// allowances for a possibly invalid Content-Length header. Thus, if
|
||||||
// NOT keep-alive, we simply accept everything in |buf|.
|
// NOT keep-alive, we simply accept everything in |buf|.
|
||||||
if (mConnection->IsKeepAlive())
|
if (mConnection->IsKeepAlive()) {
|
||||||
*countRead = PR_MIN(count, mContentLength - mContentRead);
|
*countRead = PRUint32(mContentLength) - mContentRead;
|
||||||
|
*countRead = PR_MIN(count, *countRead);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
*countRead = count;
|
*countRead = count;
|
||||||
// mContentLength might need to be increased...
|
// mContentLength might need to be increased...
|
||||||
|
|
|
@ -126,10 +126,12 @@ private:
|
||||||
PRInt32 mTransactionDone; // set atomically
|
PRInt32 mTransactionDone; // set atomically
|
||||||
nsresult mStatus;
|
nsresult mStatus;
|
||||||
|
|
||||||
|
PRUint16 mRestartCount; // the number of times this transaction has been restarted
|
||||||
|
|
||||||
PRPackedBool mHaveStatusLine;
|
PRPackedBool mHaveStatusLine;
|
||||||
PRPackedBool mHaveAllHeaders;
|
PRPackedBool mHaveAllHeaders;
|
||||||
PRPackedBool mFiredOnStart;
|
PRPackedBool mFiredOnStart;
|
||||||
PRPackedBool mNoContent; // true if we're expecting an empty entity body
|
PRPackedBool mNoContent; // expecting an empty entity body?
|
||||||
PRPackedBool mPrematureEOF;
|
PRPackedBool mPrematureEOF;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче