DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (4a108e94d3e2)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 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/. */

// Original author: ekr@rtfm.com

#ifndef transportlayerloopback_h__
#define transportlayerloopback_h__

#include "nspr.h"
#include "prio.h"
#include "prlock.h"

#include <memory>
#include <queue>


#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsITimer.h"


#include "m_cpp_utils.h"
#include "transportflow.h"
#include "transportlayer.h"

// A simple loopback transport layer that is used for testing.
namespace mozilla {

class TransportLayerLoopback : public TransportLayer {
 public:
  TransportLayerLoopback() :
      peer_(nullptr),
      timer_(nullptr),
      packets_(),
      packets_lock_(nullptr),
      deliverer_(nullptr) {}

  ~TransportLayerLoopback() {
    while (!packets_.empty()) {
      QueuedPacket *packet = packets_.front();
      packets_.pop();
      delete packet;
    }
    if (packets_lock_) {
      PR_DestroyLock(packets_lock_);
    }
    timer_->Cancel();
    deliverer_->Detach();
  }

  // Init
  nsresult Init();

  // Connect to the other side
  void Connect(TransportLayerLoopback* peer);

  // Disconnect
  void Disconnect() {
    TransportLayerLoopback *peer = peer_;

    peer_ = nullptr;
    if (peer) {
      peer->Disconnect();
    }
  }

  // Overrides for TransportLayer
  virtual TransportResult SendPacket(const unsigned char *data, size_t len);

  // Deliver queued packets
  void DeliverPackets();

  TRANSPORT_LAYER_ID("loopback")

 private:
  DISALLOW_COPY_ASSIGN(TransportLayerLoopback);

  // A queued packet
  class QueuedPacket {
   public:
    QueuedPacket() : data_(nullptr), len_(0) {}
    ~QueuedPacket() {
      delete [] data_;
    }

    void Assign(const unsigned char *data, size_t len) {
      data_ = new unsigned char[len];
      memcpy(static_cast<void *>(data_),
             static_cast<const void *>(data), len);
      len_ = len;
    }

    const unsigned char *data() const { return data_; }
    size_t len() const { return len_; }

   private:
    DISALLOW_COPY_ASSIGN(QueuedPacket);

    unsigned char *data_;
    size_t len_;
  };

  // A timer to deliver packets if some are available
  // Fires every 100 ms
  class Deliverer : public nsITimerCallback {
   public:
    explicit Deliverer(TransportLayerLoopback *layer) :
        layer_(layer) {}
    void Detach() {
      layer_ = nullptr;
    }

    NS_DECL_THREADSAFE_ISUPPORTS
    NS_DECL_NSITIMERCALLBACK

 private:
    virtual ~Deliverer() {
    }

    DISALLOW_COPY_ASSIGN(Deliverer);

    TransportLayerLoopback *layer_;
  };

  // Queue a packet for delivery
  nsresult QueuePacket(const unsigned char *data, size_t len);

  TransportLayerLoopback* peer_;
  nsCOMPtr<nsITimer> timer_;
  std::queue<QueuedPacket *> packets_;
  PRLock *packets_lock_;
  nsRefPtr<Deliverer> deliverer_;
};

}  // close namespace
#endif