tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TLSTransportLayer.cpp (27843B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=4 sw=2 et cindent: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // HttpLog.h should generally be included first
      8 #include "HttpLog.h"
      9 
     10 #include "Http2StreamTunnel.h"
     11 #include "TLSTransportLayer.h"
     12 #include "nsISocketProvider.h"
     13 #include "nsITLSSocketControl.h"
     14 #include "nsQueryObject.h"
     15 #include "nsSocketProviderService.h"
     16 #include "nsSocketTransport2.h"
     17 
     18 namespace mozilla::net {
     19 
     20 //-----------------------------------------------------------------------------
     21 // TLSTransportLayerInputStream impl
     22 //-----------------------------------------------------------------------------
     23 
     24 NS_IMPL_QUERY_INTERFACE(TLSTransportLayer::InputStreamWrapper, nsIInputStream,
     25                        nsIAsyncInputStream)
     26 
     27 NS_IMETHODIMP_(MozExternalRefCountType)
     28 TLSTransportLayer::InputStreamWrapper::AddRef() { return mTransport->AddRef(); }
     29 
     30 NS_IMETHODIMP_(MozExternalRefCountType)
     31 TLSTransportLayer::InputStreamWrapper::Release() {
     32  return mTransport->Release();
     33 }
     34 
     35 TLSTransportLayer::InputStreamWrapper::InputStreamWrapper(
     36    nsIAsyncInputStream* aInputStream, TLSTransportLayer* aTransport)
     37    : mSocketIn(aInputStream), mTransport(aTransport) {}
     38 
     39 NS_IMETHODIMP
     40 TLSTransportLayer::InputStreamWrapper::Close() {
     41  LOG(("TLSTransportLayer::InputStreamWrapper::Close [this=%p]\n", this));
     42  return mSocketIn->Close();
     43 }
     44 
     45 NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::Available(
     46    uint64_t* avail) {
     47  LOG(("TLSTransportLayer::InputStreamWrapper::Available [this=%p]\n", this));
     48  return mSocketIn->Available(avail);
     49 }
     50 
     51 NS_IMETHODIMP TLSTransportLayer::InputStreamWrapper::StreamStatus() {
     52  LOG(("TLSTransportLayer::InputStreamWrapper::StreamStatus [this=%p]\n",
     53       this));
     54  return mSocketIn->StreamStatus();
     55 }
     56 
     57 nsresult TLSTransportLayer::InputStreamWrapper::ReadDirectly(
     58    char* buf, uint32_t count, uint32_t* countRead) {
     59  LOG(("TLSTransportLayer::InputStreamWrapper::ReadDirectly [this=%p]\n",
     60       this));
     61  return mSocketIn->Read(buf, count, countRead);
     62 }
     63 
     64 NS_IMETHODIMP
     65 TLSTransportLayer::InputStreamWrapper::Read(char* buf, uint32_t count,
     66                                            uint32_t* countRead) {
     67  LOG(("TLSTransportLayer::InputStreamWrapper::Read [this=%p]\n", this));
     68 
     69  *countRead = 0;
     70 
     71  if (NS_FAILED(mStatus)) {
     72    return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
     73  }
     74 
     75  int32_t bytesRead = PR_Read(mTransport->mFD, buf, count);
     76  if (bytesRead > 0) {
     77    *countRead = bytesRead;
     78  } else if (bytesRead < 0) {
     79    PRErrorCode code = PR_GetError();
     80    if (code == PR_WOULD_BLOCK_ERROR) {
     81      LOG((
     82          "TLSTransportLayer::InputStreamWrapper::Read %p PR_Read would block ",
     83          this));
     84      return NS_BASE_STREAM_WOULD_BLOCK;
     85    }
     86    // If reading from the socket succeeded (NS_SUCCEEDED(mStatus)),
     87    // but the nss layer encountered an error remember the error.
     88    if (NS_SUCCEEDED(mStatus)) {
     89      mStatus = mTransport->mInputStatus;
     90      LOG((
     91          "TLSTransportLayer::InputStreamWrapper::Read %p socket error %" PRIx32
     92          ".\n",
     93          this, static_cast<uint32_t>(mStatus)));
     94    }
     95  }
     96 
     97  if (NS_SUCCEEDED(mStatus) && !bytesRead) {
     98    LOG(
     99        ("TLSTransportLayer::InputStreamWrapper::Read %p "
    100         "Second layer of TLS stripping results in STREAM_CLOSED\n",
    101         this));
    102    mStatus = NS_BASE_STREAM_CLOSED;
    103  }
    104 
    105  LOG(("TLSTransportLayer::InputStreamWrapper::Read %p rv=%" PRIx32
    106       " didread=%d "
    107       "2 layers of ssl stripped to plaintext\n",
    108       this, static_cast<uint32_t>(mStatus), bytesRead));
    109  return mStatus;
    110 }
    111 
    112 NS_IMETHODIMP
    113 TLSTransportLayer::InputStreamWrapper::ReadSegments(nsWriteSegmentFun writer,
    114                                                    void* closure,
    115                                                    uint32_t count,
    116                                                    uint32_t* countRead) {
    117  LOG(("TLSTransportLayer::InputStreamWrapper::ReadSegments [this=%p]\n",
    118       this));
    119  return mSocketIn->ReadSegments(writer, closure, count, countRead);
    120 }
    121 
    122 NS_IMETHODIMP
    123 TLSTransportLayer::InputStreamWrapper::IsNonBlocking(bool* nonblocking) {
    124  return mSocketIn->IsNonBlocking(nonblocking);
    125 }
    126 
    127 NS_IMETHODIMP
    128 TLSTransportLayer::InputStreamWrapper::CloseWithStatus(nsresult reason) {
    129  LOG(
    130      ("TLSTransportLayer::InputStreamWrapper::CloseWithStatus [this=%p "
    131       "reason=%" PRIx32 "]\n",
    132       this, static_cast<uint32_t>(reason)));
    133  mStatus = reason;
    134  return mSocketIn->CloseWithStatus(reason);
    135 }
    136 
    137 NS_IMETHODIMP
    138 TLSTransportLayer::InputStreamWrapper::AsyncWait(
    139    nsIInputStreamCallback* callback, uint32_t flags, uint32_t amount,
    140    nsIEventTarget* target) {
    141  LOG(
    142      ("TLSTransportLayer::InputStreamWrapper::AsyncWait [this=%p, "
    143       "callback=%p]\n",
    144       this, callback));
    145  mTransport->mInputCallback = callback;
    146  // Don't bother to call PR_POLL when |callback| is NULL. We call |AsyncWait|
    147  // directly to null out the underlying callback.
    148  if (!callback) {
    149    return mSocketIn->AsyncWait(nullptr, 0, 0, nullptr);
    150  }
    151 
    152  PRPollDesc pd;
    153  pd.fd = mTransport->mFD;
    154  pd.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
    155  // Only run PR_Poll on the socket thread. Also, make sure this lives at least
    156  // as long as that operation.
    157  auto DoPoll = [self = RefPtr{this}, pd(pd)]() mutable {
    158    int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
    159    LOG(("TLSTransportLayer::InputStreamWrapper::AsyncWait rv=%d", rv));
    160  };
    161  if (OnSocketThread()) {
    162    DoPoll();
    163  } else {
    164    gSocketTransportService->Dispatch(NS_NewRunnableFunction(
    165        "TLSTransportLayer::InputStreamWrapper::AsyncWait", DoPoll));
    166  }
    167  return NS_OK;
    168 }
    169 
    170 //-----------------------------------------------------------------------------
    171 // TLSTransportLayerOutputStream impl
    172 //-----------------------------------------------------------------------------
    173 
    174 NS_IMPL_QUERY_INTERFACE(TLSTransportLayer::OutputStreamWrapper, nsIOutputStream,
    175                        nsIAsyncOutputStream)
    176 
    177 NS_IMETHODIMP_(MozExternalRefCountType)
    178 TLSTransportLayer::OutputStreamWrapper::AddRef() {
    179  return mTransport->AddRef();
    180 }
    181 
    182 NS_IMETHODIMP_(MozExternalRefCountType)
    183 TLSTransportLayer::OutputStreamWrapper::Release() {
    184  return mTransport->Release();
    185 }
    186 
    187 TLSTransportLayer::OutputStreamWrapper::OutputStreamWrapper(
    188    nsIAsyncOutputStream* aOutputStream, TLSTransportLayer* aTransport)
    189    : mSocketOut(aOutputStream), mTransport(aTransport) {}
    190 
    191 NS_IMETHODIMP
    192 TLSTransportLayer::OutputStreamWrapper::Close() {
    193  LOG(("TLSTransportLayer::OutputStreamWrapper::Close [this=%p]\n", this));
    194  return mSocketOut->Close();
    195 }
    196 
    197 NS_IMETHODIMP
    198 TLSTransportLayer::OutputStreamWrapper::Flush() {
    199  LOG(("TLSTransportLayerOutputStream::Flush [this=%p]\n", this));
    200  return mSocketOut->Flush();
    201 }
    202 
    203 NS_IMETHODIMP
    204 TLSTransportLayer::OutputStreamWrapper::StreamStatus() {
    205  LOG(("TLSTransportLayerOutputStream::StreamStatus [this=%p]\n", this));
    206  return mSocketOut->StreamStatus();
    207 }
    208 
    209 nsresult TLSTransportLayer::OutputStreamWrapper::WriteDirectly(
    210    const char* buf, uint32_t count, uint32_t* countWritten) {
    211  LOG(
    212      ("TLSTransportLayer::OutputStreamWrapper::WriteDirectly [this=%p "
    213       "count=%u]\n",
    214       this, count));
    215  return mSocketOut->Write(buf, count, countWritten);
    216 }
    217 
    218 NS_IMETHODIMP
    219 TLSTransportLayer::OutputStreamWrapper::Write(const char* buf, uint32_t count,
    220                                              uint32_t* countWritten) {
    221  LOG(("TLSTransportLayer::OutputStreamWrapper::Write [this=%p count=%u]\n",
    222       this, count));
    223 
    224  *countWritten = 0;
    225 
    226  if (NS_FAILED(mStatus)) {
    227    return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
    228  }
    229 
    230  int32_t written = PR_Write(mTransport->mFD, buf, count);
    231  LOG(("TLSTransportLayer::OutputStreamWrapper::Write %p PRWrite(%d) = %d",
    232       this, count, written));
    233 
    234  if (written > 0) {
    235    *countWritten = written;
    236  } else if (written < 0) {
    237    PRErrorCode code = PR_GetError();
    238    if (code == PR_WOULD_BLOCK_ERROR) {
    239      LOG(
    240          ("TLSTransportLayer::OutputStreamWrapper::Write %p PRWrite would "
    241           "block ",
    242           this));
    243      return NS_BASE_STREAM_WOULD_BLOCK;
    244    }
    245 
    246    // Writing to the socket succeeded, but failed in nss layer.
    247    if (NS_SUCCEEDED(mStatus)) {
    248      mStatus = mTransport->mOutputStatus;
    249      LOG(
    250          ("TLSTransportLayer:::OutputStreamWrapper::Write %p socket error "
    251           "%" PRIx32 " code=%d\n",
    252           this, static_cast<uint32_t>(mStatus), code));
    253    }
    254  }
    255 
    256  return mStatus;
    257 }
    258 
    259 NS_IMETHODIMP
    260 TLSTransportLayer::OutputStreamWrapper::WriteSegments(nsReadSegmentFun reader,
    261                                                      void* closure,
    262                                                      uint32_t count,
    263                                                      uint32_t* countRead) {
    264  return mSocketOut->WriteSegments(reader, closure, count, countRead);
    265 }
    266 
    267 // static
    268 nsresult TLSTransportLayer::OutputStreamWrapper::WriteFromSegments(
    269    nsIInputStream* input, void* closure, const char* fromSegment,
    270    uint32_t offset, uint32_t count, uint32_t* countRead) {
    271  OutputStreamWrapper* self = (OutputStreamWrapper*)closure;
    272  return self->Write(fromSegment, count, countRead);
    273 }
    274 
    275 NS_IMETHODIMP
    276 TLSTransportLayer::OutputStreamWrapper::WriteFrom(nsIInputStream* stream,
    277                                                  uint32_t count,
    278                                                  uint32_t* countRead) {
    279  return stream->ReadSegments(WriteFromSegments, this, count, countRead);
    280 }
    281 
    282 NS_IMETHODIMP
    283 TLSTransportLayer::OutputStreamWrapper::IsNonBlocking(bool* nonblocking) {
    284  return mSocketOut->IsNonBlocking(nonblocking);
    285 }
    286 
    287 NS_IMETHODIMP
    288 TLSTransportLayer::OutputStreamWrapper::CloseWithStatus(nsresult reason) {
    289  LOG(("OutputStreamWrapper::CloseWithStatus [this=%p reason=%" PRIx32 "]\n",
    290       this, static_cast<uint32_t>(reason)));
    291  mStatus = reason;
    292  return mSocketOut->CloseWithStatus(reason);
    293 }
    294 
    295 NS_IMETHODIMP
    296 TLSTransportLayer::OutputStreamWrapper::AsyncWait(
    297    nsIOutputStreamCallback* callback, uint32_t flags, uint32_t amount,
    298    nsIEventTarget* target) {
    299  LOG(
    300      ("TLSTransportLayer::OutputStreamWrapper::AsyncWait [this=%p, "
    301       "mOutputCallback=%p "
    302       "callback=%p]\n",
    303       this, mTransport->mOutputCallback.get(), callback));
    304  mTransport->mOutputCallback = callback;
    305  // Don't bother to call PR_POLL when |callback| is NULL. We call |AsyncWait|
    306  // directly to null out the underlying callback.
    307  if (!callback) {
    308    return mSocketOut->AsyncWait(nullptr, 0, 0, nullptr);
    309  }
    310 
    311  PRPollDesc pd;
    312  pd.fd = mTransport->mFD;
    313  pd.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
    314  int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
    315  LOG(("TLSTransportLayer::OutputStreamWrapper::AsyncWait rv=%d", rv));
    316  return NS_OK;
    317 }
    318 
    319 //-----------------------------------------------------------------------------
    320 // TLSTransportLayer impl
    321 //-----------------------------------------------------------------------------
    322 
    323 static PRDescIdentity sTLSTransportLayerIdentity;
    324 static PRIOMethods sTLSTransportLayerMethods;
    325 static PRIOMethods* sTLSTransportLayerMethodsPtr = nullptr;
    326 
    327 bool TLSTransportLayer::DispatchRelease() {
    328  if (OnSocketThread()) {
    329    return false;
    330  }
    331 
    332  gSocketTransportService->Dispatch(
    333      NewNonOwningRunnableMethod("net::TLSTransportLayer::Release", this,
    334                                 &TLSTransportLayer::Release),
    335      NS_DISPATCH_NORMAL);
    336 
    337  return true;
    338 }
    339 
    340 NS_IMPL_ADDREF(TLSTransportLayer)
    341 NS_IMETHODIMP_(MozExternalRefCountType)
    342 TLSTransportLayer::Release() {
    343  nsrefcnt count = mRefCnt - 1;
    344  if (DispatchRelease()) {
    345    // Redispatched to the socket thread.
    346    return count;
    347  }
    348 
    349  MOZ_ASSERT(0 != mRefCnt, "dup release");
    350  count = --mRefCnt;
    351  NS_LOG_RELEASE(this, count, "TLSTransportLayer");
    352 
    353  if (0 == count) {
    354    mRefCnt = 1;
    355    delete (this);
    356    return 0;
    357  }
    358 
    359  return count;
    360 }
    361 
    362 NS_INTERFACE_MAP_BEGIN(TLSTransportLayer)
    363  NS_INTERFACE_MAP_ENTRY(nsISocketTransport)
    364  NS_INTERFACE_MAP_ENTRY(nsITransport)
    365  NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback)
    366  NS_INTERFACE_MAP_ENTRY(nsIOutputStreamCallback)
    367  NS_INTERFACE_MAP_ENTRY_CONCRETE(TLSTransportLayer)
    368  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITransport)
    369 NS_INTERFACE_MAP_END
    370 
    371 TLSTransportLayer::TLSTransportLayer(nsISocketTransport* aTransport,
    372                                     nsIAsyncInputStream* aInputStream,
    373                                     nsIAsyncOutputStream* aOutputStream,
    374                                     nsIInputStreamCallback* aOwner)
    375    : mSocketTransport(aTransport),
    376      mSocketInWrapper(aInputStream, this),
    377      mSocketOutWrapper(aOutputStream, this),
    378      mOwner(aOwner) {
    379  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
    380  LOG(("TLSTransportLayer ctor this=[%p]", this));
    381 }
    382 
    383 TLSTransportLayer::~TLSTransportLayer() {
    384  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
    385  LOG(("TLSTransportLayer dtor this=[%p]", this));
    386  if (mFD) {
    387    PR_Close(mFD);
    388    mFD = nullptr;
    389  }
    390  mTLSSocketControl = nullptr;
    391 }
    392 
    393 bool TLSTransportLayer::Init(const char* aTLSHost, int32_t aTLSPort) {
    394  LOG(("TLSTransportLayer::Init this=[%p]", this));
    395  nsCOMPtr<nsISocketProvider> provider;
    396  nsCOMPtr<nsISocketProviderService> spserv =
    397      nsSocketProviderService::GetOrCreate();
    398  if (!spserv) {
    399    return false;
    400  }
    401 
    402  spserv->GetSocketProvider("ssl", getter_AddRefs(provider));
    403  if (!provider) {
    404    return false;
    405  }
    406 
    407  // Install an NSPR layer to handle getpeername() with a failure. This is kind
    408  // of silly, but the default one used by the pipe asserts when called and the
    409  // nss code calls it to see if we are connected to a real socket or not.
    410  if (!sTLSTransportLayerMethodsPtr) {
    411    // one time initialization
    412    sTLSTransportLayerIdentity = PR_GetUniqueIdentity("TLSTransportLayer");
    413    sTLSTransportLayerMethods = *PR_GetDefaultIOMethods();
    414    sTLSTransportLayerMethods.getpeername = GetPeerName;
    415    sTLSTransportLayerMethods.getsocketoption = GetSocketOption;
    416    sTLSTransportLayerMethods.setsocketoption = SetSocketOption;
    417    sTLSTransportLayerMethods.read = Read;
    418    sTLSTransportLayerMethods.write = Write;
    419    sTLSTransportLayerMethods.send = Send;
    420    sTLSTransportLayerMethods.recv = Recv;
    421    sTLSTransportLayerMethods.close = Close;
    422    sTLSTransportLayerMethods.poll = Poll;
    423    sTLSTransportLayerMethodsPtr = &sTLSTransportLayerMethods;
    424  }
    425 
    426  mFD = PR_CreateIOLayerStub(sTLSTransportLayerIdentity,
    427                             &sTLSTransportLayerMethods);
    428  if (!mFD) {
    429    return false;
    430  }
    431 
    432  mFD->secret = reinterpret_cast<PRFilePrivate*>(this);
    433 
    434  return NS_SUCCEEDED(provider->AddToSocket(
    435      PR_AF_INET, aTLSHost, aTLSPort, nullptr, OriginAttributes(), 0, 0, mFD,
    436      getter_AddRefs(mTLSSocketControl)));
    437 }
    438 
    439 NS_IMETHODIMP
    440 TLSTransportLayer::OnInputStreamReady(nsIAsyncInputStream* in) {
    441  nsCOMPtr<nsIInputStreamCallback> callback = std::move(mInputCallback);
    442  if (callback) {
    443    return callback->OnInputStreamReady(&mSocketInWrapper);
    444  }
    445  return NS_OK;
    446 }
    447 
    448 NS_IMETHODIMP
    449 TLSTransportLayer::OnOutputStreamReady(nsIAsyncOutputStream* out) {
    450  nsCOMPtr<nsIOutputStreamCallback> callback = std::move(mOutputCallback);
    451  nsresult rv = NS_OK;
    452  if (callback) {
    453    rv = callback->OnOutputStreamReady(&mSocketOutWrapper);
    454 
    455    RefPtr<OutputStreamTunnel> tunnel = do_QueryObject(out);
    456    if (tunnel) {
    457      tunnel->MaybeSetRequestDone(callback);
    458    }
    459  }
    460  return rv;
    461 }
    462 
    463 NS_IMETHODIMP
    464 TLSTransportLayer::SetKeepaliveEnabled(bool aKeepaliveEnabled) {
    465  if (!mSocketTransport) {
    466    return NS_ERROR_FAILURE;
    467  }
    468  return mSocketTransport->SetKeepaliveEnabled(aKeepaliveEnabled);
    469 }
    470 
    471 NS_IMETHODIMP
    472 TLSTransportLayer::SetKeepaliveVals(int32_t keepaliveIdleTime,
    473                                    int32_t keepaliveRetryInterval) {
    474  if (!mSocketTransport) {
    475    return NS_ERROR_FAILURE;
    476  }
    477  return mSocketTransport->SetKeepaliveVals(keepaliveIdleTime,
    478                                            keepaliveRetryInterval);
    479 }
    480 
    481 NS_IMETHODIMP
    482 TLSTransportLayer::GetSecurityCallbacks(
    483    nsIInterfaceRequestor** aSecurityCallbacks) {
    484  if (!mSocketTransport) {
    485    return NS_ERROR_FAILURE;
    486  }
    487  return mSocketTransport->GetSecurityCallbacks(aSecurityCallbacks);
    488 }
    489 
    490 NS_IMETHODIMP
    491 TLSTransportLayer::SetSecurityCallbacks(
    492    nsIInterfaceRequestor* aSecurityCallbacks) {
    493  if (!mSocketTransport) {
    494    return NS_ERROR_FAILURE;
    495  }
    496 
    497  return mSocketTransport->SetSecurityCallbacks(aSecurityCallbacks);
    498 }
    499 
    500 NS_IMETHODIMP
    501 TLSTransportLayer::OpenInputStream(uint32_t aFlags, uint32_t aSegmentSize,
    502                                   uint32_t aSegmentCount,
    503                                   nsIInputStream** _retval) {
    504  return NS_ERROR_NOT_IMPLEMENTED;
    505 }
    506 
    507 NS_IMETHODIMP
    508 TLSTransportLayer::OpenOutputStream(uint32_t aFlags, uint32_t aSegmentSize,
    509                                    uint32_t aSegmentCount,
    510                                    nsIOutputStream** _retval) {
    511  return NS_ERROR_NOT_IMPLEMENTED;
    512 }
    513 
    514 NS_IMETHODIMP
    515 TLSTransportLayer::Close(nsresult aReason) {
    516  LOG(("TLSTransportLayer::Close [this=%p reason=%" PRIx32 "]\n", this,
    517       static_cast<uint32_t>(aReason)));
    518 
    519  mInputCallback = nullptr;
    520  mOutputCallback = nullptr;
    521  if (mSocketTransport) {
    522    mSocketTransport->Close(aReason);
    523    mSocketTransport = nullptr;
    524  }
    525  mSocketInWrapper.AsyncWait(nullptr, 0, 0, nullptr);
    526  mSocketInWrapper.CloseWithStatus(aReason);
    527  mSocketOutWrapper.AsyncWait(nullptr, 0, 0, nullptr);
    528  mSocketOutWrapper.CloseWithStatus(aReason);
    529 
    530  if (mOwner) {
    531    RefPtr<TLSTransportLayer> self = this;
    532    (void)NS_DispatchToCurrentThread(NS_NewRunnableFunction(
    533        "TLSTransportLayer::Close", [self{std::move(self)}]() {
    534          nsCOMPtr<nsIInputStreamCallback> inputCallback =
    535              std::move(self->mOwner);
    536          if (inputCallback) {
    537            // This is hack. We need to make
    538            // nsHttpConnection::OnInputStreamReady be called, so
    539            // nsHttpConnection::CloseTransaction can be called to release the
    540            // transaction.
    541            (void)inputCallback->OnInputStreamReady(&self->mSocketInWrapper);
    542          }
    543        }));
    544  }
    545 
    546  return NS_OK;
    547 }
    548 
    549 NS_IMETHODIMP
    550 TLSTransportLayer::SetEventSink(nsITransportEventSink* aSink,
    551                                nsIEventTarget* aEventTarget) {
    552  if (!mSocketTransport) {
    553    return NS_ERROR_FAILURE;
    554  }
    555  return mSocketTransport->SetEventSink(aSink, aEventTarget);
    556 }
    557 
    558 NS_IMETHODIMP
    559 TLSTransportLayer::Bind(NetAddr* aLocalAddr) {
    560  if (!mSocketTransport) {
    561    return NS_ERROR_FAILURE;
    562  }
    563  return mSocketTransport->Bind(aLocalAddr);
    564 }
    565 
    566 NS_IMETHODIMP
    567 TLSTransportLayer::GetEchConfigUsed(bool* aEchConfigUsed) {
    568  if (!mSocketTransport) {
    569    return NS_ERROR_FAILURE;
    570  }
    571  return mSocketTransport->GetEchConfigUsed(aEchConfigUsed);
    572 }
    573 
    574 NS_IMETHODIMP
    575 TLSTransportLayer::SetEchConfig(const nsACString& aEchConfig) {
    576  if (!mSocketTransport) {
    577    return NS_ERROR_FAILURE;
    578  }
    579  return mSocketTransport->SetEchConfig(aEchConfig);
    580 }
    581 
    582 NS_IMETHODIMP
    583 TLSTransportLayer::ResolvedByTRR(bool* aResolvedByTRR) {
    584  if (!mSocketTransport) {
    585    return NS_ERROR_FAILURE;
    586  }
    587  return mSocketTransport->ResolvedByTRR(aResolvedByTRR);
    588 }
    589 
    590 NS_IMETHODIMP TLSTransportLayer::GetEffectiveTRRMode(
    591    nsIRequest::TRRMode* aEffectiveTRRMode) {
    592  if (!mSocketTransport) {
    593    return NS_ERROR_FAILURE;
    594  }
    595  return mSocketTransport->GetEffectiveTRRMode(aEffectiveTRRMode);
    596 }
    597 
    598 NS_IMETHODIMP TLSTransportLayer::GetTrrSkipReason(
    599    nsITRRSkipReason::value* aTrrSkipReason) {
    600  if (!mSocketTransport) {
    601    return NS_ERROR_FAILURE;
    602  }
    603  return mSocketTransport->GetTrrSkipReason(aTrrSkipReason);
    604 }
    605 
    606 #define FWD_TS_PTR(fx, ts)                          \
    607  NS_IMETHODIMP                                     \
    608  TLSTransportLayer::fx(ts* arg) {                  \
    609    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    610    return mSocketTransport->fx(arg);               \
    611  }
    612 
    613 #define FWD_TS_ADDREF(fx, ts)                       \
    614  NS_IMETHODIMP                                     \
    615  TLSTransportLayer::fx(ts** arg) {                 \
    616    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    617    return mSocketTransport->fx(arg);               \
    618  }
    619 
    620 #define FWD_TS(fx, ts)                              \
    621  NS_IMETHODIMP                                     \
    622  TLSTransportLayer::fx(ts arg) {                   \
    623    if (!mSocketTransport) return NS_ERROR_FAILURE; \
    624    return mSocketTransport->fx(arg);               \
    625  }
    626 
    627 FWD_TS_PTR(GetKeepaliveEnabled, bool);
    628 FWD_TS_PTR(GetSendBufferSize, uint32_t);
    629 FWD_TS(SetSendBufferSize, uint32_t);
    630 FWD_TS_PTR(GetPort, int32_t);
    631 FWD_TS_PTR(GetPeerAddr, mozilla::net::NetAddr);
    632 FWD_TS_PTR(GetSelfAddr, mozilla::net::NetAddr);
    633 FWD_TS_ADDREF(GetScriptablePeerAddr, nsINetAddr);
    634 FWD_TS_ADDREF(GetScriptableSelfAddr, nsINetAddr);
    635 FWD_TS_PTR(IsAlive, bool);
    636 FWD_TS_PTR(GetConnectionFlags, uint32_t);
    637 FWD_TS(SetConnectionFlags, uint32_t);
    638 FWD_TS(SetIsPrivate, bool);
    639 FWD_TS_PTR(GetTlsFlags, uint32_t);
    640 FWD_TS(SetTlsFlags, uint32_t);
    641 FWD_TS_PTR(GetRecvBufferSize, uint32_t);
    642 FWD_TS(SetRecvBufferSize, uint32_t);
    643 FWD_TS_PTR(GetResetIPFamilyPreference, bool);
    644 
    645 nsresult TLSTransportLayer::GetTlsSocketControl(
    646    nsITLSSocketControl** tlsSocketControl) {
    647  if (!mTLSSocketControl) {
    648    return NS_ERROR_ABORT;
    649  }
    650 
    651  *tlsSocketControl = do_AddRef(mTLSSocketControl).take();
    652  return NS_OK;
    653 }
    654 
    655 nsresult TLSTransportLayer::GetOriginAttributes(
    656    mozilla::OriginAttributes* aOriginAttributes) {
    657  if (!mSocketTransport) {
    658    return NS_ERROR_FAILURE;
    659  }
    660  return mSocketTransport->GetOriginAttributes(aOriginAttributes);
    661 }
    662 
    663 nsresult TLSTransportLayer::SetOriginAttributes(
    664    const mozilla::OriginAttributes& aOriginAttributes) {
    665  if (!mSocketTransport) {
    666    return NS_ERROR_FAILURE;
    667  }
    668  return mSocketTransport->SetOriginAttributes(aOriginAttributes);
    669 }
    670 
    671 NS_IMETHODIMP
    672 TLSTransportLayer::GetScriptableOriginAttributes(
    673    JSContext* aCx, JS::MutableHandle<JS::Value> aOriginAttributes) {
    674  if (!mSocketTransport) {
    675    return NS_ERROR_FAILURE;
    676  }
    677  return mSocketTransport->GetScriptableOriginAttributes(aCx,
    678                                                         aOriginAttributes);
    679 }
    680 
    681 NS_IMETHODIMP
    682 TLSTransportLayer::SetScriptableOriginAttributes(
    683    JSContext* aCx, JS::Handle<JS::Value> aOriginAttributes) {
    684  if (!mSocketTransport) {
    685    return NS_ERROR_FAILURE;
    686  }
    687  return mSocketTransport->SetScriptableOriginAttributes(aCx,
    688                                                         aOriginAttributes);
    689 }
    690 
    691 NS_IMETHODIMP
    692 TLSTransportLayer::GetHost(nsACString& aHost) {
    693  if (!mSocketTransport) {
    694    return NS_ERROR_FAILURE;
    695  }
    696  return mSocketTransport->GetHost(aHost);
    697 }
    698 
    699 NS_IMETHODIMP
    700 TLSTransportLayer::GetTimeout(uint32_t aType, uint32_t* _retval) {
    701  if (!mSocketTransport) {
    702    return NS_ERROR_FAILURE;
    703  }
    704  return mSocketTransport->GetTimeout(aType, _retval);
    705 }
    706 
    707 NS_IMETHODIMP
    708 TLSTransportLayer::SetTimeout(uint32_t aType, uint32_t aValue) {
    709  if (!mSocketTransport) {
    710    return NS_ERROR_FAILURE;
    711  }
    712  return mSocketTransport->SetTimeout(aType, aValue);
    713 }
    714 
    715 NS_IMETHODIMP
    716 TLSTransportLayer::SetReuseAddrPort(bool aReuseAddrPort) {
    717  if (!mSocketTransport) {
    718    return NS_ERROR_FAILURE;
    719  }
    720  return mSocketTransport->SetReuseAddrPort(aReuseAddrPort);
    721 }
    722 
    723 NS_IMETHODIMP
    724 TLSTransportLayer::SetLinger(bool aPolarity, int16_t aTimeout) {
    725  if (!mSocketTransport) {
    726    return NS_ERROR_FAILURE;
    727  }
    728  return mSocketTransport->SetLinger(aPolarity, aTimeout);
    729 }
    730 
    731 NS_IMETHODIMP
    732 TLSTransportLayer::GetQoSBits(uint8_t* aQoSBits) {
    733  if (!mSocketTransport) {
    734    return NS_ERROR_FAILURE;
    735  }
    736  return mSocketTransport->GetQoSBits(aQoSBits);
    737 }
    738 
    739 NS_IMETHODIMP
    740 TLSTransportLayer::SetQoSBits(uint8_t aQoSBits) {
    741  if (!mSocketTransport) {
    742    return NS_ERROR_FAILURE;
    743  }
    744  return mSocketTransport->SetQoSBits(aQoSBits);
    745 }
    746 
    747 NS_IMETHODIMP
    748 TLSTransportLayer::GetRetryDnsIfPossible(bool* aRetry) {
    749  if (!mSocketTransport) {
    750    return NS_ERROR_FAILURE;
    751  }
    752  return mSocketTransport->GetRetryDnsIfPossible(aRetry);
    753 }
    754 
    755 NS_IMETHODIMP
    756 TLSTransportLayer::GetStatus(nsresult* aStatus) {
    757  if (!mSocketTransport) {
    758    return NS_ERROR_FAILURE;
    759  }
    760  return mSocketTransport->GetStatus(aStatus);
    761 }
    762 
    763 int32_t TLSTransportLayer::OutputInternal(const char* aBuf, int32_t aAmount) {
    764  LOG(("TLSTransportLayer::OutputInternal %p %d", this, aAmount));
    765 
    766  uint32_t outCountWrite = 0;
    767  mOutputStatus =
    768      mSocketOutWrapper.WriteDirectly(aBuf, aAmount, &outCountWrite);
    769  if (NS_FAILED(mOutputStatus)) {
    770    if (mOutputStatus == NS_BASE_STREAM_WOULD_BLOCK) {
    771      PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
    772    } else {
    773      PR_SetError(PR_UNKNOWN_ERROR, 0);
    774    }
    775    return -1;
    776  }
    777 
    778  return outCountWrite;
    779 }
    780 
    781 int32_t TLSTransportLayer::InputInternal(char* aBuf, int32_t aAmount) {
    782  LOG(("TLSTransportLayer::InputInternal aAmount=%d\n", aAmount));
    783 
    784  uint32_t outCountRead = 0;
    785  mInputStatus = mSocketInWrapper.ReadDirectly(aBuf, aAmount, &outCountRead);
    786  if (NS_FAILED(mInputStatus)) {
    787    if (mInputStatus == NS_BASE_STREAM_WOULD_BLOCK) {
    788      PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
    789    } else {
    790      PR_SetError(PR_UNKNOWN_ERROR, 0);
    791    }
    792    return -1;
    793  }
    794  return outCountRead;
    795 }
    796 
    797 PRStatus TLSTransportLayer::GetPeerName(PRFileDesc* aFD, PRNetAddr* addr) {
    798  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
    799  NetAddr peeraddr;
    800  if (NS_FAILED(self->Transport()->GetPeerAddr(&peeraddr))) {
    801    return PR_FAILURE;
    802  }
    803  NetAddrToPRNetAddr(&peeraddr, addr);
    804  return PR_SUCCESS;
    805 }
    806 
    807 PRStatus TLSTransportLayer::GetSocketOption(PRFileDesc* aFD,
    808                                            PRSocketOptionData* aOpt) {
    809  if (aOpt->option == PR_SockOpt_Nonblocking) {
    810    aOpt->value.non_blocking = PR_TRUE;
    811    return PR_SUCCESS;
    812  }
    813  return PR_FAILURE;
    814 }
    815 
    816 PRStatus TLSTransportLayer::SetSocketOption(PRFileDesc* aFD,
    817                                            const PRSocketOptionData* aOpt) {
    818  return PR_FAILURE;
    819 }
    820 
    821 PRStatus TLSTransportLayer::Close(PRFileDesc* aFD) { return PR_SUCCESS; }
    822 
    823 int32_t TLSTransportLayer::Write(PRFileDesc* aFD, const void* aBuf,
    824                                 int32_t aAmount) {
    825  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
    826  return self->OutputInternal(static_cast<const char*>(aBuf), aAmount);
    827 }
    828 
    829 int32_t TLSTransportLayer::Send(PRFileDesc* aFD, const void* aBuf,
    830                                int32_t aAmount, int, PRIntervalTime) {
    831  return Write(aFD, aBuf, aAmount);
    832 }
    833 
    834 int32_t TLSTransportLayer::Read(PRFileDesc* aFD, void* aBuf, int32_t aAmount) {
    835  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(aFD->secret);
    836  return self->InputInternal(static_cast<char*>(aBuf), aAmount);
    837 }
    838 
    839 int32_t TLSTransportLayer::Recv(PRFileDesc* aFD, void* aBuf, int32_t aAmount,
    840                                int, PRIntervalTime) {
    841  return Read(aFD, aBuf, aAmount);
    842 }
    843 
    844 int16_t TLSTransportLayer::Poll(PRFileDesc* fd, int16_t in_flags,
    845                                int16_t* out_flags) {
    846  LOG(("TLSTransportLayer::Poll fd=%p inf_flags=%d\n", fd, (int)in_flags));
    847  *out_flags = in_flags;
    848 
    849  TLSTransportLayer* self = reinterpret_cast<TLSTransportLayer*>(fd->secret);
    850  if (!self) {
    851    return 0;
    852  }
    853 
    854  if (in_flags & PR_POLL_READ) {
    855    self->mSocketInWrapper.mSocketIn->AsyncWait(self, 0, 0, nullptr);
    856  } else if (in_flags & PR_POLL_WRITE) {
    857    self->mSocketOutWrapper.mSocketOut->AsyncWait(self, 0, 0, nullptr);
    858  }
    859 
    860  return in_flags;
    861 }
    862 
    863 bool TLSTransportLayer::HasDataToRecv() {
    864  MOZ_ASSERT(OnSocketThread(), "not on socket thread");
    865  if (!mFD) {
    866    return false;
    867  }
    868  int32_t n = 0;
    869  char c;
    870  n = PR_Recv(mFD, &c, 1, PR_MSG_PEEK, 0);
    871  return n > 0;
    872 }
    873 
    874 }  // namespace mozilla::net