/** * 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_DATA_CHANNEL_H #define RTC_DATA_CHANNEL_H #include "channel.hpp" #include "include.hpp" #include "message.hpp" #include "queue.hpp" #include "reliability.hpp" #include #include #include #include #include namespace rtc { class SctpTransport; class PeerConnection; class DataChannel : public std::enable_shared_from_this, public Channel { public: DataChannel(std::weak_ptr pc, uint16_t stream, string label, string protocol, Reliability reliability); virtual ~DataChannel(); uint16_t stream() const; uint16_t id() const; string label() const; string protocol() const; Reliability reliability() const; void close(void) override; bool send(message_variant data) override; bool send(const byte *data, size_t size); template bool sendBuffer(const Buffer &buf); template bool sendBuffer(Iterator first, Iterator last); bool isOpen(void) const override; bool isClosed(void) const override; size_t maxMessageSize() const override; // Extended API size_t availableAmount() const override; std::optional receive() override; std::optional peek() override; protected: virtual void open(std::shared_ptr transport); virtual void processOpenMessage(message_ptr message); void remoteClose(); bool outgoing(message_ptr message); void incoming(message_ptr message); const std::weak_ptr mPeerConnection; std::weak_ptr mSctpTransport; uint16_t mStream; string mLabel; string mProtocol; std::shared_ptr mReliability; std::atomic mIsOpen = false; std::atomic mIsClosed = false; private: Queue mRecvQueue; friend class PeerConnection; }; class NegociatedDataChannel final : public DataChannel { public: NegociatedDataChannel(std::weak_ptr pc, uint16_t stream, string label, string protocol, Reliability reliability); NegociatedDataChannel(std::weak_ptr pc, std::weak_ptr transport, uint16_t stream); ~NegociatedDataChannel(); private: void open(std::shared_ptr transport) override; void processOpenMessage(message_ptr message) override; friend class PeerConnection; }; template std::pair to_bytes(const Buffer &buf) { using T = typename std::remove_pointer::type; using E = typename std::conditional::value, byte, T>::type; return std::make_pair(static_cast(static_cast(buf.data())), buf.size() * sizeof(E)); } template bool DataChannel::sendBuffer(const Buffer &buf) { auto [bytes, size] = to_bytes(buf); auto message = std::make_shared(size); std::copy(bytes, bytes + size, message->data()); return outgoing(message); } template bool DataChannel::sendBuffer(Iterator first, Iterator last) { size_t size = 0; for (Iterator it = first; it != last; ++it) size += it->size(); auto message = std::make_shared(size); auto pos = message->begin(); for (Iterator it = first; it != last; ++it) { auto [bytes, len] = to_bytes(*it); pos = std::copy(bytes, bytes + len, pos); } return outgoing(message); } } // namespace rtc #endif