1 /*
2  *  Copyright 2019 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "pc/composite_data_channel_transport.h"
12 
13 #include <utility>
14 
15 #include "absl/algorithm/container.h"
16 
17 namespace webrtc {
18 
CompositeDataChannelTransport(std::vector<DataChannelTransportInterface * > transports)19 CompositeDataChannelTransport::CompositeDataChannelTransport(
20     std::vector<DataChannelTransportInterface*> transports)
21     : transports_(std::move(transports)) {
22   for (auto transport : transports_) {
23     transport->SetDataSink(this);
24   }
25 }
26 
~CompositeDataChannelTransport()27 CompositeDataChannelTransport::~CompositeDataChannelTransport() {
28   for (auto transport : transports_) {
29     transport->SetDataSink(nullptr);
30   }
31 }
32 
SetSendTransport(DataChannelTransportInterface * send_transport)33 void CompositeDataChannelTransport::SetSendTransport(
34     DataChannelTransportInterface* send_transport) {
35   if (!absl::c_linear_search(transports_, send_transport)) {
36     return;
37   }
38   send_transport_ = send_transport;
39   // NB:  OnReadyToSend() checks if we're actually ready to send, and signals
40   // |sink_| if appropriate.  This signal is required upon setting the sink.
41   OnReadyToSend();
42 }
43 
RemoveTransport(DataChannelTransportInterface * transport)44 void CompositeDataChannelTransport::RemoveTransport(
45     DataChannelTransportInterface* transport) {
46   RTC_DCHECK(transport != send_transport_) << "Cannot remove send transport";
47 
48   auto it = absl::c_find(transports_, transport);
49   if (it == transports_.end()) {
50     return;
51   }
52 
53   transport->SetDataSink(nullptr);
54   transports_.erase(it);
55 }
56 
OpenChannel(int channel_id)57 RTCError CompositeDataChannelTransport::OpenChannel(int channel_id) {
58   RTCError error = RTCError::OK();
59   for (auto transport : transports_) {
60     RTCError e = transport->OpenChannel(channel_id);
61     if (!e.ok()) {
62       error = std::move(e);
63     }
64   }
65   return error;
66 }
67 
SendData(int channel_id,const SendDataParams & params,const rtc::CopyOnWriteBuffer & buffer)68 RTCError CompositeDataChannelTransport::SendData(
69     int channel_id,
70     const SendDataParams& params,
71     const rtc::CopyOnWriteBuffer& buffer) {
72   if (send_transport_) {
73     return send_transport_->SendData(channel_id, params, buffer);
74   }
75   return RTCError(RTCErrorType::NETWORK_ERROR, "Send transport is not ready");
76 }
77 
CloseChannel(int channel_id)78 RTCError CompositeDataChannelTransport::CloseChannel(int channel_id) {
79   if (send_transport_) {
80     return send_transport_->CloseChannel(channel_id);
81   }
82   return RTCError(RTCErrorType::NETWORK_ERROR, "Send transport is not ready");
83 }
84 
SetDataSink(DataChannelSink * sink)85 void CompositeDataChannelTransport::SetDataSink(DataChannelSink* sink) {
86   sink_ = sink;
87   // NB:  OnReadyToSend() checks if we're actually ready to send, and signals
88   // |sink_| if appropriate.  This signal is required upon setting the sink.
89   OnReadyToSend();
90 }
91 
IsReadyToSend() const92 bool CompositeDataChannelTransport::IsReadyToSend() const {
93   return send_transport_ && send_transport_->IsReadyToSend();
94 }
95 
OnDataReceived(int channel_id,DataMessageType type,const rtc::CopyOnWriteBuffer & buffer)96 void CompositeDataChannelTransport::OnDataReceived(
97     int channel_id,
98     DataMessageType type,
99     const rtc::CopyOnWriteBuffer& buffer) {
100   if (sink_) {
101     sink_->OnDataReceived(channel_id, type, buffer);
102   }
103 }
104 
OnChannelClosing(int channel_id)105 void CompositeDataChannelTransport::OnChannelClosing(int channel_id) {
106   if (sink_) {
107     sink_->OnChannelClosing(channel_id);
108   }
109 }
110 
OnChannelClosed(int channel_id)111 void CompositeDataChannelTransport::OnChannelClosed(int channel_id) {
112   if (sink_) {
113     sink_->OnChannelClosed(channel_id);
114   }
115 }
116 
OnReadyToSend()117 void CompositeDataChannelTransport::OnReadyToSend() {
118   if (sink_ && send_transport_ && send_transport_->IsReadyToSend()) {
119     sink_->OnReadyToSend();
120   }
121 }
122 
123 }  // namespace webrtc
124