зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1581637
- Part 8 - Add Http3Session/Http3Stream. r=mayhemer
Differential Revision: https://phabricator.services.mozilla.com/D46652 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e6722f5da2
Коммит
e7b8f84a64
|
@ -63,7 +63,7 @@ class ASpdySession : public nsAHttpTransaction {
|
|||
// soft errors are errors that terminate a stream without terminating the
|
||||
// connection. In general non-network errors are stream errors as well
|
||||
// as network specific items like cancels.
|
||||
bool SoftStreamError(nsresult code) {
|
||||
static bool SoftStreamError(nsresult code) {
|
||||
if (NS_SUCCEEDED(code) || code == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
return false;
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,175 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=4 sw=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef Http3Session_H__
|
||||
#define Http3Session_H__
|
||||
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "mozilla/net/NeqoHttp3Conn.h"
|
||||
#include "nsAHttpConnection.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "HttpTrafficAnalyzer.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class Http3Stream;
|
||||
class QuicSocketControl;
|
||||
|
||||
// IID for the Http3Session interface
|
||||
#define NS_HTTP3SESSION_IID \
|
||||
{ \
|
||||
0x8fc82aaf, 0xc4ef, 0x46ed, { \
|
||||
0x89, 0x41, 0x93, 0x95, 0x8f, 0xac, 0x4f, 0x21 \
|
||||
} \
|
||||
}
|
||||
|
||||
class Http3Session final : public nsAHttpTransaction,
|
||||
public nsAHttpConnection,
|
||||
public nsAHttpSegmentReader,
|
||||
public nsAHttpSegmentWriter,
|
||||
public nsITimerCallback {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_HTTP3SESSION_IID)
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSAHTTPTRANSACTION
|
||||
NS_DECL_NSAHTTPCONNECTION(mConnection)
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
|
||||
Http3Session();
|
||||
nsresult Init(const nsACString& aOrigin, nsISocketTransport* aSocketTransport,
|
||||
nsHttpConnection* readerWriter);
|
||||
|
||||
bool IsConnected() const { return mState == CONNECTED; }
|
||||
bool IsClosing() const { return (mState == CLOSING || mState == CLOSED); }
|
||||
nsresult GetError() const { return mError; }
|
||||
|
||||
nsresult Process();
|
||||
|
||||
bool AddStream(nsAHttpTransaction* aHttpTransaction, int32_t aPriority,
|
||||
nsIInterfaceRequestor* aCallbacks);
|
||||
|
||||
bool CanReuse();
|
||||
|
||||
// TODO: use this.
|
||||
bool RoomForMoreStreams() { return mQueuedStreams.GetSize() == 0; }
|
||||
|
||||
// We will let neqo-transport handle connection timeouts.
|
||||
uint32_t ReadTimeoutTick(PRIntervalTime now) { return UINT32_MAX; }
|
||||
|
||||
// overload of nsAHttpTransaction
|
||||
MOZ_MUST_USE nsresult ReadSegmentsAgain(nsAHttpSegmentReader*, uint32_t,
|
||||
uint32_t*, bool*) final;
|
||||
MOZ_MUST_USE nsresult WriteSegmentsAgain(nsAHttpSegmentWriter*, uint32_t,
|
||||
uint32_t*, bool*) final;
|
||||
|
||||
bool ResponseTimeoutEnabled() const final { return true; }
|
||||
PRIntervalTime ResponseTimeout() final;
|
||||
|
||||
// The folowing functions are used by Http3Stream:
|
||||
nsresult TryActivating(const nsACString& aMethod, const nsACString& aScheme,
|
||||
const nsACString& aHost, const nsACString& aPath,
|
||||
const nsACString& aHeaders, uint64_t* aStreamId,
|
||||
Http3Stream* aStream);
|
||||
void CloseSendingSide(uint64_t aStreamId);
|
||||
nsresult SendRequestBody(uint64_t aStreamId, const char* buf, uint32_t count,
|
||||
uint32_t* countRead);
|
||||
nsresult ReadResponseHeaders(uint64_t aStreamId,
|
||||
nsTArray<uint8_t>& aResponseHeaders, bool* aFin);
|
||||
nsresult ReadResponseData(uint64_t aStreamId, char* aBuf, uint32_t aCount,
|
||||
uint32_t* aCountWritten, bool* aFin);
|
||||
|
||||
const static uint32_t kDefaultReadAmount = 2048;
|
||||
|
||||
void CloseStream(Http3Stream* aStream, nsresult aResult);
|
||||
|
||||
void SetCleanShutdown(bool aCleanShutdown) {
|
||||
mCleanShutdown = aCleanShutdown;
|
||||
}
|
||||
|
||||
PRIntervalTime IdleTime();
|
||||
|
||||
bool TestJoinConnection(const nsACString& hostname, int32_t port);
|
||||
bool JoinConnection(const nsACString& hostname, int32_t port);
|
||||
|
||||
void TransactionHasDataToWrite(nsAHttpTransaction* caller) override;
|
||||
|
||||
nsISocketTransport* SocketTransport() { return mSocketTransport; }
|
||||
|
||||
// This function will be called by QuicSocketControl when the certificate
|
||||
// verification is done.
|
||||
void Authenticated(int32_t aError);
|
||||
|
||||
private:
|
||||
~Http3Session();
|
||||
|
||||
void CloseInternal(bool aCallNeqoClose);
|
||||
void Shutdown();
|
||||
|
||||
bool RealJoinConnection(const nsACString& hostname, int32_t port,
|
||||
bool justKidding);
|
||||
|
||||
nsresult ProcessOutput();
|
||||
nsresult ProcessInput();
|
||||
nsresult ProcessEvents(uint32_t count, uint32_t* countWritten, bool* again);
|
||||
nsresult ProcessOutputAndEvents();
|
||||
|
||||
void SetupTimer(uint64_t aTimeout);
|
||||
|
||||
void ResetRecvd(uint64_t aStreamId, Http3AppError aError);
|
||||
|
||||
void QueueStream(Http3Stream* stream);
|
||||
void RemoveStreamFromQueues(Http3Stream*);
|
||||
void ProcessPending();
|
||||
|
||||
void CallCertVerification();
|
||||
void SetSecInfo();
|
||||
|
||||
RefPtr<NeqoHttp3Conn> mHttp3Connection;
|
||||
RefPtr<nsAHttpConnection> mConnection;
|
||||
nsRefPtrHashtable<nsUint64HashKey, Http3Stream> mStreamIdHash;
|
||||
nsRefPtrHashtable<nsPtrHashKey<nsAHttpTransaction>, Http3Stream>
|
||||
mStreamTransactionHash;
|
||||
|
||||
nsDeque mReadyForWrite;
|
||||
nsDeque mQueuedStreams;
|
||||
|
||||
enum State { INITIALIZING, CONNECTED, CLOSING, CLOSED } mState;
|
||||
|
||||
bool mAuthenticationStarted;
|
||||
bool mCleanShutdown;
|
||||
bool mGoawayReceived;
|
||||
bool mShouldClose;
|
||||
nsresult mError;
|
||||
bool mBeforeConnectedError;
|
||||
uint64_t mCurrentForegroundTabOuterContentWindowId;
|
||||
|
||||
nsTArray<uint8_t> mPacketToSend;
|
||||
|
||||
RefPtr<nsHttpConnection> mSegmentReaderWriter;
|
||||
|
||||
// The underlying socket transport object is needed to propogate some events
|
||||
RefPtr<nsISocketTransport> mSocketTransport;
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
|
||||
nsDataHashtable<nsCStringHashKey, bool> mJoinConnectionCache;
|
||||
|
||||
RefPtr<QuicSocketControl> mSocketControl;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Http3Session, NS_HTTP3SESSION_IID);
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // Http3Session_H__
|
|
@ -0,0 +1,332 @@
|
|||
/* -*- 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 "nsISocketTransport.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
Http3Stream::Http3Stream(nsAHttpTransaction* httpTransaction,
|
||||
Http3Session* session)
|
||||
: mState(PREPARING_HEADERS),
|
||||
mStreamId(UINT64_MAX),
|
||||
mSession(session),
|
||||
mTransaction(httpTransaction),
|
||||
mRequestHeadersDone(false),
|
||||
mRequestStarted(false),
|
||||
mQueued(false),
|
||||
mRequestBlockedOnRead(false),
|
||||
mDataReceived(false),
|
||||
mRequestBodyLenRemaining(0),
|
||||
mSocketTransport(session->SocketTransport()),
|
||||
mTotalSent(0),
|
||||
mTotalRead(0),
|
||||
mFin(false) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG3(("Http3Stream::Http3Stream [this=%p]", this));
|
||||
}
|
||||
|
||||
void Http3Stream::Close(nsresult aResult) { mTransaction->Close(aResult); }
|
||||
|
||||
void Http3Stream::GetHeadersString(const char* buf, uint32_t avail,
|
||||
uint32_t* countUsed) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG3(("Http3Stream::GetHeadersString %p avail=%u.", this, avail));
|
||||
|
||||
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 = %u",
|
||||
this, mFlatHttpRequestHeaders.Length()));
|
||||
*countUsed = avail;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t oldLen = mFlatHttpRequestHeaders.Length();
|
||||
mFlatHttpRequestHeaders.SetLength(endHeader + 2);
|
||||
*countUsed = avail - (oldLen - endHeader) + 4;
|
||||
|
||||
FindRequestContentLength();
|
||||
mRequestHeadersDone = true;
|
||||
}
|
||||
|
||||
void Http3Stream::FindRequestContentLength() {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
// Look for Content-Length header to find out if we have request body and
|
||||
// how long it is.
|
||||
int32_t contentLengthStart = mFlatHttpRequestHeaders.Find("Content-Length:");
|
||||
if (contentLengthStart == -1) {
|
||||
// There is no content-Length.
|
||||
return;
|
||||
}
|
||||
|
||||
// We have Content-Length header, find the end of it.
|
||||
int32_t crlfIndex = mFlatHttpRequestHeaders.Find("\r\n", false, contentLengthStart);
|
||||
if (crlfIndex == -1) {
|
||||
MOZ_ASSERT(false, "We must have \\r\\n at the end of the headers string.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the beginning.
|
||||
int32_t valueIndex =
|
||||
mFlatHttpRequestHeaders.Find(":", false, contentLengthStart) + 1;
|
||||
if (valueIndex > crlfIndex) {
|
||||
// Content-Length headers is empty.
|
||||
MOZ_ASSERT(false, "Content-Length must have a value.");
|
||||
return;
|
||||
}
|
||||
|
||||
const char* beginBuffer = mFlatHttpRequestHeaders.BeginReading();
|
||||
while (valueIndex < crlfIndex && beginBuffer[valueIndex] == ' ') {
|
||||
++valueIndex;
|
||||
}
|
||||
|
||||
nsDependentCSubstring value =
|
||||
Substring(beginBuffer + valueIndex, beginBuffer + crlfIndex);
|
||||
|
||||
int64_t len;
|
||||
nsCString tmp(value);
|
||||
if (nsHttp::ParseInt64(tmp.get(), nullptr, &len)) {
|
||||
mRequestBodyLenRemaining = len;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Http3Stream::TryActivating() {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG(("Http3Stream::TryActivating [this=%p]", this));
|
||||
nsHttpRequestHead* head = mTransaction->RequestHead();
|
||||
|
||||
nsAutoCString authorityHeader;
|
||||
nsresult rv = head->GetHeader(nsHttp::Host, authorityHeader);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsDependentCString scheme(head->IsHTTPS() ? "https" : "http");
|
||||
|
||||
nsAutoCString method;
|
||||
nsAutoCString path;
|
||||
head->Method(method);
|
||||
head->Path(path);
|
||||
|
||||
rv = mSession->TryActivating(method, scheme, authorityHeader, path,
|
||||
mFlatHttpRequestHeaders, &mStreamId, this);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mRequestStarted = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult Http3Stream::OnReadSegment(const char* buf, uint32_t count,
|
||||
uint32_t* countRead) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
LOG(("Http3Stream::OnReadSegment count=%u state=%d [this=%p]", count, mState,
|
||||
this));
|
||||
|
||||
switch (mState) {
|
||||
case PREPARING_HEADERS:
|
||||
GetHeadersString(buf, count, countRead);
|
||||
|
||||
if (*countRead) {
|
||||
mTotalSent += *countRead;
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_SENDING_TO, mTotalSent);
|
||||
}
|
||||
MOZ_ASSERT(!mRequestStarted, "We should be in one of the next states.");
|
||||
if (mRequestHeadersDone && !mRequestStarted) {
|
||||
nsresult rv = TryActivating();
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
LOG3(("Http3Stream::OnReadSegment %p cannot activate now. queued.\n",
|
||||
this));
|
||||
return *countRead ? NS_OK : NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("Http3Stream::OnReadSegment %p cannot activate error=0x%" PRIx32
|
||||
".",
|
||||
this, static_cast<uint32_t>(rv)));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (mRequestStarted) {
|
||||
if (mRequestBodyLenRemaining) {
|
||||
mState = SENDING_BODY;
|
||||
} else {
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_WAITING_FOR, 0);
|
||||
mSession->CloseSendingSide(mStreamId);
|
||||
mState = READING_HEADERS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SENDING_BODY: {
|
||||
nsresult rv = mSession->SendRequestBody(mStreamId, buf, count, countRead);
|
||||
MOZ_ASSERT(mRequestBodyLenRemaining >= *countRead,
|
||||
"We cannot send more that than we promised.");
|
||||
if (mRequestBodyLenRemaining < *countRead) {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG3(("Http3Stream::OnReadSegment %p sending body returns "
|
||||
"error=0x%" PRIx32 ".", this, static_cast<uint32_t>(rv)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRequestBodyLenRemaining -= *countRead;
|
||||
if (!mRequestBodyLenRemaining) {
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_WAITING_FOR, 0);
|
||||
mSession->CloseSendingSide(mStreamId);
|
||||
mState = READING_HEADERS;
|
||||
}
|
||||
} break;
|
||||
case EARLY_RESPONSE:
|
||||
// We do not need to send the rest of the request, so just ignore it.
|
||||
*countRead = count;
|
||||
mRequestBodyLenRemaining -= count;
|
||||
if (!mRequestBodyLenRemaining) {
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_WAITING_FOR, 0);
|
||||
mState = READING_HEADERS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "We are done sending this request!");
|
||||
break;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Http3Stream::OnWriteSegment(char* buf, uint32_t count,
|
||||
uint32_t* countWritten) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
LOG(("Http3Stream::OnWriteSegment [this=%p, state=%d", this, mState));
|
||||
nsresult rv = NS_OK;
|
||||
switch (mState) {
|
||||
case PREPARING_HEADERS:
|
||||
case SENDING_BODY:
|
||||
case EARLY_RESPONSE:
|
||||
break;
|
||||
case READING_HEADERS: {
|
||||
if (mFlatResponseHeaders.IsEmpty()) {
|
||||
nsresult rv = mSession->ReadResponseHeaders(
|
||||
mStreamId, mFlatResponseHeaders, &mFin);
|
||||
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
|
||||
return rv;
|
||||
}
|
||||
LOG(("Http3Stream::OnWriteSegment [this=%p, read %u bytes of headers",
|
||||
this, (uint32_t)mFlatResponseHeaders.Length()));
|
||||
}
|
||||
*countWritten = (mFlatResponseHeaders.Length() > count)
|
||||
? count
|
||||
: mFlatResponseHeaders.Length();
|
||||
memcpy(buf, mFlatResponseHeaders.Elements(), *countWritten);
|
||||
|
||||
mFlatResponseHeaders.RemoveElementsAt(0, *countWritten);
|
||||
if (mFlatResponseHeaders.Length() == 0) {
|
||||
mState = mFin ? RECEIVED_FIN : READING_DATA;
|
||||
}
|
||||
|
||||
if (*countWritten == 0 ) {
|
||||
rv = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
} else {
|
||||
mTotalRead += *countWritten;
|
||||
mTransaction->OnTransportStatus(mSocketTransport,
|
||||
NS_NET_STATUS_RECEIVING_FROM, mTotalRead);
|
||||
}
|
||||
} break;
|
||||
case READING_DATA: {
|
||||
rv = mSession->ReadResponseData(mStreamId, buf, count, countWritten,
|
||||
&mFin);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (*countWritten == 0) {
|
||||
if (mFin) {
|
||||
mState = DONE;
|
||||
rv = NS_BASE_STREAM_CLOSED;
|
||||
} else {
|
||||
rv = NS_BASE_STREAM_WOULD_BLOCK;
|
||||
}
|
||||
} else {
|
||||
mTotalRead += *countWritten;
|
||||
mTransaction->OnTransportStatus(
|
||||
mSocketTransport, NS_NET_STATUS_RECEIVING_FROM, mTotalRead);
|
||||
|
||||
if (mFin) {
|
||||
mState = RECEIVED_FIN;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case RECEIVED_FIN:
|
||||
case RECEIVED_RESET:
|
||||
rv = NS_BASE_STREAM_CLOSED;
|
||||
break;
|
||||
case DONE:
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult Http3Stream::ReadSegments(nsAHttpSegmentReader* reader, uint32_t count,
|
||||
uint32_t* countRead) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
|
||||
mRequestBlockedOnRead = false;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
switch (mState) {
|
||||
case PREPARING_HEADERS:
|
||||
case SENDING_BODY: {
|
||||
rv = mTransaction->ReadSegments(this, count, countRead);
|
||||
LOG(("Http3Stream::ReadSegments rv=0x%" PRIx32 " [this=%p]",
|
||||
static_cast<uint32_t>(rv), this));
|
||||
|
||||
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
|
||||
mRequestBlockedOnRead = true;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
*countRead = 0;
|
||||
rv = NS_OK;
|
||||
break;
|
||||
}
|
||||
LOG(("Http3Stream::ReadSegments rv=0x%" PRIx32 " [this=%p]",
|
||||
static_cast<uint32_t>(rv), this));
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult Http3Stream::WriteSegments(nsAHttpSegmentWriter* writer,
|
||||
uint32_t count, uint32_t* countWritten) {
|
||||
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
|
||||
LOG(("Http3Stream::WriteSegments [this=%p]", this));
|
||||
nsresult rv = mTransaction->WriteSegments(this, count, countWritten);
|
||||
LOG(("Http3Stream::WriteSegments rv=0x%" PRIx32 " [this=%p]",
|
||||
static_cast<uint32_t>(rv), this));
|
||||
return rv;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef mozilla_net_Http3Stream_h
|
||||
#define mozilla_net_Http3Stream_h
|
||||
|
||||
#include "nsAHttpTransaction.h"
|
||||
#include "ARefBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class Http3Session;
|
||||
|
||||
class Http3Stream final : public nsAHttpSegmentReader,
|
||||
public nsAHttpSegmentWriter,
|
||||
public ARefBase {
|
||||
public:
|
||||
NS_DECL_NSAHTTPSEGMENTREADER
|
||||
NS_DECL_NSAHTTPSEGMENTWRITER
|
||||
// for RefPtr
|
||||
NS_INLINE_DECL_REFCOUNTING(Http3Stream, override)
|
||||
|
||||
Http3Stream(nsAHttpTransaction* httpTransaction, Http3Session* session);
|
||||
|
||||
bool HasStreamId() const { return mStreamId != UINT64_MAX; }
|
||||
uint64_t StreamId() const { return mStreamId; }
|
||||
|
||||
nsresult TryActivating();
|
||||
|
||||
// TODO priorities
|
||||
void TopLevelOuterContentWindowIdChanged(uint64_t windowId){};
|
||||
|
||||
MOZ_MUST_USE nsresult ReadSegments(nsAHttpSegmentReader*, uint32_t,
|
||||
uint32_t*);
|
||||
MOZ_MUST_USE nsresult WriteSegments(nsAHttpSegmentWriter*, uint32_t,
|
||||
uint32_t*);
|
||||
|
||||
bool RequestBlockedOnRead() const { return mRequestBlockedOnRead; }
|
||||
|
||||
void SetQueued(bool aStatus) { mQueued = aStatus; }
|
||||
bool Queued() const { return mQueued; }
|
||||
|
||||
bool Done() const { return mState == DONE; }
|
||||
|
||||
void Close(nsresult aResult);
|
||||
bool RecvdData() const { return mDataReceived; }
|
||||
|
||||
nsAHttpTransaction* Transaction() { return mTransaction; }
|
||||
bool RecvdFin() const { return mState == RECEIVED_FIN; }
|
||||
bool RecvdReset() const { return mState == RECEIVED_RESET; }
|
||||
void SetRecvdReset() { mState = RECEIVED_RESET; }
|
||||
|
||||
private:
|
||||
~Http3Stream() = default;
|
||||
|
||||
void GetHeadersString(const char* buf, uint32_t avail, uint32_t* countUsed);
|
||||
nsresult StartRequest();
|
||||
void FindRequestContentLength();
|
||||
|
||||
/**
|
||||
* StreamState:
|
||||
* While sending request:
|
||||
* - PREPARING_HEADERS:
|
||||
* In this state we are collecting the headers and in some cases also
|
||||
* waiting to be able to create a new stream.
|
||||
* We need to read all headers into a buffer before calling
|
||||
* Http3Session::TryActivating. Neqo may not have place for a new
|
||||
* stream if it hits MAX_STREAMS limit. In that case the steam will be
|
||||
* queued and dequeue when neqo can again create new stream
|
||||
* (RequestsCreatable will be called).
|
||||
* If transaction has data to send state changes to SENDING_BODY,
|
||||
* otherwise the state transfers to READING_HEADERS.
|
||||
* - SENDING_BODY:
|
||||
* The stream will be in this state while the transaction is sending
|
||||
* request body. Http3Session::SendRequestBody will be call to give
|
||||
* the data to neqo.
|
||||
* After SENDING_BODY, the state transfers to READING_HEADERS.
|
||||
* - EARLY_RESPONSE:
|
||||
* The server may send STOP_SENDING frame with error HTTP_EARLY_RESPONSE.
|
||||
* That error means that the server is not interested in the request body.
|
||||
* In this state the server will just ignore the request body.
|
||||
* After sending a request, the transaction reads data:
|
||||
* - READING_HEADERS:
|
||||
* In this state Http3Session::ReadResponseHeaders will be called to read
|
||||
* the response headers. All headers will be read at once into
|
||||
* mFlatResponseHeaders. The stream will be in this state until all
|
||||
* headers are given to the transaction.
|
||||
* If the stream has been closed by the server after sending headers the
|
||||
* stream will transit into RECEIVED_FIN state, otherwise it transits to
|
||||
* READING_DATA state.
|
||||
* - READING_DATA:
|
||||
* In this state Http3Session::ReadResponseData will be called and the
|
||||
* response body will be given to the transaction.
|
||||
* This state may transfer to RECEIVED_FIN or DONE state.
|
||||
* - RECEIVED_FIN:
|
||||
* The stream is in this state when the receiving side is closed by the
|
||||
* server and this information is not given to the transaction yet.
|
||||
* (example 1: ReadResponseData(Http3Stream is in READING_DATA state)
|
||||
* returns 10 bytes and fin set to true (the server has closed the
|
||||
* stream). The transaction will get this 10 bytes, but it cannot get
|
||||
* the information about the fin at the same time. The Http3Stream
|
||||
* transit into RECEIVED_FIN state. The transaction will need to call
|
||||
* OnWriteSegment again and the Http3Stream::OnWriteSegment will return
|
||||
* NS_BASE_STREAM_CLOSED which means that the stream has been closed.
|
||||
* example 2: if ReadResponseData(Http3Stream is in READING_DATA state)
|
||||
* returns 0 bytes and a fin set to true. Http3Stream::OnWriteSegment
|
||||
* will return NS_BASE_STREAM_CLOSED to the transaction and transfer to
|
||||
* state DONE.)
|
||||
* - RECEIVED_RESET:
|
||||
* The stream has been reset by the server.
|
||||
* - DONE:
|
||||
* The transaction is done.
|
||||
**/
|
||||
enum StreamState {
|
||||
PREPARING_HEADERS,
|
||||
SENDING_BODY,
|
||||
EARLY_RESPONSE,
|
||||
READING_HEADERS,
|
||||
READING_DATA,
|
||||
RECEIVED_FIN,
|
||||
RECEIVED_RESET,
|
||||
DONE
|
||||
} mState;
|
||||
|
||||
uint64_t mStreamId;
|
||||
Http3Session* mSession;
|
||||
RefPtr<nsAHttpTransaction> mTransaction;
|
||||
nsCString mFlatHttpRequestHeaders;
|
||||
bool mRequestHeadersDone;
|
||||
bool mRequestStarted;
|
||||
bool mQueued;
|
||||
bool mRequestBlockedOnRead;
|
||||
bool mDataReceived;
|
||||
nsTArray<uint8_t> mFlatResponseHeaders;
|
||||
uint32_t mRequestBodyLenRemaining;
|
||||
|
||||
// The underlying socket transport object is needed to propogate some events
|
||||
RefPtr<nsISocketTransport> mSocketTransport;
|
||||
|
||||
// For Progress Events
|
||||
uint64_t mTotalSent;
|
||||
uint64_t mTotalRead;
|
||||
|
||||
bool mFin;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_net_Http3Stream_h
|
|
@ -43,20 +43,17 @@ QuicSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
|
|||
}
|
||||
|
||||
void QuicSocketControl::CallAuthenticated() {
|
||||
// // Will be added when Http3 lands
|
||||
/* if (mHttp3Session) {
|
||||
if (mHttp3Session) {
|
||||
RefPtr<Http3Session> http3Session = do_QueryReferent(mHttp3Session);
|
||||
http3Session->Authenticated(GetErrorCode());
|
||||
}
|
||||
mHttp3Session = nullptr;*/
|
||||
mHttp3Session = nullptr;
|
||||
}
|
||||
|
||||
// Will be added when Http3 lands
|
||||
// void QuicSocketControl::SetAuthenticationCallback(Http3Session
|
||||
// *aHttp3Session) {
|
||||
// mHttp3Session = do_GetWeakReference(
|
||||
// static_cast<nsISupportsWeakReference*>(aHttp3Session));
|
||||
//}
|
||||
void QuicSocketControl::SetAuthenticationCallback(Http3Session* aHttp3Session) {
|
||||
mHttp3Session = do_GetWeakReference(
|
||||
static_cast<nsISupportsWeakReference*>(aHttp3Session));
|
||||
}
|
||||
|
||||
void QuicSocketControl::HandshakeCompleted() {
|
||||
psm::RememberCertErrorsTable::GetInstance().LookupCertErrorBits(this);
|
||||
|
|
|
@ -12,8 +12,7 @@
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Will be added when Http3 lands.
|
||||
// class Http3Session;
|
||||
class Http3Session;
|
||||
|
||||
// IID for the QuicSocketControl interface
|
||||
#define NS_QUICSOCKETCONTROL_IID \
|
||||
|
@ -37,8 +36,7 @@ class QuicSocketControl final : public CommonSocketControl {
|
|||
void SetInfo(uint16_t aCipherSuite, uint16_t aProtocolVersion,
|
||||
uint16_t aKeaGroup, uint16_t aSignatureScheme);
|
||||
|
||||
// Will be added when Http3 lands.
|
||||
// void SetAuthenticationCallback(Http3Session *aHttp3Session);
|
||||
void SetAuthenticationCallback(Http3Session* aHttp3Session);
|
||||
void CallAuthenticated();
|
||||
|
||||
void HandshakeCompleted();
|
||||
|
|
|
@ -77,6 +77,8 @@ UNIFIED_SOURCES += [
|
|||
'Http2Push.cpp',
|
||||
'Http2Session.cpp',
|
||||
'Http2Stream.cpp',
|
||||
'Http3Session.cpp',
|
||||
'Http3Stream.cpp',
|
||||
'HttpAuthUtils.cpp',
|
||||
'HttpBackgroundChannelChild.cpp',
|
||||
'HttpBackgroundChannelParent.cpp',
|
||||
|
@ -134,6 +136,7 @@ LOCAL_INCLUDES += [
|
|||
'/netwerk/base',
|
||||
'/netwerk/cookie',
|
||||
'/netwerk/ipc',
|
||||
'/netwerk/socket/neqo_glue',
|
||||
'/netwerk/url-classifier',
|
||||
]
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ EXPORTS += [
|
|||
'RootCertificateTelemetryUtils.h',
|
||||
'ScopedNSSTypes.h',
|
||||
'SharedCertVerifier.h',
|
||||
'SSLServerCertVerification.h',
|
||||
'TransportSecurityInfo.h',
|
||||
]
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче