зеркало из https://github.com/mozilla/pjs.git
initial framework patch for http/1.1 pipelining (bug 93054) r=gagan, sr=rpotts
This commit is contained in:
Родитель
070dba8b90
Коммит
5ac2b46834
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef nsAHttpConnection_h__
|
||||||
|
#define nsAHttpConnection_h__
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
class nsAHttpTransaction;
|
||||||
|
class nsHttpResponseHead;
|
||||||
|
class nsHttpConnectionInfo;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Abstract base class for a HTTP connection
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class nsAHttpConnection : public nsISupports
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// called by a transaction when the response headers have all been read.
|
||||||
|
// the connection can force the transaction to reset it's response headers,
|
||||||
|
// and prepare for a new set of response headers, by setting |*reset=TRUE|.
|
||||||
|
virtual nsresult OnHeadersAvailable(nsAHttpTransaction *,
|
||||||
|
nsHttpResponseHead *,
|
||||||
|
PRBool *reset) = 0;
|
||||||
|
|
||||||
|
// called by a transaction when it completes normally.
|
||||||
|
virtual nsresult OnTransactionComplete(nsAHttpTransaction *,
|
||||||
|
nsresult status) = 0;
|
||||||
|
|
||||||
|
// called by a transaction to suspend/resume the connection.
|
||||||
|
virtual nsresult OnSuspend() = 0;
|
||||||
|
virtual nsresult OnResume() = 0;
|
||||||
|
|
||||||
|
// get a reference to the connection's connection-info object.
|
||||||
|
virtual void GetConnectionInfo(nsHttpConnectionInfo **) = 0;
|
||||||
|
|
||||||
|
// called by a transaction to remove itself from the connection (eg. when
|
||||||
|
// it reads premature EOF and must restart itself).
|
||||||
|
virtual void DropTransaction(nsAHttpTransaction *) = 0;
|
||||||
|
|
||||||
|
// called by a transaction to determine whether or not the connection is
|
||||||
|
// persistent... important in determining the end of a response.
|
||||||
|
virtual PRBool IsPersistent() = 0;
|
||||||
|
|
||||||
|
// called by a transaction when the transaction reads more from the socket
|
||||||
|
// than it should have (eg. containing part of the next pipelined response).
|
||||||
|
virtual nsresult PushBack(char *data, PRUint32 length) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsAHttpConnection_h__
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef nsAHttpTransaction_h__
|
||||||
|
#define nsAHttpTransaction_h__
|
||||||
|
|
||||||
|
#include "nsISupports.h"
|
||||||
|
|
||||||
|
class nsAHttpConnection;
|
||||||
|
class nsIInputStream;
|
||||||
|
class nsIOutputStream;
|
||||||
|
class nsIInterfaceRequestor;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// Abstract base class for a HTTP transaction
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class nsAHttpTransaction : public nsISupports
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// called by the connection when it takes ownership of the transaction.
|
||||||
|
virtual void SetConnection(nsAHttpConnection *) = 0;
|
||||||
|
|
||||||
|
// called by the connection to pass socket security-info to the transaction.
|
||||||
|
virtual void SetSecurityInfo(nsISupports *) = 0;
|
||||||
|
|
||||||
|
// called by the connection to get notification callbacks to set on the
|
||||||
|
// socket transport.
|
||||||
|
virtual void GetNotificationCallbacks(nsIInterfaceRequestor **) = 0;
|
||||||
|
|
||||||
|
// called by the connection to indicate that the socket can be written to.
|
||||||
|
// the transaction returns NS_BASE_STREAM_CLOSED when it is finished
|
||||||
|
// writing its request(s).
|
||||||
|
virtual nsresult OnDataWritable(nsIOutputStream *) = 0;
|
||||||
|
|
||||||
|
// called by the connection to indicate that the socket can be read from.
|
||||||
|
// the transaction can return NS_BASE_STREAM_WOULD_BLOCK to suspend the
|
||||||
|
// socket read request.
|
||||||
|
virtual nsresult OnDataReadable(nsIInputStream *) = 0;
|
||||||
|
|
||||||
|
// called by the connection when the transaction should stop, either due
|
||||||
|
// to normal completion, cancelation, or some socket transport error.
|
||||||
|
virtual nsresult OnStopTransaction(nsresult status) = 0;
|
||||||
|
|
||||||
|
// called by the connection to report socket status.
|
||||||
|
virtual void OnStatus(nsresult status, const PRUnichar *statusText) = 0;
|
||||||
|
|
||||||
|
// called by the connection to check the transaction status.
|
||||||
|
virtual PRBool IsDone() = 0;
|
||||||
|
virtual nsresult Status() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsAHttpTransaction_h__
|
|
@ -99,7 +99,8 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info, PRUint16 maxHangTime)
|
||||||
|
|
||||||
// called from any thread, with the connection lock held
|
// called from any thread, with the connection lock held
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
|
nsHttpConnection::SetTransaction(nsAHttpTransaction *transaction,
|
||||||
|
PRUint8 caps)
|
||||||
{
|
{
|
||||||
LOG(("nsHttpConnection::SetTransaction [this=%x trans=%x]\n",
|
LOG(("nsHttpConnection::SetTransaction [this=%x trans=%x]\n",
|
||||||
this, transaction));
|
this, transaction));
|
||||||
|
@ -112,160 +113,11 @@ nsHttpConnection::SetTransaction(nsHttpTransaction *transaction)
|
||||||
NS_ADDREF(mTransaction);
|
NS_ADDREF(mTransaction);
|
||||||
|
|
||||||
// default mKeepAlive according to what will be requested
|
// default mKeepAlive according to what will be requested
|
||||||
mKeepAliveMask = mKeepAlive =
|
mKeepAliveMask = mKeepAlive = (caps & NS_HTTP_ALLOW_KEEPALIVE);
|
||||||
mTransaction->Capabilities() & NS_HTTP_ALLOW_KEEPALIVE;
|
|
||||||
|
|
||||||
return ActivateConnection();
|
return ActivateConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
// called from the socket thread
|
|
||||||
nsresult
|
|
||||||
nsHttpConnection::OnHeadersAvailable(nsHttpTransaction *trans, PRBool *reset)
|
|
||||||
{
|
|
||||||
LOG(("nsHttpConnection::OnHeadersAvailable [this=%x trans=%x]\n",
|
|
||||||
this, trans));
|
|
||||||
|
|
||||||
NS_ENSURE_ARG_POINTER(trans);
|
|
||||||
|
|
||||||
// we won't change our keep-alive policy unless the server has explicitly
|
|
||||||
// told us to do so.
|
|
||||||
|
|
||||||
if (!trans || !trans->ResponseHead()) {
|
|
||||||
LOG(("trans->ResponseHead() = %x\n", trans));
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// inspect the connection headers for keep-alive info provided the
|
|
||||||
// transaction completed successfully.
|
|
||||||
const char *val = trans->ResponseHead()->PeekHeader(nsHttp::Connection);
|
|
||||||
if (!val)
|
|
||||||
val = trans->ResponseHead()->PeekHeader(nsHttp::Proxy_Connection);
|
|
||||||
|
|
||||||
if ((trans->ResponseHead()->Version() < NS_HTTP_VERSION_1_1) ||
|
|
||||||
(nsHttpHandler::get()->DefaultVersion() < NS_HTTP_VERSION_1_1)) {
|
|
||||||
// HTTP/1.0 connections are by default NOT persistent
|
|
||||||
if (val && !PL_strcasecmp(val, "keep-alive"))
|
|
||||||
mKeepAlive = PR_TRUE;
|
|
||||||
else
|
|
||||||
mKeepAlive = PR_FALSE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// HTTP/1.1 connections are by default persistent
|
|
||||||
if (val && !PL_strcasecmp(val, "close"))
|
|
||||||
mKeepAlive = PR_FALSE;
|
|
||||||
else
|
|
||||||
mKeepAlive = PR_TRUE;
|
|
||||||
}
|
|
||||||
mKeepAliveMask = mKeepAlive;
|
|
||||||
|
|
||||||
// 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. 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);
|
|
||||||
|
|
||||||
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 idle-timeout=%u\n", this, mIdleTimeout));
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're doing an SSL proxy connect, then we need to check whether or not
|
|
||||||
// the connect was successful. if so, then we have to reset the transaction
|
|
||||||
// and step-up the socket connection to SSL. finally, we have to wake up the
|
|
||||||
// socket write request.
|
|
||||||
if (mSSLProxyConnectStream) {
|
|
||||||
mSSLProxyConnectStream = 0;
|
|
||||||
if (trans->ResponseHead()->Status() == 200) {
|
|
||||||
LOG(("SSL proxy CONNECT succeeded!\n"));
|
|
||||||
*reset = PR_TRUE;
|
|
||||||
ProxyStepUp();
|
|
||||||
mWriteRequest->Resume();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LOG(("SSL proxy CONNECT failed!\n"));
|
|
||||||
// close out the write request
|
|
||||||
mWriteRequest->Cancel(NS_OK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called from any thread
|
|
||||||
nsresult
|
|
||||||
nsHttpConnection::OnTransactionComplete(nsHttpTransaction *trans, nsresult status)
|
|
||||||
{
|
|
||||||
LOG(("nsHttpConnection::OnTransactionComplete [this=%x trans=%x status=%x]\n",
|
|
||||||
this, trans, status));
|
|
||||||
|
|
||||||
// trans may not be mTransaction
|
|
||||||
if (trans != mTransaction)
|
|
||||||
return NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRequest> writeReq, readReq;
|
|
||||||
|
|
||||||
// clear the read/write requests atomically.
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
writeReq = mWriteRequest;
|
|
||||||
readReq = mReadRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cancel the requests... this will cause OnStopRequest to be fired
|
|
||||||
if (writeReq)
|
|
||||||
writeReq->Cancel(status);
|
|
||||||
if (readReq)
|
|
||||||
readReq->Cancel(status);
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not called from the socket thread
|
|
||||||
nsresult
|
|
||||||
nsHttpConnection::Suspend()
|
|
||||||
{
|
|
||||||
// we only bother to suspend the read request, since that's the only
|
|
||||||
// one that will effect our consumers.
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRequest> readReq;
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
readReq = mReadRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readReq)
|
|
||||||
readReq->Suspend();
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not called from the socket thread
|
|
||||||
nsresult
|
|
||||||
nsHttpConnection::Resume()
|
|
||||||
{
|
|
||||||
// we only need to worry about resuming the read request, since that's
|
|
||||||
// the only one that can be suspended.
|
|
||||||
|
|
||||||
nsCOMPtr<nsIRequest> readReq;
|
|
||||||
{
|
|
||||||
nsAutoLock lock(mLock);
|
|
||||||
readReq = mReadRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (readReq)
|
|
||||||
readReq->Resume();
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called from the socket thread
|
// called from the socket thread
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpConnection::ProxyStepUp()
|
nsHttpConnection::ProxyStepUp()
|
||||||
|
@ -304,10 +156,166 @@ nsHttpConnection::IsAlive()
|
||||||
return isAlive;
|
return isAlive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// nsHttpConnection::nsAHttpConnection
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// called from the socket thread
|
||||||
|
nsresult
|
||||||
|
nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans,
|
||||||
|
nsHttpResponseHead *responseHead,
|
||||||
|
PRBool *reset)
|
||||||
|
{
|
||||||
|
LOG(("nsHttpConnection::OnHeadersAvailable [this=%p trans=%p response-head=%p]\n",
|
||||||
|
this, trans, responseHead));
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(trans);
|
||||||
|
|
||||||
|
// we won't change our keep-alive policy unless the server has explicitly
|
||||||
|
// told us to do so.
|
||||||
|
|
||||||
|
if (!trans || !responseHead) {
|
||||||
|
LOG(("nothing to do\n"));
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// inspect the connection headers for keep-alive info provided the
|
||||||
|
// transaction completed successfully.
|
||||||
|
const char *val = responseHead->PeekHeader(nsHttp::Connection);
|
||||||
|
if (!val)
|
||||||
|
val = responseHead->PeekHeader(nsHttp::Proxy_Connection);
|
||||||
|
|
||||||
|
if ((responseHead->Version() < NS_HTTP_VERSION_1_1) ||
|
||||||
|
(nsHttpHandler::get()->DefaultVersion() < NS_HTTP_VERSION_1_1)) {
|
||||||
|
// HTTP/1.0 connections are by default NOT persistent
|
||||||
|
if (val && !PL_strcasecmp(val, "keep-alive"))
|
||||||
|
mKeepAlive = PR_TRUE;
|
||||||
|
else
|
||||||
|
mKeepAlive = PR_FALSE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HTTP/1.1 connections are by default persistent
|
||||||
|
if (val && !PL_strcasecmp(val, "close"))
|
||||||
|
mKeepAlive = PR_FALSE;
|
||||||
|
else
|
||||||
|
mKeepAlive = PR_TRUE;
|
||||||
|
}
|
||||||
|
mKeepAliveMask = mKeepAlive;
|
||||||
|
|
||||||
|
// 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. 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 = responseHead->PeekHeader(nsHttp::Keep_Alive);
|
||||||
|
|
||||||
|
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 idle-timeout=%u\n", this, mIdleTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we're doing an SSL proxy connect, then we need to check whether or not
|
||||||
|
// the connect was successful. if so, then we have to reset the transaction
|
||||||
|
// and step-up the socket connection to SSL. finally, we have to wake up the
|
||||||
|
// socket write request.
|
||||||
|
if (mSSLProxyConnectStream) {
|
||||||
|
mSSLProxyConnectStream = 0;
|
||||||
|
if (responseHead->Status() == 200) {
|
||||||
|
LOG(("SSL proxy CONNECT succeeded!\n"));
|
||||||
|
*reset = PR_TRUE;
|
||||||
|
ProxyStepUp();
|
||||||
|
mWriteRequest->Resume();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG(("SSL proxy CONNECT failed!\n"));
|
||||||
|
// close out the write request
|
||||||
|
mWriteRequest->Cancel(NS_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called from any thread
|
||||||
|
nsresult
|
||||||
|
nsHttpConnection::OnTransactionComplete(nsAHttpTransaction *trans, nsresult status)
|
||||||
|
{
|
||||||
|
LOG(("nsHttpConnection::OnTransactionComplete [this=%x trans=%x status=%x]\n",
|
||||||
|
this, trans, status));
|
||||||
|
|
||||||
|
// trans may not be mTransaction
|
||||||
|
if (trans != mTransaction)
|
||||||
|
return NS_OK;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRequest> writeReq, readReq;
|
||||||
|
|
||||||
|
// clear the read/write requests atomically.
|
||||||
|
{
|
||||||
|
nsAutoLock lock(mLock);
|
||||||
|
writeReq = mWriteRequest;
|
||||||
|
readReq = mReadRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cancel the requests... this will cause OnStopRequest to be fired
|
||||||
|
if (writeReq)
|
||||||
|
writeReq->Cancel(status);
|
||||||
|
if (readReq)
|
||||||
|
readReq->Cancel(status);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not called from the socket thread
|
||||||
|
nsresult
|
||||||
|
nsHttpConnection::OnSuspend()
|
||||||
|
{
|
||||||
|
// we only bother to suspend the read request, since that's the only
|
||||||
|
// one that will effect our consumers.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRequest> readReq;
|
||||||
|
{
|
||||||
|
nsAutoLock lock(mLock);
|
||||||
|
readReq = mReadRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readReq)
|
||||||
|
readReq->Suspend();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not called from the socket thread
|
||||||
|
nsresult
|
||||||
|
nsHttpConnection::OnResume()
|
||||||
|
{
|
||||||
|
// we only need to worry about resuming the read request, since that's
|
||||||
|
// the only one that can be suspended.
|
||||||
|
|
||||||
|
nsCOMPtr<nsIRequest> readReq;
|
||||||
|
{
|
||||||
|
nsAutoLock lock(mLock);
|
||||||
|
readReq = mReadRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (readReq)
|
||||||
|
readReq->Resume();
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// called on the socket thread
|
// called on the socket thread
|
||||||
void
|
void
|
||||||
nsHttpConnection::DropTransaction()
|
nsHttpConnection::DropTransaction(nsAHttpTransaction *trans)
|
||||||
{
|
{
|
||||||
|
LOG(("nsHttpConnection::DropTransaction [trans=%p]\n", trans));
|
||||||
|
|
||||||
// the assertion here is that the transaction will not be destroyed
|
// the assertion here is that the transaction will not be destroyed
|
||||||
// by this release. we unfortunately don't have a threadsafe way of
|
// by this release. we unfortunately don't have a threadsafe way of
|
||||||
// asserting this.
|
// asserting this.
|
||||||
|
@ -361,7 +369,7 @@ nsHttpConnection::ActivateConnection()
|
||||||
// by the same token, we need to ensure that the transaction stays around.
|
// by the same token, we need to ensure that the transaction stays around.
|
||||||
// and we must not access it via mTransaction, since mTransaction is null'd
|
// and we must not access it via mTransaction, since mTransaction is null'd
|
||||||
// in our OnStopRequest.
|
// in our OnStopRequest.
|
||||||
nsHttpTransaction *trans = mTransaction;
|
nsAHttpTransaction *trans = mTransaction;
|
||||||
NS_ADDREF(trans);
|
NS_ADDREF(trans);
|
||||||
|
|
||||||
// We need to tell the socket transport what origin server we're
|
// We need to tell the socket transport what origin server we're
|
||||||
|
@ -485,15 +493,19 @@ nsHttpConnection::SetupSSLProxyConnect()
|
||||||
request.SetVersion(nsHttpHandler::get()->DefaultVersion());
|
request.SetVersion(nsHttpHandler::get()->DefaultVersion());
|
||||||
request.SetRequestURI(buf.get());
|
request.SetRequestURI(buf.get());
|
||||||
request.SetHeader(nsHttp::User_Agent, nsHttpHandler::get()->UserAgent());
|
request.SetHeader(nsHttp::User_Agent, nsHttpHandler::get()->UserAgent());
|
||||||
|
|
||||||
|
// NOTE: this cast is valid since this connection cannot be processing a
|
||||||
|
// transaction pipeline until after the first HTTP/1.1 response.
|
||||||
|
nsHttpTransaction *trans = NS_STATIC_CAST(nsHttpTransaction *, mTransaction);
|
||||||
|
|
||||||
val = mTransaction->RequestHead()->PeekHeader(nsHttp::Host);
|
val = trans->RequestHead()->PeekHeader(nsHttp::Host);
|
||||||
if (val) {
|
if (val) {
|
||||||
// all HTTP/1.1 requests must include a Host header (even though it
|
// all HTTP/1.1 requests must include a Host header (even though it
|
||||||
// may seem redundant in this case; see bug 82388).
|
// may seem redundant in this case; see bug 82388).
|
||||||
request.SetHeader(nsHttp::Host, val);
|
request.SetHeader(nsHttp::Host, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
val = mTransaction->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization);
|
val = trans->RequestHead()->PeekHeader(nsHttp::Proxy_Authorization);
|
||||||
if (val) {
|
if (val) {
|
||||||
// we don't know for sure if this authorization is intended for the
|
// we don't know for sure if this authorization is intended for the
|
||||||
// SSL proxy, so we add it just in case.
|
// SSL proxy, so we add it just in case.
|
||||||
|
@ -597,7 +609,7 @@ nsHttpConnection::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
|
||||||
|
|
||||||
// make sure mTransaction is clear before calling OnStopTransaction
|
// make sure mTransaction is clear before calling OnStopTransaction
|
||||||
if (mTransaction) {
|
if (mTransaction) {
|
||||||
nsHttpTransaction *trans = mTransaction;
|
nsAHttpTransaction *trans = mTransaction;
|
||||||
mTransaction = nsnull;
|
mTransaction = nsnull;
|
||||||
|
|
||||||
trans->OnStopTransaction(status);
|
trans->OnStopTransaction(status);
|
||||||
|
@ -702,8 +714,11 @@ nsHttpConnection::GetInterface(const nsIID &iid, void **result)
|
||||||
if (iid.Equals(NS_GET_IID(nsIProgressEventSink)))
|
if (iid.Equals(NS_GET_IID(nsIProgressEventSink)))
|
||||||
return QueryInterface(iid, result);
|
return QueryInterface(iid, result);
|
||||||
|
|
||||||
if (mTransaction && mTransaction->Callbacks())
|
if (mTransaction) {
|
||||||
return mTransaction->Callbacks()->GetInterface(iid, result);
|
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||||
|
mTransaction->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||||
|
return callbacks->GetInterface(iid, result);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_ERROR_NO_INTERFACE;
|
return NS_ERROR_NO_INTERFACE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#define nsHttpConnection_h__
|
#define nsHttpConnection_h__
|
||||||
|
|
||||||
#include "nsHttp.h"
|
#include "nsHttp.h"
|
||||||
|
#include "nsHttpConnectionInfo.h"
|
||||||
|
#include "nsAHttpConnection.h"
|
||||||
|
#include "nsAHttpTransaction.h"
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsIStreamProvider.h"
|
#include "nsIStreamProvider.h"
|
||||||
#include "nsISocketTransport.h"
|
#include "nsISocketTransport.h"
|
||||||
|
@ -33,23 +36,18 @@
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
#include "nsIEventQueue.h"
|
#include "nsIEventQueue.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
#include "nsIProxyInfo.h"
|
|
||||||
#include "nsCOMPtr.h"
|
|
||||||
#include "nsXPIDLString.h"
|
#include "nsXPIDLString.h"
|
||||||
#include "plstr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "prclist.h"
|
|
||||||
#include "nsCRT.h"
|
|
||||||
#include "prlock.h"
|
#include "prlock.h"
|
||||||
|
|
||||||
class nsHttpHandler;
|
class nsHttpHandler;
|
||||||
class nsHttpConnectionInfo;
|
|
||||||
class nsHttpTransaction;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
|
// nsHttpConnection - represents a connection to a HTTP server (or proxy)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
class nsHttpConnection : public nsIStreamListener
|
class nsHttpConnection : public nsAHttpConnection
|
||||||
|
, public nsIStreamListener
|
||||||
, public nsIStreamProvider
|
, public nsIStreamProvider
|
||||||
, public nsIProgressEventSink
|
, public nsIProgressEventSink
|
||||||
, public nsIInterfaceRequestor
|
, public nsIInterfaceRequestor
|
||||||
|
@ -74,18 +72,7 @@ public:
|
||||||
|
|
||||||
// SetTransaction causes the given transaction to be processed on this
|
// SetTransaction causes the given transaction to be processed on this
|
||||||
// connection. It fails if there is already an existing transaction.
|
// connection. It fails if there is already an existing transaction.
|
||||||
nsresult SetTransaction(nsHttpTransaction *);
|
nsresult SetTransaction(nsAHttpTransaction *, PRUint8 capabilities);
|
||||||
|
|
||||||
// called by the transaction to inform the connection that all of the
|
|
||||||
// headers are available.
|
|
||||||
nsresult OnHeadersAvailable(nsHttpTransaction *, PRBool *reset);
|
|
||||||
|
|
||||||
// called by the transaction to inform the connection that it is done.
|
|
||||||
nsresult OnTransactionComplete(nsHttpTransaction *, nsresult status);
|
|
||||||
|
|
||||||
// called by the transaction to suspend/resume a read-in-progress
|
|
||||||
nsresult Suspend();
|
|
||||||
nsresult Resume();
|
|
||||||
|
|
||||||
// called to cause the underlying socket to start speaking SSL
|
// called to cause the underlying socket to start speaking SSL
|
||||||
nsresult ProxyStepUp();
|
nsresult ProxyStepUp();
|
||||||
|
@ -96,11 +83,19 @@ public:
|
||||||
mKeepAlive = PR_FALSE;
|
mKeepAlive = PR_FALSE;
|
||||||
mIdleTimeout = 0; }
|
mIdleTimeout = 0; }
|
||||||
|
|
||||||
void DropTransaction();
|
nsAHttpTransaction *Transaction() { return mTransaction; }
|
||||||
|
|
||||||
nsHttpTransaction *Transaction() { return mTransaction; }
|
|
||||||
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
|
nsHttpConnectionInfo *ConnectionInfo() { return mConnectionInfo; }
|
||||||
|
|
||||||
|
// nsAHttpConnection methods:
|
||||||
|
nsresult OnHeadersAvailable(nsAHttpTransaction *, nsHttpResponseHead *, PRBool *reset);
|
||||||
|
nsresult OnTransactionComplete(nsAHttpTransaction *, nsresult status);
|
||||||
|
nsresult OnSuspend();
|
||||||
|
nsresult OnResume();
|
||||||
|
void GetConnectionInfo(nsHttpConnectionInfo **ci) { NS_IF_ADDREF(*ci = mConnectionInfo); }
|
||||||
|
void DropTransaction(nsAHttpTransaction *);
|
||||||
|
PRBool IsPersistent() { return IsKeepAlive(); }
|
||||||
|
nsresult PushBack(char *data, PRUint32 length) { return NS_OK; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsresult ActivateConnection();
|
nsresult ActivateConnection();
|
||||||
nsresult CreateTransport();
|
nsresult CreateTransport();
|
||||||
|
@ -116,7 +111,7 @@ private:
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> mSSLProxyConnectStream;
|
nsCOMPtr<nsIInputStream> mSSLProxyConnectStream;
|
||||||
|
|
||||||
nsHttpTransaction *mTransaction; // hard ref
|
nsAHttpTransaction *mTransaction; // hard ref
|
||||||
nsHttpConnectionInfo *mConnectionInfo; // hard ref
|
nsHttpConnectionInfo *mConnectionInfo; // hard ref
|
||||||
|
|
||||||
PRLock *mLock;
|
PRLock *mLock;
|
||||||
|
@ -132,99 +127,4 @@ private:
|
||||||
PRPackedBool mReadDone;
|
PRPackedBool mReadDone;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// nsHttpConnectionInfo - holds the properties of a connection
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
class nsHttpConnectionInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
nsHttpConnectionInfo(const char *host, PRInt32 port,
|
|
||||||
nsIProxyInfo* proxyInfo,
|
|
||||||
PRBool usingSSL=PR_FALSE)
|
|
||||||
: mRef(0)
|
|
||||||
, mProxyInfo(proxyInfo)
|
|
||||||
, mUsingSSL(usingSSL)
|
|
||||||
{
|
|
||||||
LOG(("Creating nsHttpConnectionInfo @%x\n", this));
|
|
||||||
|
|
||||||
mUsingHttpProxy = (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http"));
|
|
||||||
|
|
||||||
SetOriginServer(host, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
~nsHttpConnectionInfo()
|
|
||||||
{
|
|
||||||
LOG(("Destroying nsHttpConnectionInfo @%x\n", this));
|
|
||||||
}
|
|
||||||
|
|
||||||
nsrefcnt AddRef()
|
|
||||||
{
|
|
||||||
return PR_AtomicIncrement((PRInt32 *) &mRef);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsrefcnt Release()
|
|
||||||
{
|
|
||||||
nsrefcnt n = PR_AtomicDecrement((PRInt32 *) &mRef);
|
|
||||||
if (n == 0)
|
|
||||||
delete this;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult SetOriginServer(const char* host, PRInt32 port)
|
|
||||||
{
|
|
||||||
if (host)
|
|
||||||
mHost.Adopt(nsCRT::strdup(host));
|
|
||||||
mPort = port == -1 ? DefaultPort() : port;
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ProxyHost() const { return mProxyInfo ? mProxyInfo->Host() : nsnull; }
|
|
||||||
PRInt32 ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; }
|
|
||||||
const char *ProxyType() const { return mProxyInfo ? mProxyInfo->Type() : nsnull; }
|
|
||||||
|
|
||||||
// Compare this connection info to another...
|
|
||||||
// Two connections are 'equal' if they end up talking the same
|
|
||||||
// protocol to the same server. This is needed to properly manage
|
|
||||||
// persistent connections to proxies
|
|
||||||
// Note that we don't care about transparent proxies -
|
|
||||||
// it doesn't matter if we're talking via socks or not, since
|
|
||||||
// a request will end up at the same host.
|
|
||||||
PRBool Equals(const nsHttpConnectionInfo *info)
|
|
||||||
{
|
|
||||||
// Strictly speaking, we could talk to a proxy on the same port
|
|
||||||
// and reuse the connection. Its not worth the extra strcmp.
|
|
||||||
if ((info->mUsingHttpProxy != mUsingHttpProxy) ||
|
|
||||||
(info->mUsingSSL != mUsingSSL))
|
|
||||||
return PR_FALSE;
|
|
||||||
|
|
||||||
// if its a proxy, then compare the proxy servers.
|
|
||||||
if (mUsingHttpProxy && !mUsingSSL)
|
|
||||||
return (!PL_strcasecmp(info->ProxyHost(), ProxyHost()) &&
|
|
||||||
info->ProxyPort() == ProxyPort());
|
|
||||||
|
|
||||||
// otherwise, just check the hosts
|
|
||||||
return (!PL_strcasecmp(info->mHost, mHost) &&
|
|
||||||
info->mPort == mPort);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *Host() { return mHost; }
|
|
||||||
PRInt32 Port() { return mPort; }
|
|
||||||
nsIProxyInfo *ProxyInfo() { return mProxyInfo; }
|
|
||||||
PRBool UsingHttpProxy() { return mUsingHttpProxy; }
|
|
||||||
PRBool UsingSSL() { return mUsingSSL; }
|
|
||||||
|
|
||||||
PRInt32 DefaultPort() { return mUsingSSL ? 443 : 80; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsrefcnt mRef;
|
|
||||||
nsXPIDLCString mHost;
|
|
||||||
PRInt32 mPort;
|
|
||||||
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
|
||||||
PRPackedBool mUsingHttpProxy;
|
|
||||||
PRPackedBool mUsingSSL;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // nsHttpConnection_h__
|
#endif // nsHttpConnection_h__
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||||
|
/*
|
||||||
|
* The contents of this file are subject to the Mozilla Public
|
||||||
|
* License Version 1.1 (the "License"); you may not use this file
|
||||||
|
* except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS
|
||||||
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||||
|
* implied. See the License for the specific language governing
|
||||||
|
* rights and limitations under the License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Netscape
|
||||||
|
* Communications. Portions created by Netscape Communications are
|
||||||
|
* Copyright (C) 2001 by Netscape Communications. All
|
||||||
|
* Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Darin Fisher <darin@netscape.com> (original author)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef nsHttpConnectionInfo_h__
|
||||||
|
#define nsHttpConnectionInfo_h__
|
||||||
|
|
||||||
|
#include "nsHttp.h"
|
||||||
|
#include "nsIProxyInfo.h"
|
||||||
|
#include "nsXPIDLString.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "plstr.h"
|
||||||
|
#include "nsCRT.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// nsHttpConnectionInfo - holds the properties of a connection
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class nsHttpConnectionInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsHttpConnectionInfo(const char *host, PRInt32 port,
|
||||||
|
nsIProxyInfo* proxyInfo,
|
||||||
|
PRBool usingSSL=PR_FALSE)
|
||||||
|
: mRef(0)
|
||||||
|
, mProxyInfo(proxyInfo)
|
||||||
|
, mUsingSSL(usingSSL)
|
||||||
|
{
|
||||||
|
LOG(("Creating nsHttpConnectionInfo @%x\n", this));
|
||||||
|
|
||||||
|
mUsingHttpProxy = (proxyInfo && !nsCRT::strcmp(proxyInfo->Type(), "http"));
|
||||||
|
|
||||||
|
SetOriginServer(host, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
~nsHttpConnectionInfo()
|
||||||
|
{
|
||||||
|
LOG(("Destroying nsHttpConnectionInfo @%x\n", this));
|
||||||
|
}
|
||||||
|
|
||||||
|
nsrefcnt AddRef()
|
||||||
|
{
|
||||||
|
return PR_AtomicIncrement((PRInt32 *) &mRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsrefcnt Release()
|
||||||
|
{
|
||||||
|
nsrefcnt n = PR_AtomicDecrement((PRInt32 *) &mRef);
|
||||||
|
if (n == 0)
|
||||||
|
delete this;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult SetOriginServer(const char* host, PRInt32 port)
|
||||||
|
{
|
||||||
|
if (host)
|
||||||
|
mHost.Adopt(nsCRT::strdup(host));
|
||||||
|
mPort = port == -1 ? DefaultPort() : port;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *ProxyHost() const { return mProxyInfo ? mProxyInfo->Host() : nsnull; }
|
||||||
|
PRInt32 ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; }
|
||||||
|
const char *ProxyType() const { return mProxyInfo ? mProxyInfo->Type() : nsnull; }
|
||||||
|
|
||||||
|
// Compare this connection info to another...
|
||||||
|
// Two connections are 'equal' if they end up talking the same
|
||||||
|
// protocol to the same server. This is needed to properly manage
|
||||||
|
// persistent connections to proxies
|
||||||
|
// Note that we don't care about transparent proxies -
|
||||||
|
// it doesn't matter if we're talking via socks or not, since
|
||||||
|
// a request will end up at the same host.
|
||||||
|
PRBool Equals(const nsHttpConnectionInfo *info)
|
||||||
|
{
|
||||||
|
// Strictly speaking, we could talk to a proxy on the same port
|
||||||
|
// and reuse the connection. Its not worth the extra strcmp.
|
||||||
|
if ((info->mUsingHttpProxy != mUsingHttpProxy) ||
|
||||||
|
(info->mUsingSSL != mUsingSSL))
|
||||||
|
return PR_FALSE;
|
||||||
|
|
||||||
|
// if its a proxy, then compare the proxy servers.
|
||||||
|
if (mUsingHttpProxy && !mUsingSSL)
|
||||||
|
return (!PL_strcasecmp(info->ProxyHost(), ProxyHost()) &&
|
||||||
|
info->ProxyPort() == ProxyPort());
|
||||||
|
|
||||||
|
// otherwise, just check the hosts
|
||||||
|
return (!PL_strcasecmp(info->mHost, mHost) &&
|
||||||
|
info->mPort == mPort);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Host() { return mHost; }
|
||||||
|
PRInt32 Port() { return mPort; }
|
||||||
|
nsIProxyInfo *ProxyInfo() { return mProxyInfo; }
|
||||||
|
PRBool UsingHttpProxy() { return mUsingHttpProxy; }
|
||||||
|
PRBool UsingSSL() { return mUsingSSL; }
|
||||||
|
|
||||||
|
PRInt32 DefaultPort() { return mUsingSSL ? 443 : 80; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsrefcnt mRef;
|
||||||
|
nsXPIDLCString mHost;
|
||||||
|
PRInt32 mPort;
|
||||||
|
nsCOMPtr<nsIProxyInfo> mProxyInfo;
|
||||||
|
PRPackedBool mUsingHttpProxy;
|
||||||
|
PRPackedBool mUsingSSL;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // nsHttpConnectionInfo_h__
|
|
@ -476,7 +476,7 @@ nsHttpHandler::ProcessTransactionQ()
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpHandler::CancelTransaction(nsHttpTransaction *trans, nsresult status)
|
nsHttpHandler::CancelTransaction(nsHttpTransaction *trans, nsresult status)
|
||||||
{
|
{
|
||||||
nsHttpConnection *conn;
|
nsAHttpConnection *conn;
|
||||||
|
|
||||||
LOG(("nsHttpHandler::CancelTransaction [trans=%x status=%x]\n",
|
LOG(("nsHttpHandler::CancelTransaction [trans=%x status=%x]\n",
|
||||||
trans, status));
|
trans, status));
|
||||||
|
@ -797,7 +797,7 @@ nsHttpHandler::InitiateTransaction_Locked(nsHttpTransaction *trans,
|
||||||
// we must not hold the connection lock while making this call
|
// we must not hold the connection lock while making this call
|
||||||
// as it could lead to deadlocks.
|
// as it could lead to deadlocks.
|
||||||
PR_Unlock(mConnectionLock);
|
PR_Unlock(mConnectionLock);
|
||||||
rv = conn->SetTransaction(trans);
|
rv = conn->SetTransaction(trans, trans->Capabilities());
|
||||||
PR_Lock(mConnectionLock);
|
PR_Lock(mConnectionLock);
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
|
|
|
@ -178,17 +178,6 @@ nsHttpTransaction::SetupRequest(nsHttpRequestHead *requestHead,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
|
||||||
nsHttpTransaction::SetConnection(nsHttpConnection *conn)
|
|
||||||
{
|
|
||||||
LOG(("nsHttpTransaction::SetConnection [this=%x mConnection=%x conn=%x]\n",
|
|
||||||
this, mConnection, conn));
|
|
||||||
|
|
||||||
mConnection = conn;
|
|
||||||
NS_IF_ADDREF(mConnection);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsHttpResponseHead *
|
nsHttpResponseHead *
|
||||||
nsHttpTransaction::TakeResponseHead()
|
nsHttpTransaction::TakeResponseHead()
|
||||||
{
|
{
|
||||||
|
@ -200,6 +189,10 @@ nsHttpTransaction::TakeResponseHead()
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
// nsHttpTransaction::nsAHttpTransaction
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
// called on the socket transport thread
|
// called on the socket transport thread
|
||||||
nsresult
|
nsresult
|
||||||
nsHttpTransaction::OnDataWritable(nsIOutputStream *os)
|
nsHttpTransaction::OnDataWritable(nsIOutputStream *os)
|
||||||
|
@ -328,19 +321,21 @@ nsHttpTransaction::Restart()
|
||||||
NS_ADDREF_THIS();
|
NS_ADDREF_THIS();
|
||||||
|
|
||||||
// we don't want the connection to send anymore notifications to us.
|
// we don't want the connection to send anymore notifications to us.
|
||||||
mConnection->DropTransaction();
|
mConnection->DropTransaction(this);
|
||||||
|
|
||||||
nsHttpConnectionInfo *ci = mConnection->ConnectionInfo();
|
nsHttpConnectionInfo *ci = nsnull;
|
||||||
NS_ADDREF(ci);
|
mConnection->GetConnectionInfo(&ci);
|
||||||
|
NS_ASSERTION(ci, "connection info should be non-null");
|
||||||
|
if (ci) {
|
||||||
|
// we must release the connection before re-initiating this transaction
|
||||||
|
// since we'll be getting a new connection.
|
||||||
|
NS_RELEASE(mConnection);
|
||||||
|
|
||||||
// we must release the connection before calling initiate transaction
|
rv = nsHttpHandler::get()->InitiateTransaction(this, ci);
|
||||||
// since we will be getting a new connection.
|
NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed");
|
||||||
NS_RELEASE(mConnection);
|
|
||||||
|
|
||||||
rv = nsHttpHandler::get()->InitiateTransaction(this, ci);
|
NS_RELEASE(ci);
|
||||||
NS_ASSERTION(NS_SUCCEEDED(rv), "InitiateTransaction failed");
|
}
|
||||||
|
|
||||||
NS_RELEASE(ci);
|
|
||||||
NS_RELEASE_THIS();
|
NS_RELEASE_THIS();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -492,7 +487,7 @@ nsHttpTransaction::HandleContentStart()
|
||||||
#endif
|
#endif
|
||||||
// notify the connection, give it a chance to cause a reset.
|
// notify the connection, give it a chance to cause a reset.
|
||||||
PRBool reset = PR_FALSE;
|
PRBool reset = PR_FALSE;
|
||||||
mConnection->OnHeadersAvailable(this, &reset);
|
mConnection->OnHeadersAvailable(this, mResponseHead, &reset);
|
||||||
|
|
||||||
// looks like we should ignore this response, resetting...
|
// looks like we should ignore this response, resetting...
|
||||||
if (reset) {
|
if (reset) {
|
||||||
|
@ -578,10 +573,10 @@ nsHttpTransaction::HandleContent(char *buf,
|
||||||
}
|
}
|
||||||
else if (mContentLength >= 0) {
|
else if (mContentLength >= 0) {
|
||||||
// HTTP/1.0 servers have been known to send erroneous Content-Length
|
// HTTP/1.0 servers have been known to send erroneous Content-Length
|
||||||
// headers. So, unless the connection is keep-alive, we must make
|
// headers. So, unless the connection is persistent, 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 persistent, we simply accept everything in |buf|.
|
||||||
if (mConnection->IsKeepAlive()) {
|
if (mConnection->IsPersistent()) {
|
||||||
*countRead = PRUint32(mContentLength) - mContentRead;
|
*countRead = PRUint32(mContentLength) - mContentRead;
|
||||||
*countRead = PR_MIN(count, *countRead);
|
*countRead = PR_MIN(count, *countRead);
|
||||||
}
|
}
|
||||||
|
@ -761,7 +756,7 @@ nsHttpTransaction::Suspend()
|
||||||
{
|
{
|
||||||
LOG(("nsHttpTransaction::Suspend [this=%x]\n", this));
|
LOG(("nsHttpTransaction::Suspend [this=%x]\n", this));
|
||||||
if (mConnection && !mTransactionDone)
|
if (mConnection && !mTransactionDone)
|
||||||
mConnection->Suspend();
|
mConnection->OnSuspend();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,7 +766,7 @@ nsHttpTransaction::Resume()
|
||||||
{
|
{
|
||||||
LOG(("nsHttpTransaction::Resume [this=%x]\n", this));
|
LOG(("nsHttpTransaction::Resume [this=%x]\n", this));
|
||||||
if (mConnection && !mTransactionDone)
|
if (mConnection && !mTransactionDone)
|
||||||
mConnection->Resume();
|
mConnection->OnResume();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
|
|
||||||
#include "nsHttp.h"
|
#include "nsHttp.h"
|
||||||
#include "nsHttpHeaderArray.h"
|
#include "nsHttpHeaderArray.h"
|
||||||
|
#include "nsAHttpTransaction.h"
|
||||||
|
#include "nsAHttpConnection.h"
|
||||||
#include "nsIStreamListener.h"
|
#include "nsIStreamListener.h"
|
||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
#include "nsIInterfaceRequestor.h"
|
#include "nsIInterfaceRequestor.h"
|
||||||
|
@ -37,7 +39,6 @@
|
||||||
|
|
||||||
class nsHttpRequestHead;
|
class nsHttpRequestHead;
|
||||||
class nsHttpResponseHead;
|
class nsHttpResponseHead;
|
||||||
class nsHttpConnection;
|
|
||||||
class nsHttpChunkedDecoder;
|
class nsHttpChunkedDecoder;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -45,7 +46,8 @@ class nsHttpChunkedDecoder;
|
||||||
// intended to run on the socket thread.
|
// intended to run on the socket thread.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
class nsHttpTransaction : public nsIRequest
|
class nsHttpTransaction : public nsAHttpTransaction
|
||||||
|
, public nsIRequest
|
||||||
, public nsIInputStream
|
, public nsIInputStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -57,43 +59,32 @@ public:
|
||||||
nsHttpTransaction(nsIStreamListener *, nsIInterfaceRequestor *, PRUint8 caps);
|
nsHttpTransaction(nsIStreamListener *, nsIInterfaceRequestor *, PRUint8 caps);
|
||||||
virtual ~nsHttpTransaction();
|
virtual ~nsHttpTransaction();
|
||||||
|
|
||||||
nsrefcnt RefCnt() { return mRefCnt; }
|
|
||||||
|
|
||||||
// Called when assigned to a connection
|
|
||||||
nsresult SetConnection(nsHttpConnection *);
|
|
||||||
|
|
||||||
// Called by the connection to set the associated socket security info
|
|
||||||
void SetSecurityInfo(nsISupports *info) { mSecurityInfo = info; }
|
|
||||||
|
|
||||||
// Called to initialize the transaction
|
// Called to initialize the transaction
|
||||||
nsresult SetupRequest(nsHttpRequestHead *, nsIInputStream *);
|
nsresult SetupRequest(nsHttpRequestHead *, nsIInputStream *);
|
||||||
|
|
||||||
nsIStreamListener *Listener() { return mListener; }
|
nsIStreamListener *Listener() { return mListener; }
|
||||||
nsHttpConnection *Connection() { return mConnection; }
|
nsAHttpConnection *Connection() { return mConnection; }
|
||||||
nsHttpRequestHead *RequestHead() { return mRequestHead; }
|
nsHttpRequestHead *RequestHead() { return mRequestHead; }
|
||||||
nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; }
|
nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; }
|
||||||
nsIInterfaceRequestor *Callbacks() { return mCallbacks; }
|
nsIInterfaceRequestor *Callbacks() { return mCallbacks; }
|
||||||
nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; }
|
nsIEventQueue *ConsumerEventQ() { return mConsumerEventQ; }
|
||||||
nsISupports *SecurityInfo() { return mSecurityInfo; }
|
nsISupports *SecurityInfo() { return mSecurityInfo; }
|
||||||
PRBool IsDone() { return mTransactionDone; }
|
|
||||||
nsresult Status() { return mStatus; }
|
|
||||||
PRUint8 Capabilities() { return mCapabilities; }
|
PRUint8 Capabilities() { return mCapabilities; }
|
||||||
|
|
||||||
// Called to take ownership of the response headers; the transaction
|
// Called to take ownership of the response headers; the transaction
|
||||||
// will drop any reference to the response headers after this call.
|
// will drop any reference to the response headers after this call.
|
||||||
nsHttpResponseHead *TakeResponseHead();
|
nsHttpResponseHead *TakeResponseHead();
|
||||||
|
|
||||||
// Called to write data to the socket until return NS_BASE_STREAM_CLOSED
|
// nsAHttpTransaction methods:
|
||||||
|
void SetConnection(nsAHttpConnection *conn) { NS_IF_ADDREF(mConnection = conn); }
|
||||||
|
void SetSecurityInfo(nsISupports *info) { mSecurityInfo = info; }
|
||||||
|
void GetNotificationCallbacks(nsIInterfaceRequestor **cb) { NS_IF_ADDREF(*cb = mCallbacks); }
|
||||||
nsresult OnDataWritable(nsIOutputStream *);
|
nsresult OnDataWritable(nsIOutputStream *);
|
||||||
|
|
||||||
// Called to read data from the socket buffer
|
|
||||||
nsresult OnDataReadable(nsIInputStream *);
|
nsresult OnDataReadable(nsIInputStream *);
|
||||||
|
|
||||||
// Called when the transaction should stop, possibly prematurely with an error.
|
|
||||||
nsresult OnStopTransaction(nsresult);
|
nsresult OnStopTransaction(nsresult);
|
||||||
|
|
||||||
// Called by the connection to report socket status
|
|
||||||
void OnStatus(nsresult status, const PRUnichar *statusText);
|
void OnStatus(nsresult status, const PRUnichar *statusText);
|
||||||
|
PRBool IsDone() { return mTransactionDone; }
|
||||||
|
nsresult Status() { return mStatus; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsresult Restart();
|
nsresult Restart();
|
||||||
|
@ -114,7 +105,7 @@ private:
|
||||||
nsCOMPtr<nsIEventQueue> mConsumerEventQ;
|
nsCOMPtr<nsIEventQueue> mConsumerEventQ;
|
||||||
nsCOMPtr<nsISupports> mSecurityInfo;
|
nsCOMPtr<nsISupports> mSecurityInfo;
|
||||||
|
|
||||||
nsHttpConnection *mConnection; // hard ref
|
nsAHttpConnection *mConnection; // hard ref
|
||||||
|
|
||||||
nsCString mReqHeaderBuf; // flattened request headers
|
nsCString mReqHeaderBuf; // flattened request headers
|
||||||
nsCOMPtr<nsIInputStream> mReqHeaderStream; // header data stream
|
nsCOMPtr<nsIInputStream> mReqHeaderStream; // header data stream
|
||||||
|
|
Загрузка…
Ссылка в новой задаче