fixes bug 92224 "8.2.4 Client Behavior if Server Prematurely Closes Connection"

r=bbaetz, sr=mscott
This commit is contained in:
darin%netscape.com 2001-08-14 01:03:27 +00:00
Родитель fda1d4c471
Коммит 1dd2cdfb3a
11 изменённых файлов: 174 добавлений и 150 удалений

Просмотреть файл

@ -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;
}; };