bug 718206 fix spdy nsitransport event generation r=honzab

This commit is contained in:
Patrick McManus 2012-01-25 15:21:13 -05:00
parent 2ee6ccd415
commit d336c36446
3 changed files with 88 additions and 42 deletions

View File

@ -851,6 +851,8 @@ SpdySession::HandleSynReply(SpdySession *self)
return NS_OK;
}
self->mFrameDataStream->UpdateTransportReadEvents(self->mFrameDataSize);
if (!self->mFrameDataStream->SetFullyOpen()) {
// "If an endpoint receives multiple SYN_REPLY frames for the same active
// stream ID, it must drop the stream, and send a RST_STREAM for the
@ -1128,6 +1130,9 @@ SpdySession::HandleHeaders(SpdySession *self)
// this is actually not legal in the HTTP mapping of SPDY. All
// headers are in the syn or syn reply. Log and ignore it.
// in v3 this will be legal and we must remember to note
// NS_NET_STATUS_RECEIVING_FROM from it
LOG3(("SpdySession::HandleHeaders %p HEADERS for Stream 0x%X. "
"They are ignored in the HTTP/SPDY mapping.",
self, streamID));
@ -1148,29 +1153,6 @@ SpdySession::HandleWindowUpdate(SpdySession *self)
return NS_OK;
}
// Used for the hashtable enumeration to propogate OnTransportStatus events
struct transportStatus
{
nsITransport *transport;
nsresult status;
PRUint64 progress;
};
static PLDHashOperator
StreamTransportStatus(nsAHttpTransaction *key,
nsAutoPtr<SpdyStream> &stream,
void *closure)
{
struct transportStatus *status =
static_cast<struct transportStatus *>(closure);
stream->Transaction()->OnTransportStatus(status->transport,
status->status,
status->progress);
return PL_DHASH_NEXT;
}
//-----------------------------------------------------------------------------
// nsAHttpTransaction. It is expected that nsHttpConnection is the caller
// of these methods
@ -1183,21 +1165,47 @@ SpdySession::OnTransportStatus(nsITransport* aTransport,
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
// nsHttpChannel synthesizes progress events in OnDataAvailable
if (aStatus == nsISocketTransport::STATUS_RECEIVING_FROM)
return;
switch (aStatus) {
// These should appear only once, deliver to the first
// transaction on the session.
case NS_NET_STATUS_RESOLVING_HOST:
case NS_NET_STATUS_RESOLVED_HOST:
case NS_NET_STATUS_CONNECTING_TO:
case NS_NET_STATUS_CONNECTED_TO:
{
SpdyStream *target = mStreamIDHash.Get(1);
if (target)
target->Transaction()->OnTransportStatus(aTransport, aStatus, aProgress);
break;
}
// STATUS_SENDING_TO is handled by SpdyStream
if (aStatus == nsISocketTransport::STATUS_SENDING_TO)
return;
default:
// The other transport events are ignored here because there is no good
// way to map them to the right transaction in spdy. Instead, the events
// are generated again from the spdy code and passed directly to the
// correct transaction.
struct transportStatus status;
status.transport = aTransport;
status.status = aStatus;
status.progress = aProgress;
// NS_NET_STATUS_SENDING_TO:
// This is generated by the socket transport when (part) of
// a transaction is written out
//
// There is no good way to map it to the right transaction in spdy,
// so it is ignored here and generated separately when the SYN_STREAM
// is sent from SpdyStream::TransmitFrame
mStreamTransactionHash.Enumerate(StreamTransportStatus, &status);
// NS_NET_STATUS_WAITING_FOR:
// Created by nsHttpConnection when the request has been totally sent.
// There is no good way to map it to the right transaction in spdy,
// so it is ignored here and generated separately when the same
// condition is complete in SpdyStream when there is no more
// request body left to be transmitted.
// NS_NET_STATUS_RECEIVING_FROM
// Generated in spdysession whenever we read a data frame or a syn_reply
// that can be attributed to a particular stream/transaction
break;
}
}
// ReadSegments() is used to write data to the network. Generally, HTTP
@ -1675,6 +1683,7 @@ SpdySession::OnWriteSegment(char *buf,
mFrameDataRead += *countWritten;
mFrameDataStream->UpdateTransportReadEvents(*countWritten);
if ((mFrameDataRead == mFrameDataSize) && !mFrameDataLast)
ChangeDownstreamState(BUFFERING_FRAME_HEADER);

View File

@ -75,6 +75,7 @@ SpdyStream::SpdyStream(nsAHttpTransaction *httpTransaction,
mSentFinOnData(0),
mRecvdFin(0),
mFullyOpen(0),
mSentWaitingFor(0),
mTxInlineFrameAllocation(SpdySession::kDefaultBufferSize),
mTxInlineFrameSize(0),
mTxInlineFrameSent(0),
@ -82,7 +83,9 @@ SpdyStream::SpdyStream(nsAHttpTransaction *httpTransaction,
mTxStreamFrameSent(0),
mZlib(compressionContext),
mRequestBodyLen(0),
mPriority(priority)
mPriority(priority),
mTotalSent(0),
mTotalRead(0)
{
NS_ABORT_IF_FALSE(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -458,6 +461,36 @@ SpdyStream::ParseHttpRequestHeaders(const char *buf,
return NS_OK;
}
void
SpdyStream::UpdateTransportReadEvents(PRUint32 count)
{
mTotalRead += count;
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_RECEIVING_FROM,
mTotalRead);
}
void
SpdyStream::UpdateTransportSendEvents(PRUint32 count)
{
mTotalSent += count;
if (mUpstreamState != SENDING_FIN_STREAM)
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_SENDING_TO,
mTotalSent);
if (!mSentWaitingFor && !mRequestBodyLen &&
mTxInlineFrameSent == mTxInlineFrameSize &&
mTxStreamFrameSent == mTxStreamFrameSize) {
mSentWaitingFor = 1;
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_WAITING_FOR,
LL_ZERO);
}
}
nsresult
SpdyStream::TransmitFrame(const char *buf,
PRUint32 *countUsed)
@ -538,16 +571,11 @@ SpdyStream::TransmitFrame(const char *buf,
SpdySession::LogIO(mSession, this, "Writing from Transaction Buffer",
buf + offset, transmittedCount);
if (mUpstreamState == SENDING_REQUEST_BODY) {
mTransaction->OnTransportStatus(mSocketTransport,
nsISocketTransport::STATUS_SENDING_TO,
transmittedCount);
}
*countUsed += transmittedCount;
avail -= transmittedCount;
offset += transmittedCount;
mTxStreamFrameSent += transmittedCount;
UpdateTransportSendEvents(transmittedCount);
}
if (!avail) {

View File

@ -89,6 +89,9 @@ public:
void SetRecvdFin(bool aStatus) { mRecvdFin = aStatus ? 1 : 0; }
bool RecvdFin() { return mRecvdFin; }
void UpdateTransportSendEvents(PRUint32 count);
void UpdateTransportReadEvents(PRUint32 count);
// The zlib header compression dictionary defined by SPDY,
// and hooks to the mozilla allocator for zlib to use.
static const char *kDictionary;
@ -171,6 +174,9 @@ private:
// Flag is set after syn reply received
PRUint32 mFullyOpen : 1;
// Flag is set after the WAITING_FOR Transport event has been generated
PRUint32 mSentWaitingFor : 1;
// The InlineFrame and associated data is used for composing control
// frames and data frame headers.
nsAutoArrayPtr<char> mTxInlineFrame;
@ -200,6 +206,9 @@ private:
// based on nsISupportsPriority definitions
PRInt32 mPriority;
// For Progress Events
PRUint64 mTotalSent;
PRUint64 mTotalRead;
};
}} // namespace mozilla::net