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"
10 #include "base/logging.h"
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
)) {
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
44 return a
.transport
== transport
&&
45 b
.transport
!= transport
;
47 configs
->assign(sorted
.begin(), sorted
.end());
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
),
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
;
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())
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
;
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_
)) {
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) {
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();
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));
182 scoped_ptr
<CandidateSessionConfig
> CandidateSessionConfig::CreateEmpty() {
183 return make_scoped_ptr(new CandidateSessionConfig());
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();
199 scoped_ptr
<CandidateSessionConfig
> CandidateSessionConfig::CreateDefault() {
200 scoped_ptr
<CandidateSessionConfig
> result
= CreateEmpty();
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
));
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
));
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
));
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