bug 671875 pipeline transport event fixups r=honzab

This commit is contained in:
Patrick McManus 2011-12-01 09:19:41 -05:00
Родитель e3abab38ee
Коммит 7927a9bae0
5 изменённых файлов: 128 добавлений и 11 удалений

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

@ -124,6 +124,10 @@ public:
// Transfer the base http connection object along with a
// reference to it to the caller.
virtual nsHttpConnection *TakeHttpConnection() = 0;
// Get the nsISocketTransport used by the connection without changing
// references or ownership.
virtual nsISocketTransport *Transport() = 0;
};
#define NS_DECL_NSAHTTPCONNECTION \
@ -141,6 +145,7 @@ public:
nsresult PushBack(const char *, PRUint32); \
bool LastTransactionExpectedNoContent(); \
void SetLastTransactionExpectedNoContent(bool); \
nsHttpConnection *TakeHttpConnection();
nsHttpConnection *TakeHttpConnection(); \
nsISocketTransport *Transport();
#endif // nsAHttpConnection_h__

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

@ -123,6 +123,7 @@ public:
mLastTransactionExpectedNoContent = val;
}
nsISocketTransport *Transport() { return mSocketTransport; }
nsAHttpTransaction *Transaction() { return mTransaction; }
nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }

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

@ -1693,3 +1693,11 @@ nsConnectionHandle::SetLastTransactionExpectedNoContent(bool val)
{
mConn->SetLastTransactionExpectedNoContent(val);
}
nsISocketTransport *
nsHttpConnectionMgr::nsConnectionHandle::Transport()
{
if (!mConn)
return nsnull;
return mConn->Transport();
}

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

@ -101,6 +101,9 @@ nsHttpPipeline::nsHttpPipeline()
, mPushBackBuf(nsnull)
, mPushBackLen(0)
, mPushBackMax(0)
, mReceivingFromProgress(0)
, mSendingToProgress(0)
, mSuppressSendEvents(true)
{
}
@ -325,6 +328,14 @@ nsHttpPipeline::TakeHttpConnection()
return nsnull;
}
nsISocketTransport *
nsHttpPipeline::Transport()
{
if (!mConnection)
return nsnull;
return mConnection->Transport();
}
void
nsHttpPipeline::SetSSLConnectFailed()
{
@ -390,21 +401,80 @@ nsHttpPipeline::OnTransportStatus(nsITransport* transport,
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
nsAHttpTransaction *trans;
PRInt32 i, count;
switch (status) {
case NS_NET_STATUS_RECEIVING_FROM:
// forward this only to the transaction currently recieving data
trans = Response(0);
case NS_NET_STATUS_RESOLVING_HOST:
case NS_NET_STATUS_RESOLVED_HOST:
case NS_NET_STATUS_CONNECTING_TO:
case NS_NET_STATUS_CONNECTED_TO:
// These should only appear at most once per pipeline.
// Deliver to the first transaction.
trans = Request(0);
if (!trans)
trans = Response(0);
if (trans)
trans->OnTransportStatus(transport, status, progress);
break;
default:
// forward other notifications to all transactions
PRInt32 i, count = mRequestQ.Length();
for (i=0; i<count; ++i) {
trans = Request(i);
if (trans)
trans->OnTransportStatus(transport, status, progress);
case NS_NET_STATUS_SENDING_TO:
// This is generated by the socket transport when (part) of
// a transaction is written out
//
// In pipelining this is generated out of FillSendBuf(), but it cannot do
// so until the connection is confirmed by CONNECTED_TO.
// See patch for bug 196827.
//
if (mSuppressSendEvents) {
mSuppressSendEvents = false;
// catch up by sending the event to all the transactions that have
// moved from request to response and any that have been partially
// sent. Also send WAITING_FOR to those that were completely sent
count = mResponseQ.Length();
for (i = 0; i < count; ++i) {
Response(i)->OnTransportStatus(transport,
NS_NET_STATUS_SENDING_TO,
progress);
Response(i)->OnTransportStatus(transport,
NS_NET_STATUS_WAITING_FOR,
progress);
}
if (mRequestIsPartial && Request(0))
Request(0)->OnTransportStatus(transport,
NS_NET_STATUS_SENDING_TO,
progress);
mSendingToProgress = progress;
}
// otherwise ignore it
break;
case NS_NET_STATUS_WAITING_FOR:
// Created by nsHttpConnection when request pipeline has been totally
// sent. Ignore it here because it is simulated in FillSendBuf() when
// a request is moved from request to response.
// ignore it
break;
case NS_NET_STATUS_RECEIVING_FROM:
// Forward this only to the transaction currently recieving data. It is
// normally generated by the socket transport, but can also
// be repeated by the pushbackwriter if necessary.
mReceivingFromProgress = progress;
if (Response(0))
Response(0)->OnTransportStatus(transport, status, progress);
break;
default:
// forward other notifications to all request transactions
count = mRequestQ.Length();
for (i = 0; i < count; ++i)
Request(i)->OnTransportStatus(transport, status, progress);
break;
}
}
@ -548,6 +618,16 @@ nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer,
nsHttpPushBackWriter writer(mPushBackBuf, mPushBackLen);
PRUint32 len = mPushBackLen, n;
mPushBackLen = 0;
// This progress notification has previously been sent from
// the socket transport code, but it was delivered to the
// previous transaction on the pipeline.
nsITransport *transport = Transport();
if (transport)
OnTransportStatus(transport,
nsISocketTransport::STATUS_RECEIVING_FROM,
mReceivingFromProgress);
// the push back buffer is never larger than NS_HTTP_SEGMENT_SIZE,
// so we are guaranteed that the next response will eat the entire
// push back buffer (even though it might again call PushBack).
@ -638,6 +718,8 @@ nsHttpPipeline::FillSendBuf()
PRUint32 n, avail;
nsAHttpTransaction *trans;
nsITransport *transport = Transport();
while ((trans = Request(0)) != nsnull) {
avail = trans->Available();
if (avail) {
@ -648,13 +730,29 @@ nsHttpPipeline::FillSendBuf()
LOG(("send pipe is full"));
break;
}
mSendingToProgress += n;
if (!mSuppressSendEvents && transport) {
// Simulate a SENDING_TO event
trans->OnTransportStatus(transport,
NS_NET_STATUS_SENDING_TO,
mSendingToProgress);
}
}
avail = trans->Available();
if (avail == 0) {
// move transaction from request queue to response queue
mRequestQ.RemoveElementAt(0);
mResponseQ.AppendElement(trans);
mRequestIsPartial = false;
if (!mSuppressSendEvents && transport) {
// Simulate a WAITING_FOR event
trans->OnTransportStatus(transport,
NS_NET_STATUS_WAITING_FOR,
mSendingToProgress);
}
}
else
mRequestIsPartial = true;

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

@ -111,6 +111,11 @@ private:
char *mPushBackBuf;
PRUint32 mPushBackLen;
PRUint32 mPushBackMax;
// For support of OnTransportStatus()
PRUint64 mReceivingFromProgress;
PRUint64 mSendingToProgress;
bool mSuppressSendEvents;
};
#endif // nsHttpPipeline_h__