summaryrefslogtreecommitdiffstats
path: root/netwerk/protocol/http/NullHttpTransaction.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--netwerk/protocol/http/NullHttpTransaction.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/netwerk/protocol/http/NullHttpTransaction.cpp b/netwerk/protocol/http/NullHttpTransaction.cpp
new file mode 100644
index 0000000000..8871fd9912
--- /dev/null
+++ b/netwerk/protocol/http/NullHttpTransaction.cpp
@@ -0,0 +1,220 @@
+/* -*- 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 "mozilla/net/NeckoChannelParams.h" // For HttpActivityArgs.
+#include "nsHttp.h"
+#include "NullHttpTransaction.h"
+#include "nsHttpHandler.h"
+#include "nsHttpRequestHead.h"
+#include "nsIHttpActivityObserver.h"
+#include "nsQueryObject.h"
+#include "nsNetUtil.h"
+#include "TCPFastOpenLayer.h"
+
+namespace mozilla {
+namespace net {
+
+NS_IMPL_ISUPPORTS(NullHttpTransaction, NullHttpTransaction,
+ nsISupportsWeakReference)
+
+NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo* ci,
+ nsIInterfaceRequestor* callbacks,
+ uint32_t caps)
+ : mStatus(NS_OK),
+ mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE),
+ mRequestHead(nullptr),
+ mIsDone(false),
+ mClaimed(false),
+ mFastOpenStatus(TFO_NOT_TRIED),
+ mCallbacks(callbacks),
+ mConnectionInfo(ci) {
+ nsresult rv;
+ mActivityDistributor =
+ do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) {
+ return;
+ }
+
+ bool activityDistributorActive;
+ rv = mActivityDistributor->GetIsActive(&activityDistributorActive);
+ if (NS_SUCCEEDED(rv) && activityDistributorActive) {
+ // There are some observers registered at activity distributor.
+ LOG(
+ ("NulHttpTransaction::NullHttpTransaction() "
+ "mActivityDistributor is active "
+ "[this=%p, %s]",
+ this, ci->GetOrigin().get()));
+ } else {
+ // There is no observer, so don't use it.
+ mActivityDistributor = nullptr;
+ }
+}
+
+NullHttpTransaction::~NullHttpTransaction() {
+ mCallbacks = nullptr;
+ delete mRequestHead;
+}
+
+bool NullHttpTransaction::Claim() {
+ if (mClaimed) {
+ return false;
+ }
+ mClaimed = true;
+ return true;
+}
+
+void NullHttpTransaction::Unclaim() { mClaimed = false; }
+
+void NullHttpTransaction::SetConnection(nsAHttpConnection* conn) {
+ mConnection = conn;
+}
+
+nsAHttpConnection* NullHttpTransaction::Connection() {
+ return mConnection.get();
+}
+
+void NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor** outCB) {
+ nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
+ *outCB = copyCB.forget().take();
+}
+
+void NullHttpTransaction::OnTransportStatus(nsITransport* transport,
+ nsresult status, int64_t progress) {
+ if (status == NS_NET_STATUS_RESOLVING_HOST) {
+ if (mTimings.domainLookupStart.IsNull()) {
+ mTimings.domainLookupStart = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_RESOLVED_HOST) {
+ if (mTimings.domainLookupEnd.IsNull()) {
+ mTimings.domainLookupEnd = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_CONNECTING_TO) {
+ if (mTimings.connectStart.IsNull()) {
+ mTimings.connectStart = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_CONNECTED_TO) {
+ TimeStamp tnow = TimeStamp::Now();
+ if (mTimings.connectEnd.IsNull()) {
+ mTimings.connectEnd = tnow;
+ }
+ if (mTimings.tcpConnectEnd.IsNull()) {
+ mTimings.tcpConnectEnd = tnow;
+ }
+ // After a socket is connected we know for sure whether data has been
+ // sent on SYN packet and if not we should update TLS start timing.
+ if ((mFastOpenStatus != TFO_DATA_SENT) &&
+ !mTimings.secureConnectionStart.IsNull()) {
+ mTimings.secureConnectionStart = tnow;
+ }
+ } else if (status == NS_NET_STATUS_TLS_HANDSHAKE_STARTING) {
+ if (mTimings.secureConnectionStart.IsNull()) {
+ mTimings.secureConnectionStart = TimeStamp::Now();
+ }
+ } else if (status == NS_NET_STATUS_TLS_HANDSHAKE_ENDED) {
+ mTimings.connectEnd = TimeStamp::Now();
+ ;
+ }
+
+ if (mActivityDistributor) {
+ Unused << mActivityDistributor->ObserveActivityWithArgs(
+ HttpActivity(mConnectionInfo->GetOrigin(),
+ mConnectionInfo->OriginPort(),
+ mConnectionInfo->EndToEndSSL()),
+ NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT, static_cast<uint32_t>(status),
+ PR_Now(), progress, ""_ns);
+ }
+}
+
+bool NullHttpTransaction::IsDone() { return mIsDone; }
+
+nsresult NullHttpTransaction::Status() { return mStatus; }
+
+uint32_t NullHttpTransaction::Caps() { return mCaps; }
+
+nsresult NullHttpTransaction::ReadSegments(nsAHttpSegmentReader* reader,
+ uint32_t count,
+ uint32_t* countRead) {
+ *countRead = 0;
+ mIsDone = true;
+ return NS_BASE_STREAM_CLOSED;
+}
+
+nsresult NullHttpTransaction::WriteSegments(nsAHttpSegmentWriter* writer,
+ uint32_t count,
+ uint32_t* countWritten) {
+ *countWritten = 0;
+ return NS_BASE_STREAM_CLOSED;
+}
+
+uint32_t NullHttpTransaction::Http1xTransactionCount() { return 0; }
+
+nsHttpRequestHead* NullHttpTransaction::RequestHead() {
+ // We suport a requesthead at all so that a CONNECT tunnel transaction
+ // can obtain a Host header from it, but we lazy-popualate that header.
+
+ if (!mRequestHead) {
+ mRequestHead = new nsHttpRequestHead();
+
+ nsAutoCString hostHeader;
+ nsCString host(mConnectionInfo->GetOrigin());
+ nsresult rv = nsHttpHandler::GenerateHostPort(
+ host, mConnectionInfo->OriginPort(), hostHeader);
+ if (NS_SUCCEEDED(rv)) {
+ rv = mRequestHead->SetHeader(nsHttp::Host, hostHeader);
+ MOZ_ASSERT(NS_SUCCEEDED(rv));
+ if (mActivityDistributor) {
+ // Report request headers.
+ nsCString reqHeaderBuf;
+ mRequestHead->Flatten(reqHeaderBuf, false);
+ Unused << mActivityDistributor->ObserveActivityWithArgs(
+ HttpActivity(mConnectionInfo->GetOrigin(),
+ mConnectionInfo->OriginPort(),
+ mConnectionInfo->EndToEndSSL()),
+ NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+ NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, PR_Now(), 0, reqHeaderBuf);
+ }
+ }
+
+ // CONNECT tunnels may also want Proxy-Authorization but that is a lot
+ // harder to determine, so for now we will let those connections fail in
+ // the NullHttpTransaction and let them be retried from the pending queue
+ // with a bound transaction
+ }
+
+ return mRequestHead;
+}
+
+nsresult NullHttpTransaction::TakeSubTransactions(
+ nsTArray<RefPtr<nsAHttpTransaction> >& outTransactions) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+void NullHttpTransaction::SetProxyConnectFailed() {}
+
+void NullHttpTransaction::Close(nsresult reason) {
+ mStatus = reason;
+ mConnection = nullptr;
+ mIsDone = true;
+ if (mActivityDistributor) {
+ // Report that this transaction is closing.
+ Unused << mActivityDistributor->ObserveActivityWithArgs(
+ HttpActivity(mConnectionInfo->GetOrigin(),
+ mConnectionInfo->OriginPort(),
+ mConnectionInfo->EndToEndSSL()),
+ NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
+ NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, PR_Now(), 0, ""_ns);
+ }
+}
+
+nsHttpConnectionInfo* NullHttpTransaction::ConnectionInfo() {
+ return mConnectionInfo;
+}
+
+} // namespace net
+} // namespace mozilla