2012-10-02 13:04:58 -07:00
|
|
|
/* -*- 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 transportflow_h__
|
|
|
|
#define transportflow_h__
|
|
|
|
|
|
|
|
#include <deque>
|
2012-10-18 13:01:52 -07:00
|
|
|
#include <queue>
|
2012-10-02 13:04:58 -07:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "nscore.h"
|
|
|
|
#include "nsISupportsImpl.h"
|
|
|
|
#include "transportlayer.h"
|
|
|
|
#include "m_cpp_utils.h"
|
|
|
|
|
|
|
|
// A stack of transport layers acts as a flow.
|
|
|
|
// Generally, one reads and writes to the top layer.
|
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
class TransportFlow : public sigslot::has_slots<> {
|
|
|
|
public:
|
|
|
|
TransportFlow() : id_("(anonymous)") {}
|
|
|
|
TransportFlow(const std::string id) : id_(id) {}
|
|
|
|
~TransportFlow();
|
|
|
|
|
|
|
|
const std::string& id() const { return id_; }
|
|
|
|
|
|
|
|
// Layer management. Note PushLayer() is not thread protected, so
|
|
|
|
// either:
|
|
|
|
// (a) Do it in the thread handling the I/O
|
|
|
|
// (b) Do it before you activate the I/O system
|
2012-10-18 13:01:52 -07:00
|
|
|
//
|
|
|
|
// The flow takes ownership of the layers after a successful
|
|
|
|
// push.
|
2012-10-02 13:04:58 -07:00
|
|
|
nsresult PushLayer(TransportLayer *layer);
|
2012-10-18 13:01:52 -07:00
|
|
|
|
|
|
|
// Convenience function to push multiple layers on. Layers
|
|
|
|
// are pushed on in the order that they are in the queue.
|
|
|
|
// Any layers which cannot be pushed on are just deleted
|
|
|
|
// and an error is returned.
|
|
|
|
// TODO(ekr@rtfm.com): Change layers to be ref-counted.
|
|
|
|
nsresult PushLayers(std::queue<TransportLayer *> layers);
|
|
|
|
|
2012-10-02 13:04:58 -07:00
|
|
|
TransportLayer *top() const;
|
|
|
|
TransportLayer *GetLayer(const std::string& id) const;
|
|
|
|
|
|
|
|
// Wrappers for whatever TLayer happens to be the top layer
|
|
|
|
// at the time. This way you don't need to do top()->Foo().
|
|
|
|
TransportLayer::State state(); // Current state
|
|
|
|
TransportResult SendPacket(const unsigned char *data, size_t len);
|
|
|
|
|
|
|
|
// State has changed. Reflects the top flow.
|
|
|
|
sigslot::signal2<TransportFlow *, TransportLayer::State>
|
|
|
|
SignalStateChange;
|
|
|
|
|
|
|
|
// Data received on the flow
|
|
|
|
sigslot::signal3<TransportFlow*, const unsigned char *, size_t>
|
|
|
|
SignalPacketReceived;
|
|
|
|
|
|
|
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportFlow)
|
|
|
|
|
|
|
|
private:
|
|
|
|
DISALLOW_COPY_ASSIGN(TransportFlow);
|
|
|
|
|
|
|
|
void StateChange(TransportLayer *layer, TransportLayer::State state);
|
|
|
|
void PacketReceived(TransportLayer* layer, const unsigned char *data,
|
|
|
|
size_t len);
|
|
|
|
|
|
|
|
std::string id_;
|
|
|
|
std::deque<TransportLayer *> layers_;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // close namespace
|
|
|
|
#endif
|