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 #ifndef transportlayerloopback_h__
10 #define transportlayerloopback_h__
11 
12 #include "nspr.h"
13 #include "prio.h"
14 #include "prlock.h"
15 
16 #include <memory>
17 #include <queue>
18 
19 #include "nsCOMPtr.h"
20 #include "nsINamed.h"
21 #include "nsITimer.h"
22 
23 #include "m_cpp_utils.h"
24 #include "transportflow.h"
25 #include "transportlayer.h"
26 
27 // A simple loopback transport layer that is used for testing.
28 namespace mozilla {
29 
30 class TransportLayerLoopback : public TransportLayer {
31  public:
TransportLayerLoopback()32   TransportLayerLoopback()
33       : peer_(nullptr),
34         timer_(nullptr),
35         packets_(),
36         packets_lock_(nullptr),
37         deliverer_(nullptr),
38         combinePackets_(false) {}
39 
~TransportLayerLoopback()40   ~TransportLayerLoopback() {
41     while (!packets_.empty()) {
42       MediaPacket* packet = packets_.front();
43       packets_.pop();
44       delete packet;
45     }
46     if (packets_lock_) {
47       PR_DestroyLock(packets_lock_);
48     }
49     timer_->Cancel();
50     deliverer_->Detach();
51   }
52 
53   // Init
54   nsresult Init();
55 
56   // Connect to the other side
57   void Connect(TransportLayerLoopback* peer);
58 
59   // Disconnect
Disconnect()60   void Disconnect() {
61     TransportLayerLoopback* peer = peer_;
62 
63     peer_ = nullptr;
64     if (peer) {
65       peer->Disconnect();
66     }
67   }
68 
CombinePackets(bool combine)69   void CombinePackets(bool combine) { combinePackets_ = combine; }
70 
71   // Overrides for TransportLayer
72   TransportResult SendPacket(MediaPacket& packet) override;
73 
74   // Deliver queued packets
75   void DeliverPackets();
76 
77   TRANSPORT_LAYER_ID("loopback")
78 
79  private:
80   DISALLOW_COPY_ASSIGN(TransportLayerLoopback);
81 
82   // A timer to deliver packets if some are available
83   // Fires every 100 ms
84   class Deliverer : public nsITimerCallback, public nsINamed {
85    public:
Deliverer(TransportLayerLoopback * layer)86     explicit Deliverer(TransportLayerLoopback* layer) : layer_(layer) {}
Detach()87     void Detach() { layer_ = nullptr; }
88 
89     NS_DECL_THREADSAFE_ISUPPORTS
90     NS_DECL_NSITIMERCALLBACK
91     NS_DECL_NSINAMED
92 
93    private:
94     virtual ~Deliverer() = default;
95 
96     DISALLOW_COPY_ASSIGN(Deliverer);
97 
98     TransportLayerLoopback* layer_;
99   };
100 
101   // Queue a packet for delivery
102   nsresult QueuePacket(MediaPacket& packet);
103 
104   TransportLayerLoopback* peer_;
105   nsCOMPtr<nsITimer> timer_;
106   std::queue<MediaPacket*> packets_;
107   PRLock* packets_lock_;
108   RefPtr<Deliverer> deliverer_;
109   bool combinePackets_;
110 };
111 
112 }  // namespace mozilla
113 #endif
114