MD Downloads: prevent search text from overlapping with the cancel search (X)
[chromium-blink-merge.git] / remoting / protocol / session_config.cc
blob9034ceab5add0ecf07e15d995afc01a95ae49346
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/protocol/session_config.h"
7 #include <algorithm>
8 #include <vector>
10 #include "base/logging.h"
12 namespace remoting {
13 namespace protocol {
15 namespace {
17 bool IsChannelConfigSupported(const std::list<ChannelConfig>& list,
18 const ChannelConfig& value) {
19 return std::find(list.begin(), list.end(), value) != list.end();
22 bool SelectCommonChannelConfig(const std::list<ChannelConfig>& host_configs,
23 const std::list<ChannelConfig>& client_configs,
24 ChannelConfig* config) {
25 // Usually each of these lists will contain just a few elements, so iterating
26 // over all of them is not a problem.
27 std::list<ChannelConfig>::const_iterator it;
28 for (it = client_configs.begin(); it != client_configs.end(); ++it) {
29 if (IsChannelConfigSupported(host_configs, *it)) {
30 *config = *it;
31 return true;
34 return false;
37 void UpdateConfigListToPreferTransport(std::list<ChannelConfig>* configs,
38 ChannelConfig::TransportType transport) {
39 std::vector<ChannelConfig> sorted(configs->begin(), configs->end());
40 std::stable_sort(sorted.begin(), sorted.end(),
41 [transport](const ChannelConfig& a, const ChannelConfig& b) {
42 // |a| must precede |b| if |a| uses preferred transport and
43 // |b| doesn't.
44 return a.transport == transport &&
45 b.transport != transport;
46 });
47 configs->assign(sorted.begin(), sorted.end());
50 } // namespace
52 const int kDefaultStreamVersion = 2;
53 const int kControlStreamVersion = 3;
55 ChannelConfig ChannelConfig::None() {
56 return ChannelConfig();
59 ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
60 : transport(transport),
61 version(version),
62 codec(codec) {
65 bool ChannelConfig::operator==(const ChannelConfig& b) const {
66 // If the transport field is set to NONE then all other fields are irrelevant.
67 if (transport == ChannelConfig::TRANSPORT_NONE)
68 return transport == b.transport;
69 return transport == b.transport && version == b.version && codec == b.codec;
72 // static
73 scoped_ptr<SessionConfig> SessionConfig::SelectCommon(
74 const CandidateSessionConfig* client_config,
75 const CandidateSessionConfig* host_config) {
76 scoped_ptr<SessionConfig> result(new SessionConfig());
77 ChannelConfig control_config;
78 ChannelConfig event_config;
79 ChannelConfig video_config;
80 ChannelConfig audio_config;
82 DCHECK(host_config->standard_ice());
84 // Reject connection if the peer doesn't support ICE.
85 if (!client_config->standard_ice())
86 return nullptr;
88 // If neither host nor the client have VP9 experiment enabled then remove it
89 // from the list of host video configs.
90 std::list<ChannelConfig> host_video_configs = host_config->video_configs();
91 if (!client_config->vp9_experiment_enabled() &&
92 !host_config->vp9_experiment_enabled()) {
93 host_video_configs.remove_if([](const ChannelConfig& config) {
94 return config.codec == ChannelConfig::CODEC_VP9;
95 });
98 if (!SelectCommonChannelConfig(host_config->control_configs(),
99 client_config->control_configs(),
100 &result->control_config_) ||
101 !SelectCommonChannelConfig(host_config->event_configs(),
102 client_config->event_configs(),
103 &result->event_config_) ||
104 !SelectCommonChannelConfig(host_video_configs,
105 client_config->video_configs(),
106 &result->video_config_) ||
107 !SelectCommonChannelConfig(host_config->audio_configs(),
108 client_config->audio_configs(),
109 &result->audio_config_)) {
110 return nullptr;
113 return result;
116 // static
117 scoped_ptr<SessionConfig> SessionConfig::GetFinalConfig(
118 const CandidateSessionConfig* candidate_config) {
119 if (candidate_config->control_configs().size() != 1 ||
120 candidate_config->event_configs().size() != 1 ||
121 candidate_config->video_configs().size() != 1 ||
122 candidate_config->audio_configs().size() != 1) {
123 return nullptr;
126 scoped_ptr<SessionConfig> result(new SessionConfig());
127 result->standard_ice_ = candidate_config->standard_ice();
128 result->control_config_ = candidate_config->control_configs().front();
129 result->event_config_ = candidate_config->event_configs().front();
130 result->video_config_ = candidate_config->video_configs().front();
131 result->audio_config_ = candidate_config->audio_configs().front();
133 return result.Pass();
136 // static
137 scoped_ptr<SessionConfig> SessionConfig::ForTest() {
138 scoped_ptr<SessionConfig> result(new SessionConfig());
139 result->control_config_ = ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
140 kControlStreamVersion,
141 ChannelConfig::CODEC_UNDEFINED);
142 result->event_config_ = ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
143 kDefaultStreamVersion,
144 ChannelConfig::CODEC_UNDEFINED);
145 result->video_config_ = ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
146 kDefaultStreamVersion,
147 ChannelConfig::CODEC_VP8);
148 result->audio_config_ = ChannelConfig(ChannelConfig::TRANSPORT_NONE,
149 kDefaultStreamVersion,
150 ChannelConfig::CODEC_UNDEFINED);
151 return result.Pass();
154 scoped_ptr<SessionConfig> SessionConfig::ForTestWithVerbatimVideo() {
155 scoped_ptr<SessionConfig> result = ForTest();
156 result->video_config_ = ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
157 kDefaultStreamVersion,
158 ChannelConfig::CODEC_VERBATIM);
159 return result.Pass();
162 SessionConfig::SessionConfig() {}
164 CandidateSessionConfig::CandidateSessionConfig() {}
165 CandidateSessionConfig::CandidateSessionConfig(
166 const CandidateSessionConfig& config) = default;
167 CandidateSessionConfig::~CandidateSessionConfig() {}
169 bool CandidateSessionConfig::IsSupported(const SessionConfig& config) const {
170 return config.standard_ice() &&
171 IsChannelConfigSupported(control_configs_, config.control_config()) &&
172 IsChannelConfigSupported(event_configs_, config.event_config()) &&
173 IsChannelConfigSupported(video_configs_, config.video_config()) &&
174 IsChannelConfigSupported(audio_configs_, config.audio_config());
177 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
178 return make_scoped_ptr(new CandidateSessionConfig(*this));
181 // static
182 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
183 return make_scoped_ptr(new CandidateSessionConfig());
186 // static
187 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom(
188 const SessionConfig& config) {
189 scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
190 result->set_standard_ice(config.standard_ice());
191 result->mutable_control_configs()->push_back(config.control_config());
192 result->mutable_event_configs()->push_back(config.event_config());
193 result->mutable_video_configs()->push_back(config.video_config());
194 result->mutable_audio_configs()->push_back(config.audio_config());
195 return result.Pass();
198 // static
199 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() {
200 scoped_ptr<CandidateSessionConfig> result = CreateEmpty();
202 // Control channel.
203 result->mutable_control_configs()->push_back(
204 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
205 kControlStreamVersion,
206 ChannelConfig::CODEC_UNDEFINED));
207 result->mutable_control_configs()->push_back(
208 ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
209 kControlStreamVersion,
210 ChannelConfig::CODEC_UNDEFINED));
212 // Event channel.
213 result->mutable_event_configs()->push_back(
214 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
215 kDefaultStreamVersion,
216 ChannelConfig::CODEC_UNDEFINED));
217 result->mutable_event_configs()->push_back(
218 ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
219 kDefaultStreamVersion,
220 ChannelConfig::CODEC_UNDEFINED));
222 // Video channel.
223 result->mutable_video_configs()->push_back(
224 ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
225 kDefaultStreamVersion,
226 ChannelConfig::CODEC_VP9));
227 result->mutable_video_configs()->push_back(
228 ChannelConfig(ChannelConfig::TRANSPORT_STREAM,
229 kDefaultStreamVersion,
230 ChannelConfig::CODEC_VP8));
231 result->mutable_video_configs()->push_back(
232 ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
233 kDefaultStreamVersion,
234 ChannelConfig::CODEC_VP9));
235 result->mutable_video_configs()->push_back(
236 ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
237 kDefaultStreamVersion,
238 ChannelConfig::CODEC_VP8));
240 // Audio channel.
241 result->mutable_audio_configs()->push_back(
242 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
243 kDefaultStreamVersion,
244 ChannelConfig::CODEC_OPUS));
245 result->mutable_audio_configs()->push_back(
246 ChannelConfig(ChannelConfig::TRANSPORT_QUIC_STREAM,
247 kDefaultStreamVersion,
248 ChannelConfig::CODEC_OPUS));
249 result->mutable_audio_configs()->push_back(ChannelConfig::None());
251 return result.Pass();
254 void CandidateSessionConfig::DisableAudioChannel() {
255 mutable_audio_configs()->clear();
256 mutable_audio_configs()->push_back(ChannelConfig());
259 void CandidateSessionConfig::PreferTransport(
260 ChannelConfig::TransportType transport) {
261 UpdateConfigListToPreferTransport(&control_configs_, transport);
262 UpdateConfigListToPreferTransport(&event_configs_, transport);
263 UpdateConfigListToPreferTransport(&video_configs_, transport);
264 UpdateConfigListToPreferTransport(&audio_configs_, transport);
267 } // namespace protocol
268 } // namespace remoting