Telegram-Android/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp
2023-10-29 00:52:06 +04:00

168 lines
5.2 KiB
C++

#include "SctpDataChannelProviderInterfaceImpl.h"
#include "p2p/base/dtls_transport.h"
#include "api/transport/field_trial_based_config.h"
#include "FieldTrialsConfig.h"
namespace tgcalls {
SctpDataChannelProviderInterfaceImpl::SctpDataChannelProviderInterfaceImpl(
rtc::PacketTransportInternal *transportChannel,
bool isOutgoing,
std::function<void(bool)> onStateChanged,
std::function<void()> onTerminated,
std::function<void(std::string const &)> onMessageReceived,
std::shared_ptr<Threads> threads
) :
_threads(std::move(threads)),
_onStateChanged(onStateChanged),
_onTerminated(onTerminated),
_onMessageReceived(onMessageReceived) {
assert(_threads->getNetworkThread()->IsCurrent());
_sctpTransportFactory.reset(new cricket::SctpTransportFactory(_threads->getNetworkThread()));
_sctpTransport = _sctpTransportFactory->CreateSctpTransport(transportChannel);
_sctpTransport->SetDataChannelSink(this);
// TODO: should we disconnect the data channel sink?
webrtc::InternalDataChannelInit dataChannelInit;
dataChannelInit.id = 0;
dataChannelInit.open_handshake_role = isOutgoing ? webrtc::InternalDataChannelInit::kOpener : webrtc::InternalDataChannelInit::kAcker;
_dataChannel = webrtc::SctpDataChannel::Create(
this,
"data",
dataChannelInit,
_threads->getNetworkThread(),
_threads->getNetworkThread()
);
_dataChannel->RegisterObserver(this);
}
SctpDataChannelProviderInterfaceImpl::~SctpDataChannelProviderInterfaceImpl() {
assert(_threads->getNetworkThread()->IsCurrent());
_dataChannel->UnregisterObserver();
_dataChannel->Close();
_dataChannel = nullptr;
_sctpTransport = nullptr;
_sctpTransportFactory.reset();
}
void SctpDataChannelProviderInterfaceImpl::sendDataChannelMessage(std::string const &message) {
assert(_threads->getNetworkThread()->IsCurrent());
if (_isDataChannelOpen) {
RTC_LOG(LS_INFO) << "Outgoing DataChannel message: " << message;
webrtc::DataBuffer buffer(message);
_dataChannel->Send(buffer);
} else {
RTC_LOG(LS_INFO) << "Could not send an outgoing DataChannel message: the channel is not open";
}
}
void SctpDataChannelProviderInterfaceImpl::OnStateChange() {
assert(_threads->getNetworkThread()->IsCurrent());
auto state = _dataChannel->state();
bool isDataChannelOpen = state == webrtc::DataChannelInterface::DataState::kOpen;
if (_isDataChannelOpen != isDataChannelOpen) {
_isDataChannelOpen = isDataChannelOpen;
_onStateChanged(_isDataChannelOpen);
}
}
void SctpDataChannelProviderInterfaceImpl::OnMessage(const webrtc::DataBuffer& buffer) {
assert(_threads->getNetworkThread()->IsCurrent());
if (!buffer.binary) {
std::string messageText(buffer.data.data(), buffer.data.data() + buffer.data.size());
RTC_LOG(LS_INFO) << "Incoming DataChannel message: " << messageText;
_onMessageReceived(messageText);
}
}
void SctpDataChannelProviderInterfaceImpl::updateIsConnected(bool isConnected) {
assert(_threads->getNetworkThread()->IsCurrent());
if (isConnected) {
if (!_isSctpTransportStarted) {
_isSctpTransportStarted = true;
_sctpTransport->Start(5000, 5000, 262144);
}
}
}
void SctpDataChannelProviderInterfaceImpl::OnReadyToSend() {
assert(_threads->getNetworkThread()->IsCurrent());
_dataChannel->OnTransportReady(true);
}
void SctpDataChannelProviderInterfaceImpl::OnTransportClosed(webrtc::RTCError error) {
assert(_threads->getNetworkThread()->IsCurrent());
if (_onTerminated) {
_onTerminated();
}
}
void SctpDataChannelProviderInterfaceImpl::OnDataReceived(int channel_id, webrtc::DataMessageType type, const rtc::CopyOnWriteBuffer& buffer) {
assert(_threads->getNetworkThread()->IsCurrent());
_dataChannel->OnDataReceived(cricket::ReceiveDataParams {
.sid = channel_id,
.type = type
}, buffer);
}
bool SctpDataChannelProviderInterfaceImpl::SendData(
int sid,
const webrtc::SendDataParams& params,
const rtc::CopyOnWriteBuffer& payload,
cricket::SendDataResult* result
) {
assert(_threads->getNetworkThread()->IsCurrent());
return _sctpTransport->SendData(sid, params, payload, result);
}
bool SctpDataChannelProviderInterfaceImpl::ConnectDataChannel(webrtc::SctpDataChannel *data_channel) {
assert(_threads->getNetworkThread()->IsCurrent());
return true;
}
void SctpDataChannelProviderInterfaceImpl::DisconnectDataChannel(webrtc::SctpDataChannel* data_channel) {
assert(_threads->getNetworkThread()->IsCurrent());
return;
}
void SctpDataChannelProviderInterfaceImpl::AddSctpDataStream(int sid) {
assert(_threads->getNetworkThread()->IsCurrent());
_sctpTransport->OpenStream(sid);
}
void SctpDataChannelProviderInterfaceImpl::RemoveSctpDataStream(int sid) {
assert(_threads->getNetworkThread()->IsCurrent());
_threads->getNetworkThread()->BlockingCall([this, sid]() {
_sctpTransport->ResetStream(sid);
});
}
bool SctpDataChannelProviderInterfaceImpl::ReadyToSendData() const {
assert(_threads->getNetworkThread()->IsCurrent());
return _sctpTransport->ReadyToSendData();
}
}