OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright 2016 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 "webrtc/api/quicdatatransport.h" | |
12 | |
13 #include "webrtc/base/bind.h" | |
14 #include "webrtc/base/logging.h" | |
15 #include "webrtc/p2p/quic/quictransportchannel.h" | |
16 #include "webrtc/p2p/quic/reliablequicstream.h" | |
17 | |
18 namespace webrtc { | |
19 | |
20 QuicDataTransport::QuicDataTransport( | |
21 rtc::Thread* signaling_thread, | |
22 rtc::Thread* worker_thread, | |
23 rtc::Thread* network_thread, | |
24 cricket::TransportController* transport_controller) | |
25 : signaling_thread_(signaling_thread), | |
26 worker_thread_(worker_thread), | |
27 network_thread_(network_thread), | |
28 transport_controller_(transport_controller) { | |
29 RTC_DCHECK(signaling_thread_); | |
30 RTC_DCHECK(worker_thread_); | |
31 RTC_DCHECK(network_thread_); | |
32 } | |
33 | |
34 QuicDataTransport::~QuicDataTransport() { | |
35 DestroyTransportChannel(quic_transport_channel_); | |
36 LOG(LS_INFO) << "Destroyed the QUIC data transport."; | |
37 } | |
38 | |
39 bool QuicDataTransport::SetTransport(const std::string& transport_name) { | |
40 if (transport_name_ == transport_name) { | |
41 // Nothing to do if transport name isn't changing | |
42 return true; | |
43 } | |
44 | |
45 cricket::QuicTransportChannel* transport_channel = | |
46 CreateTransportChannel(transport_name); | |
47 if (!SetTransportChannel(transport_channel)) { | |
48 DestroyTransportChannel(transport_channel); | |
49 return false; | |
50 } | |
51 | |
52 transport_name_ = transport_name; | |
53 return true; | |
54 } | |
55 | |
56 bool QuicDataTransport::SetTransportChannel( | |
57 cricket::QuicTransportChannel* channel) { | |
58 if (!channel) { | |
59 LOG(LS_ERROR) << "|channel| is NULL. Cannot set transport channel."; | |
60 return false; | |
61 } | |
62 if (quic_transport_channel_) { | |
63 if (channel == quic_transport_channel_) { | |
64 LOG(LS_WARNING) << "Ignoring duplicate transport channel."; | |
65 return true; | |
66 } | |
67 LOG(LS_ERROR) << "|channel| does not match existing transport channel."; | |
68 return false; | |
69 } | |
70 | |
71 LOG(LS_INFO) << "Setting QuicTransportChannel for QuicDataTransport"; | |
72 quic_transport_channel_ = channel; | |
73 quic_transport_channel_->SignalIncomingStream.connect( | |
74 this, &QuicDataTransport::OnIncomingStream); | |
75 bool success = true; | |
76 for (const auto& kv : data_channel_by_id_) { | |
77 rtc::scoped_refptr<QuicDataChannel> data_channel = kv.second; | |
78 if (!data_channel->SetTransportChannel(quic_transport_channel_)) { | |
79 LOG(LS_ERROR) | |
80 << "Cannot set QUIC transport channel for QUIC data channel " | |
81 << kv.first; | |
82 success = false; | |
83 } | |
84 } | |
85 return success; | |
86 } | |
87 | |
88 rtc::scoped_refptr<DataChannelInterface> QuicDataTransport::CreateDataChannel( | |
89 const std::string& label, | |
90 const DataChannelInit* config) { | |
91 if (config == nullptr) { | |
92 return nullptr; | |
93 } | |
94 if (data_channel_by_id_.find(config->id) != data_channel_by_id_.end()) { | |
95 LOG(LS_ERROR) << "QUIC data channel already exists with id " << config->id; | |
96 return nullptr; | |
97 } | |
98 rtc::scoped_refptr<QuicDataChannel> data_channel(new QuicDataChannel( | |
99 signaling_thread_, worker_thread_, network_thread_, label, *config)); | |
100 if (quic_transport_channel_) { | |
101 if (!data_channel->SetTransportChannel(quic_transport_channel_)) { | |
102 LOG(LS_ERROR) | |
103 << "Cannot set QUIC transport channel for QUIC data channel " | |
104 << config->id; | |
105 } | |
106 } | |
107 | |
108 data_channel_by_id_[data_channel->id()] = data_channel; | |
109 return data_channel; | |
110 } | |
111 | |
112 void QuicDataTransport::DestroyDataChannel(int id) { | |
113 data_channel_by_id_.erase(id); | |
114 } | |
115 | |
116 bool QuicDataTransport::HasDataChannel(int id) const { | |
117 return data_channel_by_id_.find(id) != data_channel_by_id_.end(); | |
118 } | |
119 | |
120 bool QuicDataTransport::HasDataChannels() const { | |
121 return !data_channel_by_id_.empty(); | |
122 } | |
123 | |
124 // Called when a QUIC stream is created for incoming data. | |
125 void QuicDataTransport::OnIncomingStream(cricket::ReliableQuicStream* stream) { | |
126 RTC_DCHECK(stream != nullptr); | |
127 quic_stream_by_id_[stream->id()] = stream; | |
128 stream->SignalDataReceived.connect(this, &QuicDataTransport::OnDataReceived); | |
129 } | |
130 | |
131 // Called when the first QUIC stream frame is received for incoming data. | |
132 void QuicDataTransport::OnDataReceived(net::QuicStreamId id, | |
133 const char* data, | |
134 size_t len) { | |
135 const auto& quic_stream_kv = quic_stream_by_id_.find(id); | |
136 if (quic_stream_kv == quic_stream_by_id_.end()) { | |
137 RTC_NOTREACHED(); | |
138 return; | |
139 } | |
140 cricket::ReliableQuicStream* stream = quic_stream_kv->second; | |
141 stream->SignalDataReceived.disconnect(this); | |
142 quic_stream_by_id_.erase(id); | |
143 // Read the data channel ID and message ID. | |
144 int data_channel_id; | |
145 uint64_t message_id; | |
146 size_t bytes_read; | |
147 if (!ParseQuicDataMessageHeader(data, len, &data_channel_id, &message_id, | |
148 &bytes_read)) { | |
149 LOG(LS_ERROR) << "Could not read QUIC message header from QUIC stream " | |
150 << id; | |
151 return; | |
152 } | |
153 data += bytes_read; | |
154 len -= bytes_read; | |
155 // Retrieve the data channel which will handle the message. | |
156 const auto& data_channel_kv = data_channel_by_id_.find(data_channel_id); | |
157 if (data_channel_kv == data_channel_by_id_.end()) { | |
158 // TODO(mikescarlett): Implement OPEN message to create a new | |
159 // QuicDataChannel when messages are received for a nonexistent ID. | |
160 LOG(LS_ERROR) << "Data was received for QUIC data channel " | |
161 << data_channel_id | |
162 << " but it is not registered to the QuicDataTransport."; | |
163 return; | |
164 } | |
165 QuicDataChannel* data_channel = data_channel_kv->second; | |
166 QuicDataChannel::Message message; | |
167 message.id = message_id; | |
168 message.buffer = rtc::CopyOnWriteBuffer(data, len); | |
169 message.stream = stream; | |
170 data_channel->OnIncomingMessage(std::move(message)); | |
171 } | |
172 | |
173 cricket::QuicTransportChannel* QuicDataTransport::CreateTransportChannel( | |
174 const std::string& transport_name) { | |
175 DCHECK(transport_controller_->quic()); | |
176 | |
177 cricket::TransportChannel* transport_channel = | |
178 network_thread_->Invoke<cricket::TransportChannel*>( | |
179 RTC_FROM_HERE, | |
180 rtc::Bind(&cricket::TransportController::CreateTransportChannel_n, | |
181 transport_controller_, transport_name, | |
182 cricket::ICE_CANDIDATE_COMPONENT_DEFAULT)); | |
183 return static_cast<cricket::QuicTransportChannel*>(transport_channel); | |
184 } | |
185 | |
186 void QuicDataTransport::DestroyTransportChannel( | |
187 cricket::TransportChannel* transport_channel) { | |
188 if (transport_channel) { | |
189 network_thread_->Invoke<void>( | |
190 RTC_FROM_HERE, | |
191 rtc::Bind(&cricket::TransportController::DestroyTransportChannel_n, | |
192 transport_controller_, transport_channel->transport_name(), | |
193 cricket::ICE_CANDIDATE_COMPONENT_DEFAULT)); | |
194 } | |
195 } | |
196 | |
197 } // namespace webrtc | |
OLD | NEW |