1 /** 2 * Copyright (c) 2019 Paul-Louis Ageneau 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #ifndef RTC_IMPL_TRANSPORT_H 20 #define RTC_IMPL_TRANSPORT_H 21 22 #include "common.hpp" 23 #include "internals.hpp" 24 #include "message.hpp" 25 26 #include <atomic> 27 #include <functional> 28 #include <memory> 29 30 namespace rtc::impl { 31 32 class Transport { 33 public: 34 enum class State { Disconnected, Connecting, Connected, Completed, Failed }; 35 using state_callback = std::function<void(State state)>; 36 Transport(shared_ptr<Transport> lower=nullptr,state_callback callback=nullptr)37 Transport(shared_ptr<Transport> lower = nullptr, state_callback callback = nullptr) 38 : mLower(std::move(lower)), mStateChangeCallback(std::move(callback)) {} 39 ~Transport()40 virtual ~Transport() { stop(); } 41 start()42 virtual void start() { mStopped = false; } 43 stop()44 virtual bool stop() { 45 if (mStopped.exchange(true)) 46 return false; 47 48 // We don't want incoming() to be called by the lower layer anymore 49 if (mLower) { 50 PLOG_VERBOSE << "Unregistering incoming callback"; 51 mLower->onRecv(nullptr); 52 } 53 return true; 54 } 55 registerIncoming()56 void registerIncoming() { 57 if (mLower) { 58 PLOG_VERBOSE << "Registering incoming callback"; 59 mLower->onRecv(std::bind(&Transport::incoming, this, std::placeholders::_1)); 60 } 61 } 62 onRecv(message_callback callback)63 void onRecv(message_callback callback) { mRecvCallback = std::move(callback); } onStateChange(state_callback callback)64 void onStateChange(state_callback callback) { mStateChangeCallback = std::move(callback); } state() const65 State state() const { return mState; } 66 send(message_ptr message)67 virtual bool send(message_ptr message) { return outgoing(message); } 68 69 protected: recv(message_ptr message)70 void recv(message_ptr message) { 71 try { 72 mRecvCallback(message); 73 } catch (const std::exception &e) { 74 PLOG_WARNING << e.what(); 75 } 76 } changeState(State state)77 void changeState(State state) { 78 try { 79 if (mState.exchange(state) != state) 80 mStateChangeCallback(state); 81 } catch (const std::exception &e) { 82 PLOG_WARNING << e.what(); 83 } 84 } 85 incoming(message_ptr message)86 virtual void incoming(message_ptr message) { recv(message); } outgoing(message_ptr message)87 virtual bool outgoing(message_ptr message) { 88 if (mLower) 89 return mLower->send(message); 90 else 91 return false; 92 } 93 94 private: 95 const shared_ptr<Transport> mLower; 96 synchronized_callback<State> mStateChangeCallback; 97 synchronized_callback<message_ptr> mRecvCallback; 98 99 std::atomic<State> mState = State::Disconnected; 100 std::atomic<bool> mStopped = true; 101 }; 102 103 } // namespace rtc::impl 104 105 #endif 106