diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index a9fd2a66477..5af0ddbae22 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -51,7 +51,7 @@ native PRNetAddr(union PRNetAddr); * NOTE: This is a free-threaded interface, meaning that the methods on * this interface may be called from any thread. */ -[scriptable, uuid(66418cc8-5f5d-4f52-a7f9-db8fb3b2cfe6)] +[scriptable, uuid(ef3f4993-cfbc-4e5a-9509-16deafe16549)] interface nsISocketTransport : nsITransport { /** @@ -134,6 +134,22 @@ interface nsISocketTransport : nsITransport const unsigned long STATUS_SENDING_TO = 0x804b0005; const unsigned long STATUS_WAITING_FOR = 0x804b000a; const unsigned long STATUS_RECEIVING_FROM = 0x804b0006; + + /** + * connectionFlags is a bitmask that can be used to modify underlying + * behavior of the socket connection. + */ + attribute unsigned long connectionFlags; + + /** + * Values for the connectionFlags + * + * When making a new connection BYPASS_CACHE will force the Necko DNS + * cache entry to be refreshed with a new call to NSPR if it is set before + * opening the new stream. + */ + const unsigned long BYPASS_CACHE = (1 << 0); + }; %{C++ diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index eff1592ea51..a9f5d23bf88 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -707,6 +707,7 @@ nsSocketTransport::nsSocketTransport() , mProxyPort(0) , mProxyTransparent(PR_FALSE) , mProxyTransparentResolvesHost(PR_FALSE) + , mConnectionFlags(0) , mState(STATE_CLOSED) , mAttached(PR_FALSE) , mInputClosed(PR_TRUE) @@ -946,7 +947,11 @@ nsSocketTransport::ResolveHost() mResolving = PR_TRUE; - rv = dns->AsyncResolve(SocketHost(), 0, this, nsnull, + PRUint32 dnsFlags = 0; + if (mConnectionFlags & nsSocketTransport::BYPASS_CACHE) + dnsFlags = nsIDNSService::RESOLVE_BYPASS_CACHE; + + rv = dns->AsyncResolve(SocketHost(), dnsFlags, this, nsnull, getter_AddRefs(mDNSRequest)); if (NS_SUCCEEDED(rv)) { LOG((" advancing to STATE_RESOLVING\n")); @@ -1946,6 +1951,21 @@ nsSocketTransport::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) } +NS_IMETHODIMP +nsSocketTransport::GetConnectionFlags(PRUint32 *value) +{ + *value = mConnectionFlags; + return NS_OK; +} + +NS_IMETHODIMP +nsSocketTransport::SetConnectionFlags(PRUint32 value) +{ + mConnectionFlags = value; + return NS_OK; +} + + #ifdef ENABLE_SOCKET_TRACING #include diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h index de4133ff467..35efa229a46 100644 --- a/netwerk/base/src/nsSocketTransport2.h +++ b/netwerk/base/src/nsSocketTransport2.h @@ -202,7 +202,8 @@ private: PRUint16 mProxyPort; PRPackedBool mProxyTransparent; PRPackedBool mProxyTransparentResolvesHost; - + PRUint32 mConnectionFlags; + PRUint16 SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; } const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; } diff --git a/netwerk/protocol/http/src/nsHttp.h b/netwerk/protocol/http/src/nsHttp.h index 21a2cbd471c..ab167e75fa7 100644 --- a/netwerk/protocol/http/src/nsHttp.h +++ b/netwerk/protocol/http/src/nsHttp.h @@ -104,6 +104,10 @@ typedef PRUint8 nsHttpVersion; // preventing it from being reclaimed, even after the transaction completes. #define NS_HTTP_STICKY_CONNECTION (1<<2) +// a transaction with this caps flag will, upon opening a new connection, +// bypass the local DNS cache +#define NS_HTTP_REFRESH_DNS (1<<3) + //----------------------------------------------------------------------------- // some default values //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index cdd805be3c2..adbc595d03a 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -4010,6 +4010,10 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) if (mRequestHead.HasHeaderValue(nsHttp::Connection, "close")) mCaps &= ~(NS_HTTP_ALLOW_KEEPALIVE | NS_HTTP_ALLOW_PIPELINING); + if ((mLoadFlags & VALIDATE_ALWAYS) || + (BYPASS_LOCAL_CACHE(mLoadFlags))) + mCaps |= NS_HTTP_REFRESH_DNS; + mIsPending = PR_TRUE; mWasOpened = PR_TRUE; diff --git a/netwerk/protocol/http/src/nsHttpConnection.cpp b/netwerk/protocol/http/src/nsHttpConnection.cpp index 47f0e1cd943..fbea4ff8cb2 100644 --- a/netwerk/protocol/http/src/nsHttpConnection.cpp +++ b/netwerk/protocol/http/src/nsHttpConnection.cpp @@ -140,7 +140,7 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, PRUint8 caps) // if we don't have a socket transport then create a new one if (!mSocketTransport) { - rv = CreateTransport(); + rv = CreateTransport(caps); if (NS_FAILED(rv)) goto loser; } @@ -424,7 +424,7 @@ nsHttpConnection::ResumeRecv() //----------------------------------------------------------------------------- nsresult -nsHttpConnection::CreateTransport() +nsHttpConnection::CreateTransport(PRUint8 caps) { nsresult rv; @@ -452,6 +452,9 @@ nsHttpConnection::CreateTransport() getter_AddRefs(strans)); if (NS_FAILED(rv)) return rv; + if (caps & NS_HTTP_REFRESH_DNS) + strans->SetConnectionFlags(nsISocketTransport::BYPASS_CACHE); + // NOTE: these create cyclical references, which we break inside // nsHttpConnection::Close rv = strans->SetEventSink(this, nsnull); diff --git a/netwerk/protocol/http/src/nsHttpConnection.h b/netwerk/protocol/http/src/nsHttpConnection.h index 98cd848c776..7ca9d914754 100644 --- a/netwerk/protocol/http/src/nsHttpConnection.h +++ b/netwerk/protocol/http/src/nsHttpConnection.h @@ -125,7 +125,7 @@ private: // called to cause the underlying socket to start speaking SSL nsresult ProxyStartSSL(); - nsresult CreateTransport(); + nsresult CreateTransport(PRUint8 caps); nsresult OnTransactionDone(nsresult reason); nsresult OnSocketWritable(); nsresult OnSocketReadable();