#include "remoting/protocol/webrtc_data_stream_adapter.h"
#include <stdint.h>
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/task/sequenced_task_runner.h"
#include "net/base/net_errors.h"
#include "remoting/base/compound_buffer.h"
#include "remoting/protocol/message_serialization.h"
namespace remoting::protocol {
class ScopedAllowSyncPrimitivesForWebRtcDataStreamAdapter
: public base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {};
WebrtcDataStreamAdapter::WebrtcDataStreamAdapter(
rtc::scoped_refptr<webrtc::DataChannelInterface> channel)
: channel_(channel.get()) {
channel_->RegisterObserver(this);
DCHECK_EQ(channel_->state(), webrtc::DataChannelInterface::kConnecting);
}
WebrtcDataStreamAdapter::~WebrtcDataStreamAdapter() {
if (channel_) {
channel_->UnregisterObserver();
channel_->Close();
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce([](rtc::scoped_refptr<webrtc::DataChannelInterface>) {},
std::move(channel_)));
}
}
void WebrtcDataStreamAdapter::Start(EventHandler* event_handler) {
DCHECK(!event_handler_);
DCHECK(event_handler);
event_handler_ = event_handler;
}
void WebrtcDataStreamAdapter::Send(google::protobuf::MessageLite* message,
base::OnceClosure done) {
rtc::CopyOnWriteBuffer buffer;
buffer.SetSize(message->ByteSize());
message->SerializeWithCachedSizesToArray(buffer.MutableData());
pending_messages_.emplace(
webrtc::DataBuffer(std::move(buffer), true ),
std::move(done));
SendMessagesIfReady();
}
void WebrtcDataStreamAdapter::SendMessagesIfReady() {
ScopedAllowSyncPrimitivesForWebRtcDataStreamAdapter allow_wait;
while (state_ == State::OPEN && channel_->buffered_amount() == 0 &&
!pending_messages_.empty()) {
PendingMessage message = std::move(pending_messages_.front());
pending_messages_.pop();
if (!channel_->Send(std::move(message.buffer))) {
LOG(ERROR) << "Send failed on data channel " << channel_->label();
channel_->Close();
return;
}
if (message.done_callback) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(message.done_callback));
}
}
}
void WebrtcDataStreamAdapter::OnStateChange() {
switch (channel_->state()) {
case webrtc::DataChannelInterface::kOpen:
DCHECK(state_ == State::CONNECTING);
state_ = State::OPEN;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&WebrtcDataStreamAdapter::InvokeOpenEvent,
weak_ptr_factory_.GetWeakPtr()));
break;
case webrtc::DataChannelInterface::kClosing:
if (state_ != State::CLOSED) {
state_ = State::CLOSED;
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&WebrtcDataStreamAdapter::InvokeClosedEvent,
weak_ptr_factory_.GetWeakPtr()));
}
break;
case webrtc::DataChannelInterface::kConnecting:
case webrtc::DataChannelInterface::kClosed:
break;
}
}
void WebrtcDataStreamAdapter::OnMessage(const webrtc::DataBuffer& rtc_buffer) {
if (state_ != State::OPEN) {
LOG(ERROR) << "Dropping a message received when the channel is not open.";
return;
}
std::unique_ptr<CompoundBuffer> buffer(new CompoundBuffer());
buffer->AppendCopyOf(reinterpret_cast<const char*>(rtc_buffer.data.data()),
rtc_buffer.data.size());
buffer->Lock();
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&WebrtcDataStreamAdapter::InvokeMessageEvent,
weak_ptr_factory_.GetWeakPtr(), std::move(buffer)));
}
void WebrtcDataStreamAdapter::OnBufferedAmountChange(uint64_t previous_amount) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&WebrtcDataStreamAdapter::SendMessagesIfReady,
weak_ptr_factory_.GetWeakPtr()));
}
bool WebrtcDataStreamAdapter::IsOkToCallOnTheNetworkThread() {
return true;
}
void WebrtcDataStreamAdapter::InvokeOpenEvent() {
event_handler_->OnMessagePipeOpen();
}
void WebrtcDataStreamAdapter::InvokeClosedEvent() {
event_handler_->OnMessagePipeClosed();
}
void WebrtcDataStreamAdapter::InvokeMessageEvent(
std::unique_ptr<CompoundBuffer> buffer) {
event_handler_->OnMessageReceived(std::move(buffer));
}
WebrtcDataStreamAdapter::PendingMessage::PendingMessage(
webrtc::DataBuffer buffer,
base::OnceClosure done_callback)
: buffer(std::move(buffer)), done_callback(std::move(done_callback)) {}
WebrtcDataStreamAdapter::PendingMessage&
WebrtcDataStreamAdapter::PendingMessage::operator=(PendingMessage&&) = default;
WebrtcDataStreamAdapter::PendingMessage::PendingMessage(PendingMessage&&) =
default;
WebrtcDataStreamAdapter::PendingMessage::~PendingMessage() = default;
}