tor-browser

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

transportlayerloopback.cpp (3421B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 // Original author: ekr@rtfm.com
      8 
      9 #include "transportlayerloopback.h"
     10 
     11 #include "logging.h"
     12 #include "nsNetCID.h"
     13 #include "nsServiceManagerUtils.h"
     14 #include "nsString.h"
     15 #include "prlock.h"
     16 
     17 namespace mozilla {
     18 
     19 MOZ_MTLOG_MODULE("mtransport")
     20 
     21 nsresult TransportLayerLoopback::Init() {
     22  nsresult rv;
     23  target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     24  MOZ_ASSERT(NS_SUCCEEDED(rv));
     25  if (!NS_SUCCEEDED(rv)) return rv;
     26 
     27  timer_ = NS_NewTimer(target_);
     28  MOZ_ASSERT(timer_);
     29  if (!timer_) return NS_ERROR_FAILURE;
     30 
     31  packets_lock_ = PR_NewLock();
     32  MOZ_ASSERT(packets_lock_);
     33  if (!packets_lock_) return NS_ERROR_FAILURE;
     34 
     35  deliverer_ = new Deliverer(this);
     36 
     37  timer_->InitWithCallback(deliverer_, 100, nsITimer::TYPE_REPEATING_SLACK);
     38 
     39  return NS_OK;
     40 }
     41 
     42 // Connect to the other side
     43 void TransportLayerLoopback::Connect(TransportLayerLoopback* peer) {
     44  peer_ = peer;
     45 
     46  TL_SET_STATE(TS_OPEN);
     47 }
     48 
     49 TransportResult TransportLayerLoopback::SendPacket(MediaPacket& packet) {
     50  MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "SendPacket(" << packet.len() << ")");
     51 
     52  if (!peer_) {
     53    MOZ_MTLOG(ML_ERROR, "Discarding packet because peer not attached");
     54    return TE_ERROR;
     55  }
     56 
     57  size_t len = packet.len();
     58  nsresult res = peer_->QueuePacket(packet);
     59  if (!NS_SUCCEEDED(res)) return TE_ERROR;
     60 
     61  return static_cast<TransportResult>(len);
     62 }
     63 
     64 nsresult TransportLayerLoopback::QueuePacket(MediaPacket& packet) {
     65  MOZ_ASSERT(packets_lock_);
     66 
     67  PR_Lock(packets_lock_);
     68 
     69  if (combinePackets_ && !packets_.empty()) {
     70    MediaPacket* prevPacket = packets_.front();
     71 
     72    MOZ_MTLOG(ML_DEBUG, LAYER_INFO << " Enqueuing combined packets of length "
     73                                   << prevPacket->len() << " and "
     74                                   << packet.len());
     75    auto combined = MakeUnique<uint8_t[]>(prevPacket->len() + packet.len());
     76    memcpy(combined.get(), prevPacket->data(), prevPacket->len());
     77    memcpy(combined.get() + prevPacket->len(), packet.data(), packet.len());
     78    prevPacket->Take(std::move(combined), prevPacket->len() + packet.len());
     79  } else {
     80    MOZ_MTLOG(ML_DEBUG,
     81              LAYER_INFO << " Enqueuing packet of length " << packet.len());
     82    packets_.push(new MediaPacket(std::move(packet)));
     83  }
     84 
     85  PRStatus r = PR_Unlock(packets_lock_);
     86  MOZ_ASSERT(r == PR_SUCCESS);
     87  if (r != PR_SUCCESS) return NS_ERROR_FAILURE;
     88 
     89  return NS_OK;
     90 }
     91 
     92 void TransportLayerLoopback::DeliverPackets() {
     93  while (!packets_.empty()) {
     94    UniquePtr<MediaPacket> packet(packets_.front());
     95    packets_.pop();
     96 
     97    MOZ_MTLOG(ML_DEBUG,
     98              LAYER_INFO << " Delivering packet of length " << packet->len());
     99    SignalPacketReceived(this, *packet);
    100  }
    101 }
    102 
    103 NS_IMPL_ISUPPORTS(TransportLayerLoopback::Deliverer, nsITimerCallback, nsINamed)
    104 
    105 NS_IMETHODIMP TransportLayerLoopback::Deliverer::Notify(nsITimer* timer) {
    106  if (!layer_) return NS_OK;
    107 
    108  layer_->DeliverPackets();
    109 
    110  return NS_OK;
    111 }
    112 
    113 NS_IMETHODIMP TransportLayerLoopback::Deliverer::GetName(nsACString& aName) {
    114  aName.AssignLiteral("TransportLayerLoopback::Deliverer");
    115  return NS_OK;
    116 }
    117 
    118 }  // namespace mozilla