Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Http3StreamTunnel.cpp

  Sprache: C
 

/* 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 "nsHttpConnectionMgr.h"
#include "nsHttpHandler.h"
#include "Http3StreamTunnel.h"
#include "Http3Session.h"
#include "nsQueryObject.h"

namespace mozilla::net {

//-----------------------------------------------------------------------------
// Http3TransportLayer::InputStreamTunnel impl
//-----------------------------------------------------------------------------

NS_IMPL_QUERY_INTERFACE(Http3TransportLayer::InputStreamTunnel, nsIInputStream,
                        nsIAsyncInputStream)

NS_IMETHODIMP_(MozExternalRefCountType)
Http3TransportLayer::InputStreamTunnel::AddRef() {
  return mTransport->AddRef();
}

NS_IMETHODIMP_(MozExternalRefCountType)
Http3TransportLayer::InputStreamTunnel::Release() {
  return mTransport->Release();
}

Http3TransportLayer::InputStreamTunnel::InputStreamTunnel(
    Http3TransportLayer* aTransport)
    : mTransport(aTransport) {}

NS_IMETHODIMP
Http3TransportLayer::InputStreamTunnel::Close() {
  LOG(("Http3TransportLayer::InputStreamTunnel::Close [this=%p]\n", this));
  return CloseWithStatus(NS_BASE_STREAM_CLOSED);
}

NS_IMETHODIMP Http3TransportLayer::InputStreamTunnel::Available(
    uint64_t* avail) {
  LOG(("Http3TransportLayer::InputStreamTunnel::Available [this=%p]\n", this));

  if (NS_FAILED(mCondition)) {
    return mCondition;
  }

  return NS_ERROR_FAILURE;
}

NS_IMETHODIMP Http3TransportLayer::InputStreamTunnel::StreamStatus() {
  LOG(("Http3TransportLayer::InputStreamTunnel::StreamStatus [this=%p]\n",
       this));
  return mCondition;
}

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

  *countRead = 0;

  if (NS_FAILED(mCondition)) {
    return mCondition;
  }

  RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
  if (!tunnel) {
    return NS_ERROR_UNEXPECTED;
  }

  return tunnel->OnWriteSegment(buf, count, countRead);
}

NS_IMETHODIMP
Http3TransportLayer::InputStreamTunnel::ReadSegments(nsWriteSegmentFun writer,
                                                     void* closure,
                                                     uint32_t count,
                                                     uint32_t* countRead) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::InputStreamTunnel::IsNonBlocking(bool* nonblocking) {
  *nonblocking = true;
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::InputStreamTunnel::CloseWithStatus(nsresult reason) {
  LOG(
      ("Http3TransportLayer::InputStreamTunnel::CloseWithStatus [this=%p "
       "reason=%" PRIx32 "]\n",
       this, static_cast<uint32_t>(reason)));
  mCondition = reason;

  RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
  if (!tunnel) {
    return NS_OK;
  }

  tunnel->CleanupStream(reason);
  return NS_OK;
}

nsresult Http3TransportLayer::InputStreamTunnel::OnSocketReady(
    nsresult condition) {
  LOG(("InputStreamTunnel::OnSocketReady [this=%p cond=%" PRIx32 "]\n", this,
       static_cast<uint32_t>(condition)));

  nsCOMPtr<nsIInputStreamCallback> callback;

  // update condition, but be careful not to erase an already
  // existing error condition.
  if (NS_SUCCEEDED(mCondition)) {
    mCondition = condition;
  }
  callback = std::move(mCallback);

  return callback ? callback->OnInputStreamReady(this) : NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::InputStreamTunnel::AsyncWait(
    nsIInputStreamCallback* callback, uint32_t flags, uint32_t amount,
    nsIEventTarget* target) {
  LOG(
      ("Http3TransportLayer::InputStreamTunnel::AsyncWait [this=%p, "
       "callback=%p]\n",
       this, callback));
  // The following parameters are not used:
  (void)flags;
  (void)amount;
  (void)target;

  RefPtr<InputStreamTunnel> self(this);
  if (NS_FAILED(mCondition)) {
    (void)NS_DispatchToCurrentThread(NS_NewRunnableFunction(
        "InputStreamTunnel::CallOnSocketReady",
        [self{std::move(self)}]() { self->OnSocketReady(self->mCondition); }));
  } else if (callback) {
    RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
    if (!tunnel) {
      return NS_ERROR_UNEXPECTED;
    }
    tunnel->HasDataToRead();
  }

  mCallback = callback;
  return NS_OK;
}

//-----------------------------------------------------------------------------
// Http3TransportLayer::OutputStreamTunnel impl
//-----------------------------------------------------------------------------

NS_IMPL_QUERY_INTERFACE(Http3TransportLayer::OutputStreamTunnel,
                        nsIOutputStream, nsIAsyncOutputStream)

NS_IMETHODIMP_(MozExternalRefCountType)
Http3TransportLayer::OutputStreamTunnel::AddRef() {
  return mTransport->AddRef();
}

NS_IMETHODIMP_(MozExternalRefCountType)
Http3TransportLayer::OutputStreamTunnel::Release() {
  return mTransport->Release();
}

Http3TransportLayer::OutputStreamTunnel::OutputStreamTunnel(
    Http3TransportLayer* aTransport)
    : mTransport(aTransport) {}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::Close() {
  LOG(("Http3TransportLayer::OutputStreamTunnel::Close [this=%p]\n", this));
  return CloseWithStatus(NS_BASE_STREAM_CLOSED);
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::Flush() {
  LOG(("Http3TransportLayer::OutputStreamTunnel::Flush [this=%p]\n", this));
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::StreamStatus() {
  LOG(("TLSTransportLayerOutputStream::StreamStatus [this=%p]\n", this));
  return mCondition;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::Write(const char* buf, uint32_t count,
                                               uint32_t* countWritten) {
  LOG(("Http3TransportLayer::OutputStreamTunnel::Write [this=%p count=%u]\n",
       this, count));
  *countWritten = 0;
  if (NS_FAILED(mCondition)) {
    return mCondition;
  }

  RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
  if (!tunnel) {
    return NS_ERROR_UNEXPECTED;
  }

  tunnel->HasDataToWrite();
  return tunnel->OnReadSegment(buf, count, countWritten);
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::WriteSegments(nsReadSegmentFun reader,
                                                       void* closure,
                                                       uint32_t count,
                                                       uint32_t* countRead) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::WriteFrom(nsIInputStream* stream,
                                                   uint32_t count,
                                                   uint32_t* countRead) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::IsNonBlocking(bool* nonblocking) {
  *nonblocking = true;
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::CloseWithStatus(nsresult reason) {
  LOG(("OutputStreamTunnel::CloseWithStatus [this=%p reason=%" PRIx32 "]\n",
       this, static_cast<uint32_t>(reason)));
  mCondition = reason;

  RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
  if (!tunnel) {
    return NS_OK;
  }

  tunnel->CleanupStream(reason);
  return NS_OK;
}

nsresult Http3TransportLayer::OutputStreamTunnel::OnSocketReady(
    nsresult condition) {
  LOG(("OutputStreamTunnel::OnSocketReady [this=%p cond=%" PRIx32
       " callback=%p]\n",
       this, static_cast<uint32_t>(condition), mCallback.get()));

  nsCOMPtr<nsIOutputStreamCallback> callback;

  // update condition, but be careful not to erase an already
  // existing error condition.
  if (NS_SUCCEEDED(mCondition)) {
    mCondition = condition;
  }
  callback = std::move(mCallback);

  nsresult rv = NS_OK;
  if (callback) {
    rv = callback->OnOutputStreamReady(this);
  }

  return rv;
}

NS_IMETHODIMP
Http3TransportLayer::OutputStreamTunnel::AsyncWait(
    nsIOutputStreamCallback* callback, uint32_t flags, uint32_t amount,
    nsIEventTarget* target) {
  LOG(("OutputStreamTunnel::AsyncWait [this=%p]\n", this));

  // The following parameters are not used:
  (void)flags;
  (void)amount;
  (void)target;

  RefPtr<OutputStreamTunnel> self(this);
  if (NS_FAILED(mCondition)) {
    (void)NS_DispatchToCurrentThread(NS_NewRunnableFunction(
        "OutputStreamTunnel::CallOnSocketReady",
        [self{std::move(self)}]() { self->OnSocketReady(self->mCondition); }));
  } else if (callback) {
    // Inform the proxy connection that the inner connetion wants to
    // read data.
    RefPtr<Http3StreamTunnel> tunnel = mTransport->GetStream();
    if (!tunnel) {
      return NS_ERROR_UNEXPECTED;
    }
    tunnel->HasDataToWrite();
  }

  mCallback = callback;
  return NS_OK;
}

//-----------------------------------------------------------------------------
// Http3TransportLayer impl
//-----------------------------------------------------------------------------

NS_IMPL_ISUPPORTS(Http3TransportLayer, nsISocketTransport, nsITransport,
                  nsIInputStreamCallback, nsIOutputStreamCallback)

Http3TransportLayer::Http3TransportLayer(Http3StreamTunnel* aStream)
    : mStream(aStream), mInput(this), mOutput(this) {
  LOG(("Http3TransportLayer ctor %p", this));
}

Http3TransportLayer::~Http3TransportLayer() {
  LOG(("Http3TransportLayer dtor %p", this));
}

already_AddRefed<Http3StreamTunnel> Http3TransportLayer::GetStream() {
  RefPtr<Http3StreamTunnel> stream = mStream;
  if (!stream || stream->Closed()) {
    return nullptr;
  }

  return stream.forget();
}

nsIAsyncInputStream* Http3TransportLayer::GetInput() { return &mInput; }

nsIAsyncOutputStream* Http3TransportLayer::GetOutput() { return &mOutput; }

nsresult Http3TransportLayer::CallToReadData() {
  LOG(("Http3TransportLayer::CallToReadData this=%p", this));
  return mOutput.OnSocketReady(NS_OK);
}

nsresult Http3TransportLayer::CallToWriteData() {
  LOG(("Http3TransportLayer::CallToWriteData this=%p", this));
  if (!mInput.HasCallback()) {
    return NS_BASE_STREAM_WOULD_BLOCK;
  }
  return mInput.OnSocketReady(NS_OK);
}

NS_IMETHODIMP
Http3TransportLayer::OnInputStreamReady(nsIAsyncInputStream* in) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::OnOutputStreamReady(nsIAsyncOutputStream* out) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::SetKeepaliveEnabled(bool aKeepaliveEnabled) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::SetKeepaliveVals(int32_t keepaliveIdleTime,
                                      int32_t keepaliveRetryInterval) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::GetSecurityCallbacks(
    nsIInterfaceRequestor** aSecurityCallbacks) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::SetSecurityCallbacks(
    nsIInterfaceRequestor* aSecurityCallbacks) {
  return NS_OK;
}

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

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

NS_IMETHODIMP
Http3TransportLayer::Close(nsresult aReason) {
  LOG(("Http3TransportLayer::Close [this=%p reason=%" PRIx32 "]\n", this,
       static_cast<uint32_t>(aReason)));
  if (NS_SUCCEEDED(mCondition)) {
    if (NS_SUCCEEDED(aReason)) {
      aReason = NS_BASE_STREAM_CLOSED;
    }
    mOutput.CloseWithStatus(aReason);
    mInput.CloseWithStatus(aReason);
    // Let the session pickup that the stream has been closed.
    mCondition = aReason;
  }
  return NS_OK;
}

void Http3TransportLayer::OnStreamClosed(nsresult aReason) {
  LOG(("Http3TransportLayer::OnStreamClosed this=%p", this));
  if (NS_SUCCEEDED(mCondition)) {
    if (NS_SUCCEEDED(aReason)) {
      aReason = NS_BASE_STREAM_CLOSED;
    }
    mOutput.OnSocketReady(aReason);
    mInput.OnSocketReady(aReason);
    mCondition = aReason;
  }
}

NS_IMETHODIMP
Http3TransportLayer::SetEventSink(nsITransportEventSink* aSink,
                                  nsIEventTarget* aEventTarget) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::Bind(NetAddr* aLocalAddr) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::GetEchConfigUsed(bool* aEchConfigUsed) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::SetEchConfig(const nsACString& aEchConfig) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP
Http3TransportLayer::ResolvedByTRR(bool* aResolvedByTRR) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP Http3TransportLayer::GetEffectiveTRRMode(
    nsIRequest::TRRMode* aEffectiveTRRMode) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

NS_IMETHODIMP Http3TransportLayer::GetTrrSkipReason(
    nsITRRSkipReason::value* aTrrSkipReason) {
  return NS_ERROR_NOT_IMPLEMENTED;
}

#define FWD_H3ST_PTR(fx, ts) \
  NS_IMETHODIMP              \
  Http3TransportLayer::fx(ts* arg) { return NS_OK; }

#define FWD_H3ST_ADDREF(fx, ts) \
  NS_IMETHODIMP                 \
  Http3TransportLayer::fx(ts** arg) { return NS_OK; }

#define FWD_H3ST(fx, ts) \
  NS_IMETHODIMP          \
  Http3TransportLayer::fx(ts arg) { return NS_OK; }

FWD_H3ST_PTR(GetKeepaliveEnabled, bool);
FWD_H3ST_PTR(GetSendBufferSize, uint32_t);
FWD_H3ST(SetSendBufferSize, uint32_t);
FWD_H3ST_PTR(GetPort, int32_t);
FWD_H3ST_PTR(GetSelfAddr, mozilla::net::NetAddr);
FWD_H3ST_ADDREF(GetScriptablePeerAddr, nsINetAddr);
FWD_H3ST_ADDREF(GetScriptableSelfAddr, nsINetAddr);
FWD_H3ST_PTR(GetConnectionFlags, uint32_t);
FWD_H3ST(SetConnectionFlags, uint32_t);
FWD_H3ST(SetIsTRRConnection, bool);
FWD_H3ST_PTR(GetIsTRRConnection, bool);
FWD_H3ST_PTR(GetTlsFlags, uint32_t);
FWD_H3ST(SetTlsFlags, uint32_t);
FWD_H3ST_PTR(GetRecvBufferSize, uint32_t);
FWD_H3ST(SetRecvBufferSize, uint32_t);
FWD_H3ST_PTR(GetResetIPFamilyPreference, bool);

nsresult Http3TransportLayer::IsAlive(bool* aAlive) {
  *aAlive = true;
  return NS_OK;
}

nsresult Http3TransportLayer::GetPeerAddr(NetAddr* addr) {
  // TODO: what address we should use?
  NetAddr peerAddr;
  peerAddr.InitFromString("127.0.0.1"_ns);
  *addr = peerAddr;
  return NS_OK;
}

nsresult Http3TransportLayer::GetTlsSocketControl(
    nsITLSSocketControl** tlsSocketControl) {
  return NS_OK;
}

nsresult Http3TransportLayer::GetOriginAttributes(
    mozilla::OriginAttributes* aOriginAttributes) {
  return NS_OK;
}

nsresult Http3TransportLayer::SetOriginAttributes(
    const mozilla::OriginAttributes& aOriginAttributes) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::GetScriptableOriginAttributes(
    JSContext* aCx, JS::MutableHandle<JS::Value> aOriginAttributes) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::SetScriptableOriginAttributes(
    JSContext* aCx, JS::Handle<JS::Value> aOriginAttributes) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::GetHost(nsACString& aHost) { return NS_OK; }

NS_IMETHODIMP
Http3TransportLayer::GetTimeout(uint32_t aType, uint32_t* _retval) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::SetTimeout(uint32_t aType, uint32_t aValue) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::SetReuseAddrPort(bool aReuseAddrPort) { return NS_OK; }

NS_IMETHODIMP
Http3TransportLayer::SetLinger(bool aPolarity, int16_t aTimeout) {
  return NS_OK;
}

NS_IMETHODIMP
Http3TransportLayer::GetQoSBits(uint8_t* aQoSBits) { return NS_OK; }

NS_IMETHODIMP
Http3TransportLayer::SetQoSBits(uint8_t aQoSBits) { return NS_OK; }

NS_IMETHODIMP
Http3TransportLayer::GetRetryDnsIfPossible(bool* aRetry) { return NS_OK; }

NS_IMETHODIMP
Http3TransportLayer::GetStatus(nsresult* aStatus) {
  *aStatus = mCondition;
  return NS_OK;
}

//-----------------------------------------------------------------------------
// Http3StreamTunnel impl
//-----------------------------------------------------------------------------

Http3StreamTunnel::Http3StreamTunnel(nsAHttpTransaction* aTrans,
                                     Http3Session* aSession,
                                     uint64_t aCurrentBrowserId)
    : Http3Stream(aTrans, aSession, ClassOfService(), aCurrentBrowserId) {
  LOG(("Http3StreamTunnel ctor %p", this));
}

Http3StreamTunnel::~Http3StreamTunnel() {
  LOG(("Http3StreamTunnel dtor %p", this));
}

nsresult Http3StreamTunnel::TryActivating() {
  nsProxyInfo* info = mTransaction->ConnectionInfo()->ProxyInfo();
  if (!info) {
    return NS_ERROR_UNEXPECTED;
  }

  nsAutoCString host;
  DebugOnly<nsresult> rv{};
  rv = nsHttpHandler::GenerateHostPort(
      nsDependentCString(mTransaction->ConnectionInfo()->Origin()),
      mTransaction->ConnectionInfo()->OriginPort(), host);
  MOZ_ASSERT(NS_SUCCEEDED(rv));

  LOG(("Http3StreamTunnel::TryActivating [auth=%s]", host.get()));
  return mSession->TryActivating("CONNECT"_ns, ""_ns, host, ""_ns,
                                 mFlatHttpRequestHeaders, &mStreamId, this);
}

void Http3StreamTunnel::Close(nsresult aResult) {
  LOG(("Http3StreamTunnel::Close %p", this));
  if (mClosed) {
    return;
  }
  mClosed = true;

  mRecvState = RECV_DONE;
  mSendState = SEND_DONE;

  mSession = nullptr;

  if (mTransaction) {
    mTransaction->Close(aResult);
  }

  if (mTransport) {
    mTransport->OnStreamClosed(aResult);
    mTransport = nullptr;
  }
}

nsresult Http3StreamTunnel::ReadSegments() {
  LOG(("Http3StreamTunnel::ReadSegments %p mSendState=%d mRecvState=%d", this,
       mSendState, mRecvState));
  if (mRecvState == RECV_DONE) {
    // Don't transmit any request frames if the peer cannot respond or respone
    // is already done.
    LOG3(
        ("Http3StreamTunnel %p ReadSegments request stream aborted due to"
         " response side closure\n",
         this));
    return NS_ERROR_ABORT;
  }

  if (mSendState == SEND_DONE) {
    return NS_OK;
  }

  if (!mTransport) {
    return NS_ERROR_UNEXPECTED;
  }

  nsresult rv = mTransport->CallToReadData();

  if (mSendState == WAITING_TO_ACTIVATE &&
      (NS_SUCCEEDED(rv) || rv == NS_BASE_STREAM_WOULD_BLOCK)) {
    LOG3(("Http3StreamTunnel %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)));
  }

  return rv;
}

nsresult Http3StreamTunnel::BufferInput() {
  char buf[SimpleBufferPage::kSimpleBufferPageSize];
  uint32_t countWritten;
  nsresult rv = mSession->ReadResponseData(
      mStreamId, buf, SimpleBufferPage::kSimpleBufferPageSize, &countWritten,
      &mFin);
  if (NS_FAILED(rv) && rv != NS_BASE_STREAM_WOULD_BLOCK) {
    return rv;
  }
  LOG(("Http3StreamTunnel::BufferInput %p countWritten=%d mFin=%d", this,
       countWritten, mFin));
  if (countWritten == 0) {
    if (mFin) {
      mRecvState = RECV_DONE;
      rv = NS_BASE_STREAM_CLOSED;
    } else {
      rv = NS_BASE_STREAM_WOULD_BLOCK;
    }
  } else {
    mTotalRead += countWritten;
    if (mFin) {
      mRecvState = RECEIVED_FIN;
    }
  }
  if (NS_SUCCEEDED(rv)) {
    rv = mSimpleBuffer.Write(buf, countWritten);
    if (NS_FAILED(rv)) {
      MOZ_ASSERT(rv == NS_ERROR_OUT_OF_MEMORY);
      return NS_ERROR_OUT_OF_MEMORY;
    }
  }
  return rv;
}

nsresult Http3StreamTunnel::WriteSegments() {
  LOG(("Http3StreamTunnel::WriteSegments [this=%p]", this));
  if (mRecvState == RECV_DONE) {
    return NS_OK;
  }

  if (!mTransport) {
    return NS_ERROR_UNEXPECTED;
  }

  nsresult rv = NS_OK;
  bool again = true;

  do {
    mSocketInCondition = NS_OK;
    rv = mTransport->CallToWriteData();
    if (mRecvState == RECV_DONE) {
      return NS_ERROR_UNEXPECTED;
    }

    // When CallToWriteData() returns NS_BASE_STREAM_WOULD_BLOCK, it means the
    // consumer can't accept data at the moment. We need to read the data into a
    // buffer so it won't block other streams.
    if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
      rv = BufferInput();
    }

    if (mRecvState == RECEIVED_FIN) {
      rv = NS_BASE_STREAM_CLOSED;
      mRecvState = RECV_DONE;
    }

    if (NS_FAILED(rv)) {
      if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
        rv = NS_OK;
      }
      again = false;
    } else if (NS_FAILED(mSocketInCondition)) {
      if (mSocketInCondition != NS_BASE_STREAM_WOULD_BLOCK) {
        rv = mSocketInCondition;
      }
      again = false;
    }
  } while (again && gHttpHandler->Active());

  return rv;
}

nsresult Http3StreamTunnel::OnWriteSegment(char* buf, uint32_t count,
                                           uint32_t* countWritten) {
  LOG(("Http3StreamTunnel::OnWriteSegment [this=%p, state=%d", this,
       mRecvState));
  // Sometimes we have read data from the network and stored it in a pipe
  // so that other streams can proceed when the gecko caller is not processing
  // data events fast enough and flow control hasn't caught up yet. This
  // gets the stored data out of that pipe
  if (mSimpleBuffer.Available()) {
    *countWritten = mSimpleBuffer.Read(buf, count);
    MOZ_ASSERT(*countWritten);
    LOG3(
        ("Http3StreamTunnel::OnWriteSegment read from flow "
         "control buffer %p %d",
         this, *countWritten));
    return NS_OK;
  }

  return Http3Stream::OnWriteSegment(buf, count, countWritten);
}

void Http3StreamTunnel::HasDataToWrite() {
  mSession->StreamHasDataToWrite(this);
}

void Http3StreamTunnel::HasDataToRead() {
  // We can't always call ConnectSlowConsumer(), because it triggers
  // ForceRecv(),
  // which posts a runnable to call WriteSegments() again. When we already have
  // data buffered, this is fine. The consumer can read data from the buffer.
  // However, if no data is buffered, doing this would create a busy loop that
  // continuously waits for data.
  if (mSimpleBuffer.Available()) {
    mSession->ConnectSlowConsumer(this);
  }
}

already_AddRefed<nsHttpConnection> Http3StreamTunnel::CreateHttpConnection(
    nsIInterfaceRequestor* aCallbacks, PRIntervalTime aRtt,
    bool aIsExtendedCONNECT) {
  mTransport = new Http3TransportLayer(this);
  RefPtr<nsHttpConnection> conn = new nsHttpConnection();

  conn->SetTransactionCaps(mTransaction->Caps());
  nsresult rv =
      conn->Init(mTransaction->ConnectionInfo(),
                 gHttpHandler->ConnMgr()->MaxRequestDelay(), mTransport,
                 mTransport->GetInput(), mTransport->GetOutput(), true, NS_OK,
                 aCallbacks, aRtt, aIsExtendedCONNECT);
  MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
  return conn.forget();
}

void Http3StreamTunnel::CleanupStream(nsresult aReason) {
  if (mSession && !mClosed) {
    LOG(("Http3StreamTunnel::CleanupStream %p", this));
    mSession->CloseStream(this, aReason);
  }
}

}  // namespace mozilla::net

Messung V0.5 in Prozent
C=93 H=95 G=93

¤ Dauer der Verarbeitung: 0.8 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

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 und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002