summaryrefslogtreecommitdiffstats
path: root/media/mtransport/transportlayerloopback.h
diff options
context:
space:
mode:
Diffstat (limited to 'media/mtransport/transportlayerloopback.h')
-rw-r--r--media/mtransport/transportlayerloopback.h153
1 files changed, 153 insertions, 0 deletions
diff --git a/media/mtransport/transportlayerloopback.h b/media/mtransport/transportlayerloopback.h
new file mode 100644
index 000000000..8ad5e2865
--- /dev/null
+++ b/media/mtransport/transportlayerloopback.h
@@ -0,0 +1,153 @@
+/* -*- 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),
+ combinePackets_(false) {}
+
+ ~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();
+ }
+ }
+
+ void CombinePackets(bool combine) { combinePackets_ = combine; }
+
+ // 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;
+ }
+
+ void Assign(const unsigned char *data1, size_t len1,
+ const unsigned char *data2, size_t len2) {
+ data_ = new unsigned char[len1 + len2];
+ memcpy(static_cast<void *>(data_),
+ static_cast<const void *>(data1), len1);
+ memcpy(static_cast<void *>(data_ + len1),
+ static_cast<const void *>(data2), len2);
+ len_ = len1 + len2;
+ }
+
+ 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_;
+ RefPtr<Deliverer> deliverer_;
+ bool combinePackets_;
+};
+
+} // close namespace
+#endif