NS_IMETHODIMP nsPipeOutputStream::WriteFrom(nsIInputStream* fromStream, PRUint32 count, PRUint32 *writeCount) { return WriteSegments(nsReadFromInputStream, fromStream, count, writeCount); }
NS_IMETHODIMP nsPipeOutputStream::Write(const char* fromBuf, PRUint32 bufLen, PRUint32 *writeCount) { return WriteSegments(nsReadFromRawBuffer, (void*)fromBuf, bufLen, writeCount); }
nsresult nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer, PRUint32 count, PRUint32 *countWritten) { LOG(("nsHttpPipeline::WriteSegments [this=%x count=%u]\n", this, count)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); if (mClosed) return NS_SUCCEEDED(mStatus) ? NS_BASE_STREAM_CLOSED : mStatus; nsAHttpTransaction *trans; nsresult rv; trans = Response(0); if (!trans) { if (mRequestQ.Count() > 0) rv = NS_BASE_STREAM_WOULD_BLOCK; else rv = NS_BASE_STREAM_CLOSED; } else { // // ask the transaction to consume data from the connection. // PushBack may be called recursively. // rv = trans->WriteSegments(writer, count, countWritten); if (rv == NS_BASE_STREAM_CLOSED || trans->IsDone()) { trans->Close(NS_OK); NS_RELEASE(trans); mResponseQ.RemoveElementAt(0); mResponseIsPartial = PR_FALSE; // ask the connection manager to add additional transactions // to our pipeline. gHttpHandler->ConnMgr()->AddTransactionToPipeline(this); } else mResponseIsPartial = PR_TRUE; } if (mPushBackLen) { nsHttpPushBackWriter writer(mPushBackBuf, mPushBackLen); PRUint32 len = mPushBackLen, n; mPushBackLen = 0; // 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). rv = WriteSegments(&writer, len, &n); } return rv; }
nsresult nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer, PRUint32 count, PRUint32 *countWritten) { LOG(("nsHttpPipeline::WriteSegments [this=%x count=%u]\n", this, count)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); if (mClosed) return NS_SUCCEEDED(mStatus) ? NS_BASE_STREAM_CLOSED : mStatus; nsAHttpTransaction *trans; nsresult rv; trans = Response(0); // This code deals with the establishment of a CONNECT tunnel through // an HTTP proxy. It allows the connection to do the CONNECT/200 // HTTP transaction to establish an SSL tunnel as a precursor to the // actual pipeline of regular HTTP transactions. if (!trans && mRequestQ.Length() && mConnection->IsProxyConnectInProgress()) { LOG(("nsHttpPipeline::WriteSegments [this=%p] Forced Delegation\n", this)); trans = Request(0); } if (!trans) { if (mRequestQ.Length() > 0) rv = NS_BASE_STREAM_WOULD_BLOCK; else rv = NS_BASE_STREAM_CLOSED; } else { // // ask the transaction to consume data from the connection. // PushBack may be called recursively. // rv = trans->WriteSegments(writer, count, countWritten); if (rv == NS_BASE_STREAM_CLOSED || trans->IsDone()) { trans->Close(NS_OK); // Release the transaction if it is not IsProxyConnectInProgress() if (trans == Response(0)) { NS_RELEASE(trans); mResponseQ.RemoveElementAt(0); mResponseIsPartial = false; ++mHttp1xTransactionCount; } // ask the connection manager to add additional transactions // to our pipeline. nsRefPtr<nsHttpConnectionInfo> ci; GetConnectionInfo(getter_AddRefs(ci)); if (ci) gHttpHandler->ConnMgr()->ProcessPendingQForEntry(ci); } else mResponseIsPartial = true; } if (mPushBackLen) { 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). rv = WriteSegments(&writer, len, &n); } return rv; }
nsresult nsHttpPipeline::WriteSegments(nsAHttpSegmentWriter *writer, PRUint32 count, PRUint32 *countWritten) { LOG(("nsHttpPipeline::WriteSegments [this=%x count=%u]\n", this, count)); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); if (mClosed) return NS_SUCCEEDED(mStatus) ? NS_BASE_STREAM_CLOSED : mStatus; nsAHttpTransaction *trans; nsresult rv; trans = Response(0); if (!trans) { if (mRequestQ.Length() > 0) rv = NS_BASE_STREAM_WOULD_BLOCK; else rv = NS_BASE_STREAM_CLOSED; } else { // // ask the transaction to consume data from the connection. // PushBack may be called recursively. // rv = trans->WriteSegments(writer, count, countWritten); if (rv == NS_BASE_STREAM_CLOSED || trans->IsDone()) { trans->Close(NS_OK); NS_RELEASE(trans); mResponseQ.RemoveElementAt(0); mResponseIsPartial = false; ++mHttp1xTransactionCount; // ask the connection manager to add additional transactions // to our pipeline. gHttpHandler->ConnMgr()->AddTransactionToPipeline(this); } else mResponseIsPartial = true; } if (mPushBackLen) { 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). rv = WriteSegments(&writer, len, &n); } return rv; }