/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=8 et tw=80 : */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first #include"HttpLog.h" #include"Http3Session.h" #include"Http3Stream.h" #include"nsHttpRequestHead.h" #include"nsHttpTransaction.h" #include"nsIClassOfService.h" #include"nsISocketTransport.h" #include"nsSocketTransportService2.h" #include"mozilla/StaticPrefs_network.h" #include"mozilla/Telemetry.h" #include"nsIOService.h" #include"nsHttpHandler.h"
mFlatHttpRequestHeaders.Append(buf, avail); // We can use the simple double crlf because firefox is the // only client we are parsing
int32_t endHeader = mFlatHttpRequestHeaders.Find("\r\n\r\n");
if (endHeader == kNotFound) { // We don't have all the headers yet
LOG3(
("Http3Stream::GetHeadersString %p " "Need more header bytes. Len = %zu", this, mFlatHttpRequestHeaders.Length()));
*countUsed = avail; returnfalse;
}
mSendState = SENDING_BODY; break; case SENDING_BODY: {
rv = mSession->SendRequestBody(mStreamId, buf, count, countRead); if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
mSendingBlockedByFlowControlCount++;
}
if (NS_FAILED(rv)) {
LOG3(
("Http3Stream::OnReadSegment %p sending body returns " "error=0x%" PRIx32 ".", this, static_cast<uint32_t>(rv))); break;
}
#ifdef DEBUG
mRequestBodyLenSent += *countRead; #endif
mTotalSent += *countRead;
mTransaction->OnTransportStatus(nullptr, NS_NET_STATUS_SENDING_TO,
mTotalSent);
} break; case EARLY_RESPONSE: // We do not need to send the rest of the request, so just ignore it.
*countRead = count; #ifdef DEBUG
mRequestBodyLenSent += count; #endif break; default:
MOZ_ASSERT(false, "We are done sending this request!");
rv = NS_ERROR_UNEXPECTED; break;
}
LOG(("Http3Stream::OnWriteSegment [this=%p, state=%d", this, mRecvState));
nsresult rv = NS_OK; switch (mRecvState) { case BEFORE_HEADERS: {
*countWritten = 0;
rv = NS_BASE_STREAM_WOULD_BLOCK;
} break; case READING_HEADERS: case READING_INTERIM_HEADERS: { // SetResponseHeaders should have been previously called.
MOZ_ASSERT(!mFlatResponseHeaders.IsEmpty(), "Headers empty!");
*countWritten = (mFlatResponseHeaders.Length() > count)
? count
: mFlatResponseHeaders.Length();
memcpy(buf, mFlatResponseHeaders.Elements(), *countWritten);
mFlatResponseHeaders.RemoveElementsAt(0, *countWritten); if (mFlatResponseHeaders.Length() == 0) { if (mRecvState == READING_INTERIM_HEADERS) { // neqo makes sure that fin cannot be received before the final // headers are received.
MOZ_ASSERT(!mFin);
mRecvState = BEFORE_HEADERS;
} else {
mRecvState = mFin ? RECEIVED_FIN : READING_DATA;
}
}
if (mFin) {
mRecvState = RECEIVED_FIN;
}
}
} break; case RECEIVED_FIN:
rv = NS_BASE_STREAM_CLOSED;
mRecvState = RECV_DONE; break; case RECV_DONE:
rv = NS_ERROR_UNEXPECTED;
}
// Remember the error received from lower layers. A stream pipe may overwrite // it. // If rv == NS_OK this will reset mSocketInCondition.
mSocketInCondition = rv;
return rv;
}
nsresult Http3Stream::ReadSegments() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
if (mRecvState == RECV_DONE) { // Don't transmit any request frames if the peer cannot respond or respone // is already done.
LOG3(
("Http3Stream %p ReadSegments request stream aborted due to" " response side closure\n", this)); return NS_ERROR_ABORT;
}
nsresult rv = NS_OK;
uint32_t transactionBytes; bool again = true; do {
transactionBytes = 0;
rv = mSocketOutCondition = NS_OK;
LOG(("Http3Stream::ReadSegments state=%d [this=%p]", mSendState, this)); switch (mSendState) { case WAITING_TO_ACTIVATE: { // A transaction that had already generated its headers before it was // queued at the session level (due to concurrency concerns) may not // call onReadSegment off the ReadSegments() stack above.
LOG3(
("Http3Stream %p ReadSegments forcing OnReadSegment call\n", this));
uint32_t wasted = 0;
nsresult rv2 = OnReadSegment("", 0, &wasted);
LOG3((" OnReadSegment returned 0x%08" PRIx32, static_cast<uint32_t>(rv2))); if (mSendState != SENDING_BODY) { break;
}
} // If we are in state SENDING_BODY we can continue sending data.
[[fallthrough]]; case PREPARING_HEADERS: case SENDING_BODY: {
rv = mTransaction->ReadSegmentsAgain( this, nsIOService::gDefaultSegmentSize, &transactionBytes, &again);
} break; default:
transactionBytes = 0;
rv = NS_OK; break;
}
// XXX some streams return NS_BASE_STREAM_CLOSED to indicate EOF. if (rv == NS_BASE_STREAM_CLOSED && !mTransaction->IsDone()) {
rv = NS_OK;
transactionBytes = 0;
}
if (NS_FAILED(rv)) { // if the transaction didn't want to write any more data, then // wait for the transaction to call ResumeSend. if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = NS_OK;
}
again = false;
} elseif (NS_FAILED(mSocketOutCondition)) { if (mSocketOutCondition != NS_BASE_STREAM_WOULD_BLOCK) {
rv = mSocketOutCondition;
}
again = false;
} elseif (!transactionBytes) {
mTransaction->OnTransportStatus(nullptr, NS_NET_STATUS_WAITING_FOR, 0);
mSession->CloseSendingSide(mStreamId);
mSendState = SEND_DONE;
Telemetry::Accumulate(
Telemetry::HTTP3_SENDING_BLOCKED_BY_FLOW_CONTROL_PER_TRANS,
mSendingBlockedByFlowControlCount);
#ifdef DEBUG
MOZ_ASSERT(mRequestBodyLenSent == mRequestBodyLenExpected); #endif
rv = NS_OK;
again = false;
} // write more to the socket until error or end-of-request...
} while (again && gHttpHandler->Active()); return rv;
}
do {
mSocketInCondition = NS_OK;
countWrittenSingle = 0;
rv = mTransaction->WriteSegmentsAgain( this, nsIOService::gDefaultSegmentSize, &countWrittenSingle, &again);
LOG(("Http3Stream::WriteSegments rv=0x%" PRIx32 " countWrittenSingle=%" PRIu32 " socketin=%" PRIx32 " [this=%p]", static_cast<uint32_t>(rv), countWrittenSingle, static_cast<uint32_t>(mSocketInCondition), this)); if (mTransaction->IsDone()) { // If a transaction has read the amount of data specified in // Content-Length it is marked as done.The Http3Stream should be // marked as done as well to start the process of cleanup and // closure.
mRecvState = RECV_DONE;
}
if (NS_FAILED(rv)) { // if the transaction didn't want to take any more data, then // wait for the transaction to call ResumeRecv. if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
rv = NS_OK;
}
again = false;
} elseif (NS_FAILED(mSocketInCondition)) { if (mSocketInCondition != NS_BASE_STREAM_WOULD_BLOCK) {
rv = mSocketInCondition;
}
again = false;
} // read more from the socket until error...
} while (again && gHttpHandler->Active());
uint8_t Http3Stream::PriorityUrgency() { if (!StaticPrefs::network_http_http3_priority()) { // send default priority which is equivalent to sending no priority return 3;
}
bool Http3Stream::PriorityIncremental() { if (!StaticPrefs::network_http_http3_priority()) { // send default priority which is equivalent to sending no priority returnfalse;
} return mPriorityIncremental;
}
} // namespace net
} // namespace mozilla
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.