Files
libdatachannel/src/impl/transport.hpp
2021-04-13 23:03:16 +02:00

105 lines
2.8 KiB
C++

/**
* Copyright (c) 2019 Paul-Louis Ageneau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RTC_IMPL_TRANSPORT_H
#define RTC_IMPL_TRANSPORT_H
#include "common.hpp"
#include "internals.hpp"
#include "message.hpp"
#include <atomic>
#include <functional>
#include <memory>
namespace rtc::impl {
class Transport {
public:
enum class State { Disconnected, Connecting, Connected, Completed, Failed };
using state_callback = std::function<void(State state)>;
Transport(shared_ptr<Transport> lower = nullptr, state_callback callback = nullptr)
: mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) {}
virtual ~Transport() { stop(); }
virtual void start() { mStopped = false; }
virtual bool stop() {
if (mStopped.exchange(true))
return false;
// We don't want incoming() to be called by the lower layer anymore
if (mLower) {
PLOG_VERBOSE << "Unregistering incoming callback";
mLower->onRecv(nullptr);
}
return true;
}
void registerIncoming() {
if (mLower) {
PLOG_VERBOSE << "Registering incoming callback";
mLower->onRecv(std::bind(&Transport::incoming, this, std::placeholders::_1));
}
}
void onRecv(message_callback callback) { mRecvCallback = std::move(callback); }
State state() const { return mState; }
virtual bool send(message_ptr message) { return outgoing(message); }
protected:
void recv(message_ptr message) {
try {
mRecvCallback(message);
} catch (const std::exception &e) {
PLOG_WARNING << e.what();
}
}
void changeState(State state) {
try {
if (mState.exchange(state) != state)
mStateChangeCallback(state);
} catch (const std::exception &e) {
PLOG_WARNING << e.what();
}
}
virtual void incoming(message_ptr message) { recv(message); }
virtual bool outgoing(message_ptr message) {
if (mLower)
return mLower->send(message);
else
return false;
}
private:
shared_ptr<Transport> mLower;
synchronized_callback<State> mStateChangeCallback;
synchronized_callback<message_ptr> mRecvCallback;
std::atomic<State> mState = State::Disconnected;
std::atomic<bool> mStopped = true;
};
} // namespace rtc::impl
#endif