Bug 1582663 - Add HttpConnectionUDP. It is just a copy of nsHttpConnection. r=mayhemer

Depends on D64035

Differential Revision: https://phabricator.services.mozilla.com/D64037

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Dragana Damjanovic 2020-02-28 10:20:11 +00:00
Родитель c0693368e2
Коммит 8ffeb14135
14 изменённых файлов: 3279 добавлений и 28 удалений

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

@ -9,6 +9,7 @@
#include "nsHttpConnectionMgr.h"
#include "nsHttpConnection.h"
#include "HttpConnectionUDP.h"
#include "Http2Session.h"
#include "nsHttpHandler.h"
#include "nsIConsoleService.h"
@ -157,6 +158,38 @@ void nsHttpConnection::PrintDiagnostics(nsCString& log) {
if (mSpdySession) mSpdySession->PrintDiagnostics(log);
}
void HttpConnectionUDP::PrintDiagnostics(nsCString& log) {
log.AppendPrintf(" CanDirectlyActivate = %d\n", CanDirectlyActivate());
log.AppendPrintf(" npncomplete = %d setupSSLCalled = %d\n", mNPNComplete,
mSetupSSLCalled);
log.AppendPrintf(" spdyVersion = %d reportedSpdy = %d everspdy = %d\n",
static_cast<int32_t>(mUsingSpdyVersion), mReportedSpdy,
mEverUsedSpdy);
log.AppendPrintf(" iskeepalive = %d dontReuse = %d isReused = %d\n",
IsKeepAlive(), mDontReuse, mIsReused);
log.AppendPrintf(" mTransaction = %d mSpdySession = %d\n",
!!mTransaction.get(), !!mSpdySession.get());
PRIntervalTime now = PR_IntervalNow();
log.AppendPrintf(" time since last read = %ums\n",
PR_IntervalToMilliseconds(now - mLastReadTime));
log.AppendPrintf(" max-read/read/written %" PRId64 "/%" PRId64 "/%" PRId64
"\n",
mMaxBytesRead, mTotalBytesRead, mTotalBytesWritten);
log.AppendPrintf(" rtt = %ums\n", PR_IntervalToMilliseconds(mRtt));
log.AppendPrintf(" idlemonitoring = %d transactionCount=%d\n",
mIdleMonitoring, mHttp1xTransactionCount);
if (mSpdySession) mSpdySession->PrintDiagnostics(log);
}
void Http2Session::PrintDiagnostics(nsCString& log) {
log.AppendPrintf(" ::: HTTP2\n");
log.AppendPrintf(

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

@ -19,7 +19,7 @@
#include "nsThreadUtils.h"
#include "QuicSocketControl.h"
#include "SSLServerCertVerification.h"
//#include "cert.h"
#include "HttpConnectionUDP.h"
#include "sslerr.h"
namespace mozilla {
@ -72,7 +72,7 @@ Http3Session::Http3Session()
nsresult Http3Session::Init(const nsACString& aOrigin,
nsISocketTransport* aSocketTransport,
nsHttpConnection* readerWriter) {
HttpConnectionUDP* readerWriter) {
LOG3(("Http3Session::Init %p", this));
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
@ -334,7 +334,7 @@ nsresult Http3Session::ProcessEvents(uint32_t count, uint32_t* countWritten,
mError = NS_ERROR_NET_HTTP3_PROTOCOL_ERROR;
}
mIsClosedByNeqo = true;
// We need to return here and let nsHttpConnection close the session.
// We need to return here and let HttpConnectionUDP close the session.
return mError;
break;
default:

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

@ -20,6 +20,7 @@
namespace mozilla {
namespace net {
class HttpConnectionUDP;
class Http3Stream;
class QuicSocketControl;
@ -48,7 +49,7 @@ class Http3Session final : public nsAHttpTransaction,
Http3Session();
nsresult Init(const nsACString& aOrigin, nsISocketTransport* aSocketTransport,
nsHttpConnection* readerWriter);
HttpConnectionUDP* readerWriter);
bool IsConnected() const { return mState == CONNECTED; }
bool IsClosing() const { return (mState == CLOSING || mState == CLOSED); }
@ -157,7 +158,7 @@ class Http3Session final : public nsAHttpTransaction,
nsTArray<uint8_t> mPacketToSend;
RefPtr<nsHttpConnection> mSegmentReaderWriter;
RefPtr<HttpConnectionUDP> mSegmentReaderWriter;
// The underlying socket transport object is needed to propogate some events
RefPtr<nsISocketTransport> mSocketTransport;

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

@ -22,7 +22,6 @@
#include "nsIAsyncOutputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsITimer.h"
#include "Http3Session.h"
class nsISocketTransport;
class nsISSLSocketControl;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -0,0 +1,360 @@
/* -*- Mode: C++; tab-width: 4; 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 HttpConnectionUDP_h__
#define HttpConnectionUDP_h__
#include "HttpConnectionBase.h"
#include "nsHttpConnectionInfo.h"
#include "nsHttpResponseHead.h"
#include "nsAHttpTransaction.h"
#include "nsCOMPtr.h"
#include "nsProxyRelease.h"
#include "prinrval.h"
#include "TunnelUtils.h"
#include "mozilla/Mutex.h"
#include "ARefBase.h"
#include "TimingStruct.h"
#include "HttpTrafficAnalyzer.h"
#include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsITimer.h"
#include "Http3Session.h"
class nsISocketTransport;
class nsISSLSocketControl;
namespace mozilla {
namespace net {
class nsHttpHandler;
class ASpdySession;
// 1dcc863e-db90-4652-a1fe-13fea0b54e46
#define HTTPCONNECTIONUDP_IID \
{ \
0xb97d2036, 0xb441, 0x48be, { \
0xb3, 0x1e, 0x25, 0x3e, 0xe8, 0x32, 0xdd, 0x67 \
} \
}
//-----------------------------------------------------------------------------
// HttpConnectionUDP - represents a connection to a HTTP3 server
//
// NOTE: this objects lives on the socket thread only. it should not be
// accessed from any other thread.
//-----------------------------------------------------------------------------
class HttpConnectionUDP final : public HttpConnectionBase,
public nsAHttpSegmentReader,
public nsAHttpSegmentWriter,
public nsIInputStreamCallback,
public nsIOutputStreamCallback,
public nsITransportEventSink,
public nsIInterfaceRequestor,
public NudgeTunnelCallback {
private:
virtual ~HttpConnectionUDP();
public:
NS_DECLARE_STATIC_IID_ACCESSOR(HTTPCONNECTIONUDP_IID)
NS_DECL_HTTPCONNECTIONBASE
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSAHTTPSEGMENTREADER
NS_DECL_NSAHTTPSEGMENTWRITER
NS_DECL_NSIINPUTSTREAMCALLBACK
NS_DECL_NSIOUTPUTSTREAMCALLBACK
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NUDGETUNNELCALLBACK
HttpConnectionUDP();
void SetFastOpen(bool aFastOpen);
// Close this connection and return the transaction. The transaction is
// restarted as well. This will only happened before connection is
// connected.
nsAHttpTransaction* CloseConnectionFastOpenTakesTooLongOrError(
bool aCloseocketTransport);
//-------------------------------------------------------------------------
// XXX document when these are ok to call
bool IsKeepAlive() {
return (mUsingSpdyVersion != SpdyVersion::NONE) ||
(mKeepAliveMask && mKeepAlive);
}
// Returns time in seconds for how long connection can be reused.
uint32_t TimeToLive() override;
bool NeedSpdyTunnel() {
return mConnInfo->UsingHttpsProxy() && !mTLSFilter &&
mConnInfo->UsingConnect();
}
// A connection is forced into plaintext when it is intended to be used as a
// CONNECT tunnel but the setup fails. The plaintext only carries the CONNECT
// error.
void ForcePlainText() { mForcePlainText = true; }
bool IsUrgentStartPreferred() const override {
return mUrgentStartPreferredKnown && mUrgentStartPreferred;
}
void SetUrgentStartPreferred(bool urgent) override;
void SetIsReusedAfter(uint32_t afterMilliseconds) override;
int64_t MaxBytesRead() override { return mMaxBytesRead; }
HttpVersion GetLastHttpResponseVersion() { return mLastHttpResponseVersion; }
friend class HttpConnectionUDPForceIO;
static MOZ_MUST_USE nsresult ReadFromStream(nsIInputStream*, void*,
const char*, uint32_t, uint32_t,
uint32_t*);
// When a persistent connection is in the connection manager idle
// connection pool, the HttpConnectionUDP still reads errors and hangups
// on the socket so that it can be proactively released if the server
// initiates a termination. Only call on socket thread.
void BeginIdleMonitoring() override;
void EndIdleMonitoring() override;
bool UsingSpdy() override { return (mUsingSpdyVersion != SpdyVersion::NONE); }
SpdyVersion GetSpdyVersion() { return mUsingSpdyVersion; }
bool EverUsedSpdy() override { return mEverUsedSpdy; }
bool UsingHttp3() override { return mHttp3Session; }
// true when connection SSL NPN phase is complete and we know
// authoritatively whether UsingSpdy() or not.
bool ReportedNPN() override { return mReportedSpdy; }
// When the connection is active this is called up to once every 1 second
// return the interval (in seconds) that the connection next wants to
// have this invoked. It might happen sooner depending on the needs of
// other connections.
uint32_t ReadTimeoutTick(PRIntervalTime now);
// For Active and Idle connections, this will be called when
// mTCPKeepaliveTransitionTimer fires, to check if the TCP keepalive config
// should move from short-lived (fast-detect) to long-lived.
static void UpdateTCPKeepalive(nsITimer* aTimer, void* aClosure);
// When the connection is active this is called every second
void ReadTimeoutTick();
int64_t ContentBytesWritten() { return mContentBytesWritten; }
static MOZ_MUST_USE nsresult MakeConnectString(nsAHttpTransaction* trans,
nsHttpRequestHead* request,
nsACString& result, bool h2ws);
void SetupSecondaryTLS(nsAHttpTransaction* aSpdyConnectTransaction = nullptr);
void SetInSpdyTunnel(bool arg);
// Check active connections for traffic (or not). SPDY connections send a
// ping, ordinary HTTP connections get some time to get traffic to be
// considered alive.
// Http3 has its own ping triggered by a separate timer, therefore it does not
// use this one.
void CheckForTraffic(bool check);
// NoTraffic() returns true if there's been no traffic on the (non-spdy)
// connection since CheckForTraffic() was called.
bool NoTraffic() {
return mTrafficStamp &&
(mTrafficCount == (mTotalBytesWritten + mTotalBytesRead)) &&
!mFastOpen;
}
void SetFastOpenStatus(uint8_t tfoStatus);
uint8_t GetFastOpenStatus() { return mFastOpenStatus; }
// Return true when the socket this connection is using has not been
// authenticated using a client certificate. Before SSL negotiation
// has finished this returns false.
bool NoClientCertAuth() const override;
private:
// Value (set in mTCPKeepaliveConfig) indicates which set of prefs to use.
enum TCPKeepaliveConfig {
kTCPKeepaliveDisabled = 0,
kTCPKeepaliveShortLivedConfig,
kTCPKeepaliveLongLivedConfig
};
// called to cause the underlying socket to start speaking SSL
MOZ_MUST_USE nsresult InitSSLParams(bool connectingToProxy,
bool ProxyStartSSL);
MOZ_MUST_USE nsresult SetupNPNList(nsISSLSocketControl* ssl, uint32_t caps);
MOZ_MUST_USE nsresult OnTransactionDone(nsresult reason);
MOZ_MUST_USE nsresult OnSocketWritable();
MOZ_MUST_USE nsresult OnSocketReadable();
MOZ_MUST_USE nsresult SetupProxyConnect();
PRIntervalTime IdleTime();
bool IsAlive();
// Makes certain the SSL handshake is complete and NPN negotiation
// has had a chance to happen
MOZ_MUST_USE bool EnsureNPNComplete(nsresult& aOut0RTTWriteHandshakeValue,
uint32_t& aOut0RTTBytesWritten);
// This performs the quic transport handshake. The handshake also performs TLS
// handshake at the same time.
MOZ_MUST_USE bool EnsureNPNCompleteHttp3();
void SetupSSL();
// Start the Spdy transaction handler when NPN indicates spdy/*
void StartSpdy(nsISSLSocketControl* ssl, SpdyVersion versionLevel);
// Like the above, but do the bare minimum to do 0RTT data, so we can back
// it out, if necessary
void Start0RTTSpdy(SpdyVersion versionLevel);
// Helpers for Start*Spdy
nsresult TryTakeSubTransactions(nsTArray<RefPtr<nsAHttpTransaction> >& list);
nsresult MoveTransactionsToSpdy(nsresult status,
nsTArray<RefPtr<nsAHttpTransaction> >& list);
// Directly Add a transaction to an active connection for SPDY
MOZ_MUST_USE nsresult AddTransaction(nsAHttpTransaction*, int32_t);
// Used to set TCP keepalives for fast detection of dead connections during
// an initial period, and slower detection for long-lived connections.
MOZ_MUST_USE nsresult StartShortLivedTCPKeepalives();
MOZ_MUST_USE nsresult StartLongLivedTCPKeepalives();
MOZ_MUST_USE nsresult DisableTCPKeepalives();
private:
nsCOMPtr<nsIAsyncInputStream> mSocketIn;
nsCOMPtr<nsIAsyncOutputStream> mSocketOut;
nsresult mSocketInCondition;
nsresult mSocketOutCondition;
nsCOMPtr<nsIInputStream> mProxyConnectStream;
nsCOMPtr<nsIInputStream> mRequestStream;
RefPtr<TLSFilterTransaction> mTLSFilter;
nsWeakPtr mWeakTrans; // SpdyConnectTransaction *
RefPtr<nsHttpHandler> mHttpHandler; // keep gHttpHandler alive
PRIntervalTime mLastReadTime;
PRIntervalTime mLastWriteTime;
PRIntervalTime
mMaxHangTime; // max download time before dropping keep-alive status
PRIntervalTime mIdleTimeout; // value of keep-alive: timeout=
PRIntervalTime mConsiderReusedAfterInterval;
PRIntervalTime mConsiderReusedAfterEpoch;
int64_t mCurrentBytesRead; // data read per activation
int64_t mMaxBytesRead; // max read in 1 activation
int64_t mTotalBytesRead; // total data read
int64_t mContentBytesWritten; // does not include CONNECT tunnel or TLS
RefPtr<nsIAsyncInputStream> mInputOverflow;
// Whether the first non-null transaction dispatched on this connection was
// urgent-start or not
bool mUrgentStartPreferred;
// A flag to prevent reset of mUrgentStartPreferred by subsequent transactions
bool mUrgentStartPreferredKnown;
bool mConnectedTransport;
bool mKeepAlive;
bool mKeepAliveMask;
bool mDontReuse;
bool mIsReused;
bool mCompletedProxyConnect;
bool mLastTransactionExpectedNoContent;
bool mIdleMonitoring;
bool mProxyConnectInProgress;
bool mInSpdyTunnel;
bool mForcePlainText;
// A snapshot of current number of transfered bytes
int64_t mTrafficCount;
bool mTrafficStamp; // true then the above is set
// The number of <= HTTP/1.1 transactions performed on this connection. This
// excludes spdy transactions.
uint32_t mHttp1xTransactionCount;
// Keep-Alive: max="mRemainingConnectionUses" provides the number of future
// transactions (including the current one) that the server expects to allow
// on this persistent connection.
uint32_t mRemainingConnectionUses;
// SPDY related
bool mNPNComplete;
bool mSetupSSLCalled;
// version level in use, 0 if unused
SpdyVersion mUsingSpdyVersion;
RefPtr<ASpdySession> mSpdySession;
int32_t mPriority;
bool mReportedSpdy;
// mUsingSpdyVersion is cleared when mSpdySession is freed, this is permanent
bool mEverUsedSpdy;
// mLastHttpResponseVersion stores the last response's http version seen.
HttpVersion mLastHttpResponseVersion;
// If a large keepalive has been requested for any trans,
// scale the default by this factor
uint32_t mDefaultTimeoutFactor;
bool mResponseTimeoutEnabled;
// Flag to indicate connection is in inital keepalive period (fast detect).
uint32_t mTCPKeepaliveConfig;
nsCOMPtr<nsITimer> mTCPKeepaliveTransitionTimer;
private:
// For ForceSend()
static void ForceSendIO(nsITimer* aTimer, void* aClosure);
MOZ_MUST_USE nsresult MaybeForceSendIO();
bool mForceSendPending;
nsCOMPtr<nsITimer> mForceSendTimer;
// Helper variable for 0RTT handshake;
bool m0RTTChecked; // Possible 0RTT has been
// checked.
bool mWaitingFor0RTTResponse; // We have are
// sending 0RTT
// data and we
// are waiting
// for the end of
// the handsake.
int64_t mContentBytesWritten0RTT;
bool mEarlyDataNegotiated; // Only used for telemetry
nsCString mEarlyNegotiatedALPN;
bool mDid0RTTSpdy;
bool mFastOpen;
uint8_t mFastOpenStatus;
bool mForceSendDuringFastOpenPending;
bool mReceivedSocketWouldBlockDuringFastOpen;
bool mCheckNetworkStallsWithTFO;
PRIntervalTime mLastRequestBytesSentTime;
private:
bool mThroughCaptivePortal;
// Http3
RefPtr<Http3Session> mHttp3Session;
};
NS_DEFINE_STATIC_IID_ACCESSOR(HttpConnectionUDP, HTTPCONNECTIONUDP_IID)
} // namespace net
} // namespace mozilla
#endif // HttpConnectionUDP_h__

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

@ -7,7 +7,12 @@
#include "InterceptedHttpChannel.h"
#include "nsContentSecurityManager.h"
#include "nsEscape.h"
#include "mozilla/dom/ChannelInfo.h"
#include "mozilla/dom/PerformanceStorage.h"
#include "nsHttpChannel.h"
#include "nsIRedirectResultListener.h"
#include "nsStringStream.h"
#include "nsStreamUtils.h"
namespace mozilla {
namespace net {

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

@ -8,11 +8,13 @@
#define mozilla_net_InterceptedHttpChannel_h
#include "HttpBaseChannel.h"
#include "nsIAsyncVerifyRedirectCallback.h"
#include "nsINetworkInterceptController.h"
#include "nsIInputStream.h"
#include "nsICacheInfoChannel.h"
#include "nsIChannelWithDivertableParentListener.h"
#include "nsIThreadRetargetableRequest.h"
#include "nsIThreadRetargetableStreamListener.h"
namespace mozilla {
namespace net {

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

@ -93,6 +93,7 @@ UNIFIED_SOURCES += [
'HttpConnectionBase.cpp',
'HttpConnectionMgrChild.cpp',
'HttpConnectionMgrParent.cpp',
'HttpConnectionUDP.cpp',
'HttpInfo.cpp',
'HttpTrafficAnalyzer.cpp',
'HttpTransactionChild.cpp',

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

@ -6,7 +6,6 @@
#define nsAHttpConnection_h__
#include "nsHttp.h"
#include "HttpConnectionBase.h"
#include "nsISupports.h"
#include "nsAHttpTransaction.h"
#include "HttpTrafficAnalyzer.h"
@ -19,7 +18,7 @@ namespace mozilla {
namespace net {
class nsHttpConnectionInfo;
class nsHttpConnection;
class HttpConnectionBase;
class nsHttpRequestHead;
class nsHttpResponseHead;

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

@ -98,6 +98,7 @@
#include "nsIX509Cert.h"
#include "ScopedNSSTypes.h"
#include "nsIDeprecationWarner.h"
#include "nsIDNSRecord.h"
#include "mozilla/dom/Document.h"
#include "nsICompressConvStats.h"
#include "nsCORSListenerProxy.h"

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

@ -203,20 +203,6 @@ nsresult nsHttpConnection::Init(
mSocketIn = instream;
mSocketOut = outstream;
if (mConnInfo->IsHttp3()) {
mHttp3Session = new Http3Session();
nsresult rv =
mHttp3Session->Init(mConnInfo->GetOrigin(), mSocketTransport, this);
if (NS_FAILED(rv)) {
LOG(
("nsHttpConnection::Init mHttp3Session->Init failed "
"[this=%p rv=%x]\n",
this, static_cast<uint32_t>(rv)));
return rv;
}
mTransaction = mHttp3Session;
}
// See explanation for non-strictness of this operation in
// SetSecurityCallbacks.
mCallbacks = new nsMainThreadPtrHolder<nsIInterfaceRequestor>(

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

@ -25,6 +25,7 @@
#include "nsCOMPtr.h"
#include "nsHttpConnectionMgr.h"
#include "nsHttpHandler.h"
#include "nsIClassOfService.h"
#include "nsIDNSRecord.h"
#include "nsIHttpChannelInternal.h"
#include "nsIRequestContext.h"
@ -35,6 +36,9 @@
#include "nsInterfaceRequestorAgg.h"
#include "nsNetCID.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "HttpConnectionUDP.h"
#include "TCPFastOpenLayer.h"
namespace mozilla {
namespace net {
@ -4845,7 +4849,13 @@ nsresult nsHttpConnectionMgr::nsHalfOpenSocket::SetupConn(
// We cannot ask for a connection for TFO and Http3 ata the same time.
MOZ_ASSERT(!(mIsHttp3 && aFastOpen));
// assign the new socket to the http connection
RefPtr<HttpConnectionBase> conn = new nsHttpConnection();
RefPtr<HttpConnectionBase> conn;
if (!mIsHttp3) {
conn = new nsHttpConnection();
} else {
conn = new HttpConnectionUDP();
}
LOG(
("nsHalfOpenSocket::SetupConn "
"Created new nshttpconnection %p %s\n",
@ -5056,10 +5066,7 @@ nsresult nsHttpConnectionMgr::nsHalfOpenSocket::SetupConn(
// If this connection has a transaction get reference to its
// ConnectionHandler.
RefPtr<nsHttpConnection> connTCP = do_QueryObject(conn);
MOZ_ASSERT(connTCP);
if (!connTCP) {
rv = NS_ERROR_UNEXPECTED;
} else {
if (connTCP) {
if (aFastOpen) {
MOZ_ASSERT(mEnt);
MOZ_ASSERT(static_cast<int32_t>(mEnt->mIdleConns.IndexOf(conn)) == -1);

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

@ -6,8 +6,8 @@
#ifndef nsHttpConnectionMgr_h__
#define nsHttpConnectionMgr_h__
#include "HttpConnectionMgrShell.h"
#include "HttpConnectionBase.h"
#include "HttpConnectionMgrShell.h"
#include "nsHttpConnection.h"
#include "nsHttpTransaction.h"
#include "nsTArray.h"