Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Apache/docs/manual/mod/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 19.0.2025 mit Größe 9 kB image not shown  

Quelle  TLSTransportLayer.cpp   Sprache: unbekannt

 
Spracherkennung für: .cpp vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

/* -*- 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/. */

// HttpLog.h should generally be included first
#include "HttpLog.h"

#include "Http2StreamTunnel.h"
#include "TLSTransportLayer.h"
#include "nsISocketProvider.h"
#include "nsITLSSocketControl.h"
#include "nsQueryObject.h"
#include "nsSocketProviderService.h"
#include "nsSocketTransport2.h"

namespace mozilla::net {

//-----------------------------------------------------------------------------
// TLSTransportLayerInputStream impl
//-----------------------------------------------------------------------------

NS_IMPL_QUERY_INTERFACE(TLSTransportLayer::InputStreamWrapper, nsIInputStream,
                        nsIAsyncInputStream)

NS_IMETHODIMP_(MozExternalRefCountType)
TLSTransportLayer::InputStreamWrapper::AddRef() { return mTransport->AddRef(); }

NS_IMETHODIMP_(MozExternalRefCountType)
TLSTransportLayer::InputStreamWrapper::Release() {
  return mTransport->Release();
}

TLSTransportLayer::InputStreamWrapper::InputStreamWrapper(
    nsIAsyncInputStream* aInputStream, TLSTransportLayer* aTransport)
    : mSocketIn(aInputStream), mTransport(aTransport) {}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::Close() {
  LOG(("TLSTransportLayer::InputStreamWrapper::Close [this=%p]\n", this));
  return mSocketIn->Close();
}

NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::Available(
    uint64_t* avail) {
  LOG(("TLSTransportLayer::InputStreamWrapper::Available [this=%p]\n", this));
  return mSocketIn->Available(avail);
}

NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::StreamStatus() {
  LOG(("TLSTransportLayer::InputStreamWrapper::StreamStatus [this=%p]\n",
       this));
  return mSocketIn->StreamStatus();
}

nsresult TLSTransportLayer::InputStreamWrapper::ReadDirectly(
    char* buf, uint32_t count, uint32_t* countRead) {
  LOG(("TLSTransportLayer::InputStreamWrapper::ReadDirectly [this=%p]\n",
       this));
  return mSocketIn->Read(buf, count, countRead);
}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::Read(char* buf, uint32_t count,
                                            uint32_t* countRead) {
  LOG(("TLSTransportLayer::InputStreamWrapper::Read [this=%p]\n", this));

  *countRead = 0;

  if (NS_FAILED(mStatus)) {
    return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
  }

  int32_t bytesRead = PR_Read(mTransport->mFD, buf, count);
  if (bytesRead > 0) {
    *countRead = bytesRead;
  } else if (bytesRead < 0) {
    PRErrorCode code = PR_GetError();
    if (code == PR_WOULD_BLOCK_ERROR) {
      LOG((
          "TLSTransportLayer::InputStreamWrapper::Read %p PR_Read would block ",
          this));
      return NS_BASE_STREAM_WOULD_BLOCK;
    }
    // If reading from the socket succeeded (NS_SUCCEEDED(mStatus)),
    // but the nss layer encountered an error remember the error.
    if (NS_SUCCEEDED(mStatus)) {
      mStatus = ErrorAccordingToNSPR(code);
      LOG(("TLSTransportLayer::InputStreamWrapper::Read %p nss error %" PRIx32
           ".\n",
           this, static_cast<uint32_t>(mStatus)));
    }
  }

  if (NS_SUCCEEDED(mStatus) && !bytesRead) {
    LOG(
        ("TLSTransportLayer::InputStreamWrapper::Read %p "
         "Second layer of TLS stripping results in STREAM_CLOSED\n",
         this));
    mStatus = NS_BASE_STREAM_CLOSED;
  }

  LOG(("TLSTransportLayer::InputStreamWrapper::Read %p rv=%" PRIx32
       " didread=%d "
       "2 layers of ssl stripped to plaintext\n",
       this, static_cast<uint32_t>(mStatus), bytesRead));
  return mStatus;
}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::ReadSegments(nsWriteSegmentFun writer,
                                                    void* closure,
                                                    uint32_t count,
                                                    uint32_t* countRead) {
  LOG(("TLSTransportLayer::InputStreamWrapper::ReadSegments [this=%p]\n",
       this));
  return mSocketIn->ReadSegments(writer, closure, count, countRead);
}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::IsNonBlocking(bool* nonblocking) {
  return mSocketIn->IsNonBlocking(nonblocking);
}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::CloseWithStatus(nsresult reason) {
  LOG(
      ("TLSTransportLayer::InputStreamWrapper::CloseWithStatus [this=%p "
       "reason=%" PRIx32 "]\n",
       this, static_cast<uint32_t>(reason)));
  return mSocketIn->CloseWithStatus(reason);
}

NS_IMETHODIMP
TLSTransportLayer::InputStreamWrapper::AsyncWait(
    nsIInputStreamCallback* callback, uint32_t flags, uint32_t amount,
    nsIEventTarget* target) {
  LOG(
      ("TLSTransportLayer::InputStreamWrapper::AsyncWait [this=%p, "
       "callback=%p]\n",
       this, callback));
  mTransport->mInputCallback = callback;
  // Don't bother to call PR_POLL when |callback| is NULL. We call |AsyncWait|
  // directly to null out the underlying callback.
  if (!callback) {
    return mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
  }

  PRPollDesc pd;
  pd.fd = mTransport->mFD;
  pd.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
  // Only run PR_Poll on the socket thread. Also, make sure this lives at least
  // as long as that operation.
  auto DoPoll = [self = RefPtr{this}, pd(pd)]() mutable {
    int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
    LOG(("TLSTransportLayer::InputStreamWrapper::AsyncWait rv=%d", rv));
  };
  if (OnSocketThread()) {
    DoPoll();
  } else {
    gSocketTransportService->Dispatch(NS_NewRunnableFunction(
        "TLSTransportLayer::InputStreamWrapper::AsyncWait", DoPoll));
  }
  return NS_OK;
}

//-----------------------------------------------------------------------------
// TLSTransportLayerOutputStream impl
//-----------------------------------------------------------------------------

NS_IMPL_QUERY_INTERFACE(TLSTransportLayer::OutputStreamWrapper, nsIOutputStream,
                        nsIAsyncOutputStream)

NS_IMETHODIMP_(MozExternalRefCountType)
TLSTransportLayer::OutputStreamWrapper::AddRef() {
  return mTransport->AddRef();
}

NS_IMETHODIMP_(MozExternalRefCountType)
TLSTransportLayer::OutputStreamWrapper::Release() {
  return mTransport->Release();
}

TLSTransportLayer::OutputStreamWrapper::OutputStreamWrapper(
    nsIAsyncOutputStream* aOutputStream, TLSTransportLayer* aTransport)
    : mSocketOut(aOutputStream), mTransport(aTransport) {}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::Close() {
  LOG(("TLSTransportLayer::OutputStreamWrapper::Close [this=%p]\n", this));
  return mSocketOut->Close();
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::Flush() {
  LOG(("TLSTransportLayerOutputStream::Flush [this=%p]\n", this));
  return mSocketOut->Flush();
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::StreamStatus() {
  LOG(("TLSTransportLayerOutputStream::StreamStatus [this=%p]\n", this));
  return mSocketOut->StreamStatus();
}

nsresult TLSTransportLayer::OutputStreamWrapper::WriteDirectly(
    const char* buf, uint32_t count, uint32_t* countWritten) {
  LOG(
      ("TLSTransportLayer::OutputStreamWrapper::WriteDirectly [this=%p "
       "count=%u]\n",
       this, count));
  return mSocketOut->Write(buf, count, countWritten);
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::Write(const char* buf, uint32_t count,
                                              uint32_t* countWritten) {
  LOG(("TLSTransportLayer::OutputStreamWrapper::Write [this=%p count=%u]\n",
       this, count));

  *countWritten = 0;

  if (NS_FAILED(mStatus)) {
    return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
  }

  int32_t written = PR_Write(mTransport->mFD, buf, count);
  LOG(
      ("TLSTransportLayer::OutputStreamWrapper::Write %p PRWrite(%d) = %d "
       "%d\n",
       this, count, written, PR_GetError() == PR_WOULD_BLOCK_ERROR));

  if (written > 0) {
    *countWritten = written;
  } else if (written < 0) {
    PRErrorCode code = PR_GetError();
    if (code == PR_WOULD_BLOCK_ERROR) {
      LOG(
          ("TLSTransportLayer::OutputStreamWrapper::Write %p PRWrite would "
           "block ",
           this));
      return NS_BASE_STREAM_WOULD_BLOCK;
    }

    // Writing to the socket succeeded, but failed in nss layer.
    if (NS_SUCCEEDED(mStatus)) {
      mStatus = ErrorAccordingToNSPR(code);
    }
  }

  return mStatus;
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::WriteSegments(nsReadSegmentFun reader,
                                                      void* closure,
                                                      uint32_t count,
                                                      uint32_t* countRead) {
  return mSocketOut->WriteSegments(reader, closure, count, countRead);
}

// static
nsresult TLSTransportLayer::OutputStreamWrapper::WriteFromSegments(
    nsIInputStream* input, void* closure, const char* fromSegment,
    uint32_t offset, uint32_t count, uint32_t* countRead) {
  OutputStreamWrapper* self = (OutputStreamWrapper*)closure;
  return self->Write(fromSegment, count, countRead);
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::WriteFrom(nsIInputStream* stream,
                                                  uint32_t count,
                                                  uint32_t* countRead) {
  return stream->ReadSegments(WriteFromSegments, this, count, countRead);
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::IsNonBlocking(bool* nonblocking) {
  return mSocketOut->IsNonBlocking(nonblocking);
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::CloseWithStatus(nsresult reason) {
  LOG(("OutputStreamWrapper::CloseWithStatus [this=%p reason=%" PRIx32 "]\n",
       this, static_cast<uint32_t>(reason)));
  return mSocketOut->CloseWithStatus(reason);
}

NS_IMETHODIMP
TLSTransportLayer::OutputStreamWrapper::AsyncWait(
    nsIOutputStreamCallback* callback, uint32_t flags, uint32_t amount,
    nsIEventTarget* target) {
  LOG(
      ("TLSTransportLayer::OutputStreamWrapper::AsyncWait [this=%p, "
       "mOutputCallback=%p "
       "callback=%p]\n",
       this, mTransport->mOutputCallback.get(), callback));
  mTransport->mOutputCallback = callback;
  // Don't bother to call PR_POLL when |callback| is NULL. We call |AsyncWait|
  // directly to null out the underlying callback.
  if (!callback) {
    return mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
  }

  PRPollDesc pd;
  pd.fd = mTransport->mFD;
  pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
  int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
  LOG(("TLSTransportLayer::OutputStreamWrapper::AsyncWait rv=%d", rv));
  return NS_OK;
}

//-----------------------------------------------------------------------------
// TLSTransportLayer impl
//-----------------------------------------------------------------------------

static PRDescIdentity sTLSTransportLayerIdentity;
static PRIOMethods sTLSTransportLayerMethods;
static PRIOMethods* sTLSTransportLayerMethodsPtr = nullptr;

bool TLSTransportLayer::DispatchRelease() {
  if (OnSocketThread()) {
    return false;
  }

  gSocketTransportService->Dispatch(
      NewNonOwningRunnableMethod("net::TLSTransportLayer::Release", this,
                                 &TLSTransportLayer::Release),
      NS_DISPATCH_NORMAL);

  return true;
}

NS_IMPL_ADDREF(TLSTransportLayer)
NS_IMETHODIMP_(MozExternalRefCountType)
TLSTransportLayer::Release() {
  nsrefcnt count = mRefCnt - 1;
  if (DispatchRelease()) {
    // Redispatched to the socket thread.
    return count;
  }

  MOZ_ASSERT(0 != mRefCnt, "dup release");
  count = --mRefCnt;
  NS_LOG_RELEASE(this, count, "TLSTransportLayer");

  if (0 == count) {
    mRefCnt = 1;
    delete (this);
    return 0;
  }

  return count;
}

NS_INTERFACE_MAP_BEGIN(TLSTransportLayer)
  NS_INTERFACE_MAP_ENTRY(nsISocketTransport)
  NS_INTERFACE_MAP_ENTRY(nsITransport)
  NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
  NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback)
  NS_INTERFACE_MAP_ENTRY_CONCRETE(TLSTransportLayer)
  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransport)
NS_INTERFACE_MAP_END

TLSTransportLayer::TLSTransportLayer(nsISocketTransport* aTransport,
                                     nsIAsyncInputStream* aInputStream,
                                     nsIAsyncOutputStream* aOutputStream,
                                     nsIInputStreamCallback* aOwner)
    : mSocketTransport(aTransport),
      mSocketInWrapper(aInputStream, this),
      mSocketOutWrapper(aOutputStream, this),
      mOwner(aOwner) {
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
  LOG(("TLSTransportLayer ctor this=[%p]", this));
}

TLSTransportLayer::~TLSTransportLayer() {
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
  LOG(("TLSTransportLayer dtor this=[%p]", this));
  if (mFD) {
    PR_Close(mFD);
    mFD = nullptr;
  }
  mTLSSocketControl = nullptr;
}

bool TLSTransportLayer::Init(const char* aTLSHost, int32_t aTLSPort) {
  LOG(("TLSTransportLayer::Init this=[%p]", this));
  nsCOMPtr<nsISocketProvider> provider;
  nsCOMPtr<nsISocketProviderService> spserv =
      nsSocketProviderService::GetOrCreate();
  if (!spserv) {
    return false;
  }

  spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
  if (!provider) {
    return false;
  }

  // Install an NSPR layer to handle getpeername() with a failure. This is kind
  // of silly, but the default one used by the pipe asserts when called and the
  // nss code calls it to see if we are connected to a real socket or not.
  if (!sTLSTransportLayerMethodsPtr) {
    // one time initialization
    sTLSTransportLayerIdentity = PR_GetUniqueIdentity("TLSTransportLayer");
    sTLSTransportLayerMethods = *PR_GetDefaultIOMethods();
    sTLSTransportLayerMethods.getpeername = GetPeerName;
    sTLSTransportLayerMethods.getsocketoption = GetSocketOption;
    sTLSTransportLayerMethods.setsocketoption = SetSocketOption;
    sTLSTransportLayerMethods.read = Read;
    sTLSTransportLayerMethods.write = Write;
    sTLSTransportLayerMethods.send = Send;
    sTLSTransportLayerMethods.recv = Recv;
    sTLSTransportLayerMethods.close = Close;
    sTLSTransportLayerMethods.poll = Poll;
    sTLSTransportLayerMethodsPtr = &sTLSTransportLayerMethods;
  }

  mFD = PR_CreateIOLayerStub(sTLSTransportLayerIdentity,
                             &sTLSTransportLayerMethods);
  if (!mFD) {
    return false;
  }

  mFD->secret = reinterpret_cast<PRFilePrivate*>(this);

  return NS_SUCCEEDED(provider->AddToSocket(
      PR_AF_INET, aTLSHost, aTLSPort, nullptr, OriginAttributes(), 0, 0, mFD,
      getter_AddRefs(mTLSSocketControl)));
}

NS_IMETHODIMP
TLSTransportLayer::OnInputStreamReady(nsIAsyncInputStream* in) {
  nsCOMPtr<nsIInputStreamCallback> callback = std::move(mInputCallback);
  if (callback) {
    return callback->OnInputStreamReady(&mSocketInWrapper);
  }
  return NS_OK;
}

NS_IMETHODIMP
TLSTransportLayer::OnOutputStreamReady(nsIAsyncOutputStream* out) {
  nsCOMPtr<nsIOutputStreamCallback> callback = std::move(mOutputCallback);
  nsresult rv = NS_OK;
  if (callback) {
    rv = callback->OnOutputStreamReady(&mSocketOutWrapper);

    RefPtr<OutputStreamTunnel> tunnel = do_QueryObject(out);
    if (tunnel) {
      tunnel->MaybeSetRequestDone(callback);
    }
  }
  return rv;
}

NS_IMETHODIMP
TLSTransportLayer::SetKeepaliveEnabled(bool aKeepaliveEnabled) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetKeepaliveEnabled(aKeepaliveEnabled);
}

NS_IMETHODIMP
TLSTransportLayer::SetKeepaliveVals(int32_t keepaliveIdleTime,
                                    int32_t keepaliveRetryInterval) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetKeepaliveVals(keepaliveIdleTime,
                                            keepaliveRetryInterval);
}

NS_IMETHODIMP
TLSTransportLayer::GetSecurityCallbacks(
    nsIInterfaceRequestor** aSecurityCallbacks) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetSecurityCallbacks(aSecurityCallbacks);
}

NS_IMETHODIMP
TLSTransportLayer::SetSecurityCallbacks(
    nsIInterfaceRequestor* aSecurityCallbacks) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }

  return mSocketTransport->SetSecurityCallbacks(aSecurityCallbacks);
}

NS_IMETHODIMP
TLSTransportLayer::OpenInputStream(uint32_t aFlags, uint32_t aSegmentSize,
                                   uint32_t aSegmentCount,
                                   nsIInputStream** _retval) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
TLSTransportLayer::OpenOutputStream(uint32_t aFlags, uint32_t aSegmentSize,
                                    uint32_t aSegmentCount,
                                    nsIOutputStream** _retval) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
TLSTransportLayer::Close(nsresult aReason) {
  LOG(("TLSTransportLayer::Close [this=%p reason=%" PRIx32 "]\n", this,
       static_cast<uint32_t>(aReason)));

  mInputCallback = nullptr;
  mOutputCallback = nullptr;
  if (mSocketTransport) {
    mSocketTransport->Close(aReason);
    mSocketTransport = nullptr;
  }
  mSocketInWrapper.AsyncWait(nullptr, 0, 0, nullptr);
  mSocketOutWrapper.AsyncWait(nullptr, 0, 0, nullptr);

  if (mOwner) {
    RefPtr<TLSTransportLayer> self = this;
    Unused << NS_DispatchToCurrentThread(NS_NewRunnableFunction(
        "TLSTransportLayer::Close", [self{std::move(self)}]() {
          nsCOMPtr<nsIInputStreamCallback> inputCallback =
              std::move(self->mOwner);
          if (inputCallback) {
            // This is hack. We need to make
            // nsHttpConnection::OnInputStreamReady be called, so
            // nsHttpConnection::CloseTransaction can be called to release the
            // transaction.
            Unused << inputCallback->OnInputStreamReady(
                &self->mSocketInWrapper);
          }
        }));
  }

  return NS_OK;
}

NS_IMETHODIMP
TLSTransportLayer::SetEventSink(nsITransportEventSink* aSink,
                                nsIEventTarget* aEventTarget) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetEventSink(aSink, aEventTarget);
}

NS_IMETHODIMP
TLSTransportLayer::Bind(NetAddr* aLocalAddr) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->Bind(aLocalAddr);
}

NS_IMETHODIMP
TLSTransportLayer::GetEchConfigUsed(bool* aEchConfigUsed) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetEchConfigUsed(aEchConfigUsed);
}

NS_IMETHODIMP
TLSTransportLayer::SetEchConfig(const nsACString& aEchConfig) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetEchConfig(aEchConfig);
}

NS_IMETHODIMP
TLSTransportLayer::ResolvedByTRR(bool* aResolvedByTRR) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->ResolvedByTRR(aResolvedByTRR);
}

NS_IMETHODIMP TLSTransportLayer::GetEffectiveTRRMode(
    nsIRequest::TRRMode* aEffectiveTRRMode) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetEffectiveTRRMode(aEffectiveTRRMode);
}

NS_IMETHODIMP TLSTransportLayer::GetTrrSkipReason(
    nsITRRSkipReason::value* aTrrSkipReason) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetTrrSkipReason(aTrrSkipReason);
}

#define FWD_TS_PTR(fx, ts)                          \
  NS_IMETHODIMP                                     \
  TLSTransportLayer::fx(ts* arg) {                  \
    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    return mSocketTransport->fx(arg);               \
  }

#define FWD_TS_ADDREF(fx, ts)                       \
  NS_IMETHODIMP                                     \
  TLSTransportLayer::fx(ts** arg) {                 \
    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    return mSocketTransport->fx(arg);               \
  }

#define FWD_TS(fx, ts)                              \
  NS_IMETHODIMP                                     \
  TLSTransportLayer::fx(ts arg) {                   \
    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    return mSocketTransport->fx(arg);               \
  }

FWD_TS_PTR(GetKeepaliveEnabled, bool);
FWD_TS_PTR(GetSendBufferSize, uint32_t);
FWD_TS(SetSendBufferSize, uint32_t);
FWD_TS_PTR(GetPort, int32_t);
FWD_TS_PTR(GetPeerAddr, mozilla::net::NetAddr);
FWD_TS_PTR(GetSelfAddr, mozilla::net::NetAddr);
FWD_TS_ADDREF(GetScriptablePeerAddr, nsINetAddr);
FWD_TS_ADDREF(GetScriptableSelfAddr, nsINetAddr);
FWD_TS_PTR(IsAlive, bool);
FWD_TS_PTR(GetConnectionFlags, uint32_t);
FWD_TS(SetConnectionFlags, uint32_t);
FWD_TS(SetIsPrivate, bool);
FWD_TS_PTR(GetTlsFlags, uint32_t);
FWD_TS(SetTlsFlags, uint32_t);
FWD_TS_PTR(GetRecvBufferSize, uint32_t);
FWD_TS(SetRecvBufferSize, uint32_t);
FWD_TS_PTR(GetResetIPFamilyPreference, bool);

nsresult TLSTransportLayer::GetTlsSocketControl(
    nsITLSSocketControl** tlsSocketControl) {
  if (!mTLSSocketControl) {
    return NS_ERROR_ABORT;
  }

  *tlsSocketControl = do_AddRef(mTLSSocketControl).take();
  return NS_OK;
}

nsresult TLSTransportLayer::GetOriginAttributes(
    mozilla::OriginAttributes* aOriginAttributes) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetOriginAttributes(aOriginAttributes);
}

nsresult TLSTransportLayer::SetOriginAttributes(
    const mozilla::OriginAttributes& aOriginAttributes) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetOriginAttributes(aOriginAttributes);
}

NS_IMETHODIMP
TLSTransportLayer::GetScriptableOriginAttributes(
    JSContext* aCx, JS::MutableHandle<JS::Value> aOriginAttributes) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetScriptableOriginAttributes(aCx,
                                                         aOriginAttributes);
}

NS_IMETHODIMP
TLSTransportLayer::SetScriptableOriginAttributes(
    JSContext* aCx, JS::Handle<JS::Value> aOriginAttributes) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetScriptableOriginAttributes(aCx,
                                                         aOriginAttributes);
}

NS_IMETHODIMP
TLSTransportLayer::GetHost(nsACString& aHost) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetHost(aHost);
}

NS_IMETHODIMP
TLSTransportLayer::GetTimeout(uint32_t aType, uint32_t* _retval) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetTimeout(aType, _retval);
}

NS_IMETHODIMP
TLSTransportLayer::SetTimeout(uint32_t aType, uint32_t aValue) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetTimeout(aType, aValue);
}

NS_IMETHODIMP
TLSTransportLayer::SetReuseAddrPort(bool aReuseAddrPort) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetReuseAddrPort(aReuseAddrPort);
}

NS_IMETHODIMP
TLSTransportLayer::SetLinger(bool aPolarity, int16_t aTimeout) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetLinger(aPolarity, aTimeout);
}

NS_IMETHODIMP
TLSTransportLayer::GetQoSBits(uint8_t* aQoSBits) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetQoSBits(aQoSBits);
}

NS_IMETHODIMP
TLSTransportLayer::SetQoSBits(uint8_t aQoSBits) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->SetQoSBits(aQoSBits);
}

NS_IMETHODIMP
TLSTransportLayer::GetRetryDnsIfPossible(bool* aRetry) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetRetryDnsIfPossible(aRetry);
}

NS_IMETHODIMP
TLSTransportLayer::GetStatus(nsresult* aStatus) {
  if (!mSocketTransport) {
    return NS_ERROR_FAILURE;
  }
  return mSocketTransport->GetStatus(aStatus);
}

int32_t TLSTransportLayer::OutputInternal(const char* aBuf, int32_t aAmount) {
  LOG(("TLSTransportLayer::OutputInternal %p %d", this, aAmount));

  uint32_t outCountWrite = 0;
  nsresult rv = mSocketOutWrapper.WriteDirectly(aBuf, aAmount, &outCountWrite);
  if (NS_FAILED(rv)) {
    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
      PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
    } else {
      PR_SetError(PR_UNKNOWN_ERROR, 0);
    }
    return -1;
  }

  return outCountWrite;
}

int32_t TLSTransportLayer::InputInternal(char* aBuf, int32_t aAmount) {
  LOG(("TLSTransportLayer::InputInternal aAmount=%d\n", aAmount));

  uint32_t outCountRead = 0;
  nsresult rv = mSocketInWrapper.ReadDirectly(aBuf, aAmount, &outCountRead);
  if (NS_FAILED(rv)) {
    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
      PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
    } else {
      PR_SetError(PR_UNKNOWN_ERROR, 0);
    }
    return -1;
  }
  return outCountRead;
}

PRStatus TLSTransportLayer::GetPeerName(PRFileDesc* aFD, PRNetAddr* addr) {
  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
  NetAddr peeraddr;
  if (NS_FAILED(self->Transport()->GetPeerAddr(&peeraddr))) {
    return PR_FAILURE;
  }
  NetAddrToPRNetAddr(&peeraddr, addr);
  return PR_SUCCESS;
}

PRStatus TLSTransportLayer::GetSocketOption(PRFileDesc* aFD,
                                            PRSocketOptionData* aOpt) {
  if (aOpt->option == PR_SockOpt_Nonblocking) {
    aOpt->value.non_blocking = PR_TRUE;
    return PR_SUCCESS;
  }
  return PR_FAILURE;
}

PRStatus TLSTransportLayer::SetSocketOption(PRFileDesc* aFD,
                                            const PRSocketOptionData* aOpt) {
  return PR_FAILURE;
}

PRStatus TLSTransportLayer::Close(PRFileDesc* aFD) { return PR_SUCCESS; }

int32_t TLSTransportLayer::Write(PRFileDesc* aFD, const void* aBuf,
                                 int32_t aAmount) {
  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
  return self->OutputInternal(static_cast<const char*>(aBuf), aAmount);
}

int32_t TLSTransportLayer::Send(PRFileDesc* aFD, const void* aBuf,
                                int32_t aAmount, int, PRIntervalTime) {
  return Write(aFD, aBuf, aAmount);
}

int32_t TLSTransportLayer::Read(PRFileDesc* aFD, void* aBuf, int32_t aAmount) {
  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
  return self->InputInternal(static_cast<char*>(aBuf), aAmount);
}

int32_t TLSTransportLayer::Recv(PRFileDesc* aFD, void* aBuf, int32_t aAmount,
                                int, PRIntervalTime) {
  return Read(aFD, aBuf, aAmount);
}

int16_t TLSTransportLayer::Poll(PRFileDesc* fd, int16_t in_flags,
                                int16_t* out_flags) {
  LOG(("TLSTransportLayer::Poll fd=%p inf_flags=%d\n", fd, (int)in_flags));
  *out_flags = in_flags;

  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(fd->secret);
  if (!self) {
    return 0;
  }

  if (in_flags & PR_POLL_READ) {
    self->mSocketInWrapper.mSocketIn->AsyncWait(self, 0, 0, nullptr);
  } else if (in_flags & PR_POLL_WRITE) {
    self->mSocketOutWrapper.mSocketOut->AsyncWait(self, 0, 0, nullptr);
  }

  return in_flags;
}

bool TLSTransportLayer::HasDataToRecv() {
  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
  if (!mFD) {
    return false;
  }
  int32_t n = 0;
  char c;
  n = PR_Recv(mFD, &c, 1, PR_MSG_PEEK, 0);
  return n > 0;
}

}  // namespace mozilla::net

[ Dauer der Verarbeitung: 0.105 Sekunden  ]