123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* 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
|