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
Родитель cc57e5230a
Коммит c4d52e8eb2
11 изменённых файлов: 174 добавлений и 150 удалений

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

@ -44,21 +44,28 @@
extern PRLogModuleInfo *gHttpLog;
#endif
// http logging
#define LOG1(args) PR_LOG(gHttpLog, 1, args)
#define LOG2(args) PR_LOG(gHttpLog, 2, args)
#define LOG3(args) PR_LOG(gHttpLog, 3, args)
#define LOG4(args) PR_LOG(gHttpLog, 4, args)
#define LOG(args) LOG4(args)
// http default buffer geometry
#define NS_HTTP_SEGMENT_SIZE 4096
#define NS_HTTP_BUFFER_SIZE 4096*4 // 16k maximum
enum nsHttpVersion {
NS_HTTP_VERSION_UNKNOWN,
NS_HTTP_VERSION_0_9,
NS_HTTP_VERSION_1_0,
NS_HTTP_VERSION_1_1
};
// http version codes
#define NS_HTTP_VERSION_UNKNOWN 0
#define NS_HTTP_VERSION_0_9 9
#define NS_HTTP_VERSION_1_0 10
#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...
@ -117,4 +124,8 @@ PRTimeToSeconds(PRTime t_usec)
#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)
, mConnectionInfo(nsnull)
, mLoadFlags(LOAD_NORMAL)
, mCapabilities(0)
, mStatus(NS_OK)
, mCapabilities(0)
, mReferrerType(REFERRER_NONE)
, mCachedResponseHead(nsnull)
, mCacheAccess(0)
@ -98,7 +98,7 @@ nsHttpChannel::~nsHttpChannel()
nsresult
nsHttpChannel::Init(nsIURI *uri,
PRUint32 caps,
PRUint8 caps,
const char *proxyHost,
PRInt32 proxyPort,
const char *proxyType)
@ -171,8 +171,7 @@ nsHttpChannel::Init(nsIURI *uri,
PRBool useProxy = (proxyHost && !PL_strcmp(proxyType, "http"));
rv = nsHttpHandler::get()->AddStandardRequestHeaders(&mRequestHead.Headers(),
caps,
useProxy);
caps, useProxy);
if (NS_FAILED(rv)) return rv;
// check to see if authorization headers should be included
@ -1922,7 +1921,7 @@ nsHttpChannel::SetReferrer(nsIURI *referrer, PRUint32 referrerType)
mReferrer = referrer;
// save a copy of the referrer type for redirects
mReferrerType = referrerType;
mReferrerType = (PRUint8) referrerType;
// clear the old referer first
mRequestHead.SetHeader(nsHttp::Referer, nsnull);

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

@ -73,7 +73,7 @@ public:
virtual ~nsHttpChannel();
nsresult Init(nsIURI *uri,
PRUint32 capabilities,
PRUint8 capabilities,
const char *proxyHost=0,
PRInt32 proxyPort=-1,
const char *proxyType=0);
@ -133,9 +133,9 @@ private:
nsXPIDLCString mSpec;
PRUint32 mLoadFlags;
PRUint32 mCapabilities;
PRUint32 mStatus;
PRUint32 mReferrerType;
PRUint8 mCapabilities;
PRUint8 mReferrerType;
// cache specific data
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry;

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

@ -47,10 +47,8 @@ nsHttpConnection::nsHttpConnection()
: mTransaction(0)
, mConnectionInfo(0)
, mLock(nsnull)
, mReuseCount(0)
, mMaxReuseCount(0)
, mIdleTimeout(0)
, mLastActiveTime(0)
, mIdleTimeout(0)
, mKeepAlive(0)
, mWriteDone(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"
// 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
// before the server will close it. If this header is not present, then we
// pick a suitably large number. Technically, any number > 0 will do, since
// we reset this each time, and with HTTP/1.1 connections continue until we
// get a {Proxy-,}Connection: close header. Don't just use 1 though, because
// of pipelining
// before the server will close it. we ignore the max reuse count, because
// a "keep-alive" connection is by definition capable of being reused, and
// we only care about being able to reuse it once. if a timeout is not
// specified then we use our advertized timeout value.
if (mKeepAlive) {
val = trans->ResponseHead()->PeekHeader(nsHttp::Keep_Alive);
LOG(("val = [%s]\n", val));
const char *cp = PL_strcasestr(val, "max=");
if (cp)
mMaxReuseCount = (PRUint32) atoi(cp + 4);
else
mMaxReuseCount = 100;
cp = PL_strcasestr(val, "timeout=");
const char *cp = PL_strcasestr(val, "timeout=");
if (cp)
mIdleTimeout = (PRUint32) atoi(cp + 8);
else
mIdleTimeout = nsHttpHandler::get()->IdleTimeout();
LOG(("Connection can be reused [this=%x max-reuse=%u "
"keep-alive-timeout=%u\n", this, mMaxReuseCount, mIdleTimeout));
LOG(("Connection can be reused [this=%x idle-timeout=%u\n", this, mIdleTimeout));
}
// if we're doing an SSL proxy connect, then we need to check whether or not
@ -302,8 +290,8 @@ nsHttpConnection::ProxyStepUp()
PRBool
nsHttpConnection::CanReuse()
{
return mKeepAlive && (mReuseCount < mMaxReuseCount) &&
(NowInSeconds() - mLastActiveTime < mIdleTimeout) && IsAlive();
return mKeepAlive && (NowInSeconds() - mLastActiveTime < mIdleTimeout)
&& IsAlive();
}
PRBool

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

@ -86,13 +86,9 @@ public:
PRBool CanReuse(); // can this connection be reused?
PRBool IsAlive();
PRBool IsKeepAlive() { return mKeepAlive; }
PRUint32 ReuseCount() { return mReuseCount; }
PRUint32 MaxReuseCount() { return mMaxReuseCount; }
PRUint32 IdleTimeout() { return mIdleTimeout; }
PRUint16 IdleTimeout() { return mIdleTimeout; }
void DontReuse() { mKeepAlive = PR_FALSE;
mReuseCount = 0;
mMaxReuseCount = 0;
mIdleTimeout = 0; }
void DropTransaction();
@ -126,10 +122,8 @@ private:
PRLock *mLock;
PRUint32 mReuseCount;
PRUint32 mMaxReuseCount; // value of keep-alive: max=
PRUint32 mIdleTimeout; // value of keep-alive: timeout=
PRUint32 mLastActiveTime;
PRUint16 mIdleTimeout; // value of keep-alive: timeout=
PRPackedBool mKeepAlive;
PRPackedBool mWriteDone;

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

@ -86,16 +86,13 @@ nsHttpHandler *nsHttpHandler::mGlobalInstance = 0;
nsHttpHandler::nsHttpHandler()
: mAuthCache(nsnull)
, mHttpVersion(NS_HTTP_VERSION_1_1)
, mReferrerLevel(PRUint32(-1)) // by default we always send a referrer
, mCapabilities(ALLOW_KEEPALIVE)
, mProxyCapabilities(ALLOW_KEEPALIVE)
, mProxySSLConnectAllowed(PR_TRUE)
, mConnectTimeout(30)
, mRequestTimeout(30)
, mReferrerLevel(0xff) // by default we always send a referrer
, mCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
, mProxyCapabilities(NS_HTTP_ALLOW_KEEPALIVE)
, mIdleTimeout(10)
, mMaxRequestAttempts(10)
, mMaxConnections(16)
, mMaxConnectionsPerServer(8)
, mMaxIdleConnections(16)
, mMaxIdleConnectionsPerServer(4)
, mActiveConnections(0)
, mIdleConnections(0)
@ -243,7 +240,7 @@ nsHttpHandler::Init()
nsresult
nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
PRUint32 caps,
PRUint8 caps,
PRBool useProxy)
{
nsresult rv;
@ -275,15 +272,16 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
// and "Keep-alive" request headers should not be sent by HTTP/1.1
// user-agents. Otherwise, problems with proxy servers (especially
// transparent proxies) can result.
//
// 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
// talking to an http proxy, and Connection: otherwise
// with HTTP/1.0 servers/proxies. We use "Proxy-Connection:" when
// we're talking to an http proxy, and "Connection:" otherwise
const char* connectionType = "close";
if (caps & ALLOW_KEEPALIVE) {
if (caps & NS_HTTP_ALLOW_KEEPALIVE) {
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);
if (NS_FAILED(rv)) return rv;
@ -294,8 +292,9 @@ nsHttpHandler::AddStandardRequestHeaders(nsHttpHeaderArray *request,
request->SetHeader(nsHttp::Connection, "close");
}
const nsHttpAtom& connAtom = useProxy ? nsHttp::Proxy_Connection : nsHttp::Connection;
return request->SetHeader(connAtom, connectionType);
const nsHttpAtom &header =
useProxy ? nsHttp::Proxy_Connection : nsHttp::Connection;
return request->SetHeader(header, connectionType);
}
PRBool
@ -632,7 +631,7 @@ nsHttpHandler::ProcessTransactionQ()
PRInt32 i;
for (i=0; (i < mTransactionQ.Count()) &&
(mActiveConnections.Count() < mMaxConnections); ++i) {
(mActiveConnections.Count() < PRInt32(mMaxConnections)); ++i) {
pt = (nsPendingTransaction *) mTransactionQ[i];
@ -677,8 +676,8 @@ nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
LOG(("nsHttpHandler::InitiateTransaction_Locked [failIfBusy=%d]\n", failIfBusy));
if ((mActiveConnections.Count() == mMaxConnections) ||
(CountActiveConnections(ci) == PRUint32(mMaxConnectionsPerServer))) {
if ((mActiveConnections.Count() == PRInt32(mMaxConnections)) ||
(CountActiveConnections(ci) == mMaxConnectionsPerServer)) {
LOG(("unable to perform the transaction at this time [trans=%x]\n", trans));
if (failIfBusy) return NS_ERROR_FAILURE;
return EnqueueTransaction(trans, ci);
@ -775,10 +774,10 @@ nsHttpHandler::RemovePendingTransaction(nsHttpTransaction *trans)
return NS_ERROR_NOT_AVAILABLE;
}
PRUint32
PRUint8
nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
{
PRUint32 count = 0;
PRUint8 count = 0;
nsHttpConnection *conn = 0;
LOG(("nsHttpHandler::CountActiveConnections [host=%s:%d]\n",
@ -792,14 +791,14 @@ nsHttpHandler::CountActiveConnections(nsHttpConnectionInfo *ci)
count++;
}
LOG(("found count=%u\n", count));
LOG(("found count=%u\n", (PRUintn) count));
return count;
}
PRUint32
PRUint8
nsHttpHandler::CountIdleConnections(nsHttpConnectionInfo *ci)
{
PRUint32 count = 0;
PRUint8 count = 0;
nsHttpConnection *conn = 0;
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;
}
@ -1049,18 +1048,51 @@ nsHttpHandler::PrefsChanged(const char *pref)
}
nsresult rv = NS_OK;
PRInt32 val;
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.timeout") == 0)
mPrefs->GetIntPref("network.http.keep-alive.timeout", &mIdleTimeout);
if (bChangedAll || PL_strcmp(pref, "network.http.keep-alive.timeout") == 0) {
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)
mPrefs->GetIntPref("network.http.max-connections", &mMaxConnections);
if (bChangedAll || PL_strcmp(pref, "network.http.request.max-attempts") == 0) {
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)
mPrefs->GetIntPref("network.http.max-connections-per-server", &mMaxConnectionsPerServer);
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections") == 0) {
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)
mPrefs->GetIntPref("network.http.sendRefererHeader", (PRInt32 *) &mReferrerLevel);
if (bChangedAll || PL_strcmp(pref, "network.http.max-connections-per-server") == 0) {
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) {
nsXPIDLCString httpVersion;
@ -1076,8 +1108,8 @@ nsHttpHandler::PrefsChanged(const char *pref)
}
if (mHttpVersion == NS_HTTP_VERSION_1_1) {
mCapabilities = ALLOW_KEEPALIVE;
mProxyCapabilities = ALLOW_KEEPALIVE;
mCapabilities = NS_HTTP_ALLOW_KEEPALIVE;
mProxyCapabilities = NS_HTTP_ALLOW_KEEPALIVE;
}
else {
mCapabilities = 0;
@ -1091,9 +1123,9 @@ nsHttpHandler::PrefsChanged(const char *pref)
rv = mPrefs->GetBoolPref("network.http.keep-alive", &cVar);
if (NS_SUCCEEDED(rv)) {
if (cVar)
mCapabilities |= ALLOW_KEEPALIVE;
mCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
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);
if (NS_SUCCEEDED(rv)) {
if (cVar)
mProxyCapabilities |= ALLOW_KEEPALIVE;
mProxyCapabilities |= NS_HTTP_ALLOW_KEEPALIVE;
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);
if (NS_SUCCEEDED(rv)) {
if (cVar)
mCapabilities |= ALLOW_PIPELINING;
mCapabilities |= NS_HTTP_ALLOW_PIPELINING;
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);
if (NS_SUCCEEDED(rv)) {
if (cVar)
mProxyCapabilities |= ALLOW_PIPELINING;
mProxyCapabilities |= NS_HTTP_ALLOW_PIPELINING;
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)
mPrefs->GetIntPref("network.http.connect.timeout", &mConnectTimeout);
if (bChangedAll || PL_strcmp(pref, "network.http.request.timeout") == 0)
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) {
nsXPIDLString acceptLanguages;
@ -1168,9 +1201,8 @@ nsHttpHandler::PrefsChanged(const char *pref)
// general.useragent.override
if (bChangedAll || PL_strcmp(pref, UA_PREF_PREFIX "override") == 0) {
char* temp = 0;
rv = mPrefs->CopyCharPref(UA_PREF_PREFIX "override",
&temp);
char *temp = 0;
rv = mPrefs->CopyCharPref(UA_PREF_PREFIX "override", &temp);
if (NS_SUCCEEDED(rv)) {
mUserAgentOverride.Adopt(temp);
temp = 0;
@ -1589,7 +1621,6 @@ nsHttpHandler::NewChannel(nsIURI *uri, nsIChannel **result)
}
rv = NewProxyChannel(uri,
nsnull,
-1,
nsnull,
@ -1627,10 +1658,10 @@ nsHttpHandler::NewProxyChannel(nsIURI *uri,
NS_ADDREF(httpChannel);
nsresult rv = httpChannel->Init(uri,
mCapabilities,
proxyHost,
proxyPort,
proxyType);
mCapabilities,
proxyHost,
proxyPort,
proxyType);
if (NS_SUCCEEDED(rv))
rv = httpChannel->

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

@ -64,11 +64,6 @@ public:
NS_DECL_NSIHTTPPROTOCOLHANDLER
NS_DECL_NSIOBSERVER
enum {
ALLOW_KEEPALIVE = 1 << 0,
ALLOW_PIPELINING = 1 << 1
};
nsHttpHandler();
virtual ~nsHttpHandler();
@ -81,15 +76,15 @@ public:
nsresult Init();
nsresult AddStandardRequestHeaders(nsHttpHeaderArray *,
PRUint32 capabilities,
PRUint8 capabilities,
PRBool useProxy);
PRBool IsAcceptableEncoding(const char *encoding);
const char *UserAgent();
nsHttpVersion DefaultVersion() { return (nsHttpVersion) mHttpVersion; }
PRUint32 ReferrerLevel() { return mReferrerLevel; }
PRUint32 IdleTimeout() { return mIdleTimeout; }
nsHttpVersion DefaultVersion() { return mHttpVersion; }
PRUint8 ReferrerLevel() { return mReferrerLevel; }
PRUint16 IdleTimeout() { return mIdleTimeout; }
PRUint16 MaxRequestAttempts() { return mMaxRequestAttempts; }
nsHttpAuthCache *AuthCache() { return mAuthCache; }
@ -173,8 +168,8 @@ private:
nsresult RemovePendingTransaction(nsHttpTransaction *);
PRUint32 CountActiveConnections(nsHttpConnectionInfo *);
PRUint32 CountIdleConnections(nsHttpConnectionInfo *);
PRUint8 CountActiveConnections(nsHttpConnectionInfo *);
PRUint8 CountIdleConnections(nsHttpConnectionInfo *);
void DropConnections(nsVoidArray &);
@ -213,20 +208,17 @@ private:
// prefs
//
PRUint32 mHttpVersion;
PRUint32 mReferrerLevel;
PRUint32 mCapabilities;
PRUint32 mProxyCapabilities;
PRBool mProxySSLConnectAllowed;
PRUint8 mHttpVersion;
PRUint8 mReferrerLevel;
PRUint8 mCapabilities;
PRUint8 mProxyCapabilities;
PRInt32 mConnectTimeout;
PRInt32 mRequestTimeout;
PRInt32 mIdleTimeout;
PRUint16 mIdleTimeout;
PRUint16 mMaxRequestAttempts;
PRInt32 mMaxConnections;
PRInt32 mMaxConnectionsPerServer;
PRInt32 mMaxIdleConnections;
PRInt32 mMaxIdleConnectionsPerServer;
PRUint16 mMaxConnections;
PRUint8 mMaxConnectionsPerServer;
PRUint8 mMaxIdleConnectionsPerServer;
nsCString mAccept;
nsCString mAcceptLanguages;

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

@ -57,7 +57,7 @@ nsHttpResponseHead::Flatten(nsACString &buf, PRBool pruneTransients)
buf.Append("1.0 ");
char b[32];
PR_snprintf(b, sizeof(b), "%d", mStatus);
PR_snprintf(b, sizeof(b), "%u", PRUintn(mStatus));
buf.Append(b);
buf.Append(' ');
@ -144,28 +144,26 @@ nsHttpResponseHead::ParseStatusLine(char *line)
if ((mVersion == NS_HTTP_VERSION_0_9) || !(line = PL_strchr(line, ' '))) {
mStatus = 200;
mStatusText.Adopt(nsCRT::strdup("OK"));
LOG(("Have status line [version=%d status=%d statusText=%s]\n",
mVersion, mStatus, mStatusText.get()));
return;
}
// Status-Code
mStatus = atoi(++line);
if (mStatus == 0) {
LOG(("mal-formed response status; assuming status = 200\n"));
mStatus = 200;
else {
// Status-Code
mStatus = (PRUint16) atoi(++line);
if (mStatus == 0) {
LOG(("mal-formed response status; assuming status = 200\n"));
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
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));
LOG(("Have status line [version=%d status=%d statusText=%s]\n",
mVersion, mStatus, mStatusText.get()));
LOG(("Have status line [version=%u status=%u statusText=%s]\n",
PRUintn(mVersion), PRUintn(mStatus), mStatusText.get()));
}
void

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

@ -43,7 +43,7 @@ public:
nsHttpHeaderArray &Headers() { return mHeaders; }
nsHttpVersion Version() { return mVersion; }
PRUint32 Status() { return mStatus; }
PRUint16 Status() { return mStatus; }
const char *StatusText() { return mStatusText; }
PRInt32 ContentLength() { return mContentLength; }
const char *ContentType() { return mContentType; }
@ -98,7 +98,7 @@ private:
private:
nsHttpHeaderArray mHeaders;
nsHttpVersion mVersion;
PRUint32 mStatus;
PRUint16 mStatus;
nsXPIDLCString mStatusText;
PRInt32 mContentLength;
nsXPIDLCString mContentType;

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

@ -48,6 +48,7 @@ nsHttpTransaction::nsHttpTransaction(nsIStreamListener *listener,
, mChunkedDecoder(nsnull)
, mTransactionDone(0)
, mStatus(NS_OK)
, mRestartCount(0)
, mHaveStatusLine(PR_FALSE)
, mHaveAllHeaders(PR_FALSE)
, mFiredOnStart(PR_FALSE)
@ -182,6 +183,12 @@ nsHttpTransaction::OnDataReadable(nsIInputStream *is)
// check if this transaction needs to be restarted
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;
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
// allowances for a possibly invalid Content-Length header. Thus, if
// NOT keep-alive, we simply accept everything in |buf|.
if (mConnection->IsKeepAlive())
*countRead = PR_MIN(count, mContentLength - mContentRead);
if (mConnection->IsKeepAlive()) {
*countRead = PRUint32(mContentLength) - mContentRead;
*countRead = PR_MIN(count, *countRead);
}
else {
*countRead = count;
// mContentLength might need to be increased...

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

@ -126,10 +126,12 @@ private:
PRInt32 mTransactionDone; // set atomically
nsresult mStatus;
PRUint16 mRestartCount; // the number of times this transaction has been restarted
PRPackedBool mHaveStatusLine;
PRPackedBool mHaveAllHeaders;
PRPackedBool mFiredOnStart;
PRPackedBool mNoContent; // true if we're expecting an empty entity body
PRPackedBool mNoContent; // expecting an empty entity body?
PRPackedBool mPrematureEOF;
};