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. 4 5#include "remoting/protocol/session_config.h" 6 7#include <algorithm> 8 9namespace remoting { 10namespace protocol { 11 12const int kDefaultStreamVersion = 2; 13 14// The control channel version that supports the "capabilities" message. 15const int kControlStreamVersion = 3; 16const int kControlStreamVersionNoCapabilities = kDefaultStreamVersion; 17 18ChannelConfig ChannelConfig::None() { 19 return ChannelConfig(); 20} 21 22ChannelConfig::ChannelConfig() 23 : transport(TRANSPORT_NONE), 24 version(0), 25 codec(CODEC_UNDEFINED) { 26} 27 28ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec) 29 : transport(transport), 30 version(version), 31 codec(codec) { 32} 33 34bool ChannelConfig::operator==(const ChannelConfig& b) const { 35 // If the transport field is set to NONE then all other fields are irrelevant. 36 if (transport == ChannelConfig::TRANSPORT_NONE) 37 return transport == b.transport; 38 return transport == b.transport && version == b.version && codec == b.codec; 39} 40 41SessionConfig::SessionConfig() { 42} 43 44bool SessionConfig::SupportsCapabilities() const { 45 return control_config_.version >= kControlStreamVersion; 46} 47 48// static 49SessionConfig SessionConfig::ForTest() { 50 SessionConfig result; 51 result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 52 kControlStreamVersionNoCapabilities, 53 ChannelConfig::CODEC_UNDEFINED)); 54 result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 55 kDefaultStreamVersion, 56 ChannelConfig::CODEC_UNDEFINED)); 57 result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 58 kDefaultStreamVersion, 59 ChannelConfig::CODEC_VP8)); 60 result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE, 61 kDefaultStreamVersion, 62 ChannelConfig::CODEC_VERBATIM)); 63 return result; 64} 65 66CandidateSessionConfig::CandidateSessionConfig() { } 67 68CandidateSessionConfig::CandidateSessionConfig( 69 const CandidateSessionConfig& config) 70 : control_configs_(config.control_configs_), 71 event_configs_(config.event_configs_), 72 video_configs_(config.video_configs_), 73 audio_configs_(config.audio_configs_) { 74} 75 76CandidateSessionConfig::~CandidateSessionConfig() { } 77 78bool CandidateSessionConfig::Select( 79 const CandidateSessionConfig* client_config, 80 SessionConfig* result) { 81 ChannelConfig control_config; 82 ChannelConfig event_config; 83 ChannelConfig video_config; 84 ChannelConfig audio_config; 85 86 if (!SelectCommonChannelConfig( 87 control_configs_, client_config->control_configs_, &control_config) || 88 !SelectCommonChannelConfig( 89 event_configs_, client_config->event_configs_, &event_config) || 90 !SelectCommonChannelConfig( 91 video_configs_, client_config->video_configs_, &video_config) || 92 !SelectCommonChannelConfig( 93 audio_configs_, client_config->audio_configs_, &audio_config)) { 94 return false; 95 } 96 97 result->set_control_config(control_config); 98 result->set_event_config(event_config); 99 result->set_video_config(video_config); 100 result->set_audio_config(audio_config); 101 102 return true; 103} 104 105bool CandidateSessionConfig::IsSupported( 106 const SessionConfig& config) const { 107 return 108 IsChannelConfigSupported(control_configs_, config.control_config()) && 109 IsChannelConfigSupported(event_configs_, config.event_config()) && 110 IsChannelConfigSupported(video_configs_, config.video_config()) && 111 IsChannelConfigSupported(audio_configs_, config.audio_config()); 112} 113 114bool CandidateSessionConfig::GetFinalConfig(SessionConfig* result) const { 115 if (control_configs_.size() != 1 || 116 event_configs_.size() != 1 || 117 video_configs_.size() != 1 || 118 audio_configs_.size() != 1) { 119 return false; 120 } 121 122 result->set_control_config(control_configs_.front()); 123 result->set_event_config(event_configs_.front()); 124 result->set_video_config(video_configs_.front()); 125 result->set_audio_config(audio_configs_.front()); 126 127 return true; 128} 129 130// static 131bool CandidateSessionConfig::SelectCommonChannelConfig( 132 const std::vector<ChannelConfig>& host_configs, 133 const std::vector<ChannelConfig>& client_configs, 134 ChannelConfig* config) { 135 // Usually each of these vectors will contain just several elements, 136 // so iterating over all of them is not a problem. 137 std::vector<ChannelConfig>::const_iterator it; 138 for (it = client_configs.begin(); it != client_configs.end(); ++it) { 139 if (IsChannelConfigSupported(host_configs, *it)) { 140 *config = *it; 141 return true; 142 } 143 } 144 return false; 145} 146 147// static 148bool CandidateSessionConfig::IsChannelConfigSupported( 149 const std::vector<ChannelConfig>& vector, 150 const ChannelConfig& value) { 151 return std::find(vector.begin(), vector.end(), value) != vector.end(); 152} 153 154scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const { 155 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this)); 156} 157 158// static 159scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() { 160 return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig()); 161} 162 163// static 164scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom( 165 const SessionConfig& config) { 166 scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); 167 result->mutable_control_configs()->push_back(config.control_config()); 168 result->mutable_event_configs()->push_back(config.event_config()); 169 result->mutable_video_configs()->push_back(config.video_config()); 170 result->mutable_audio_configs()->push_back(config.audio_config()); 171 return result.Pass(); 172} 173 174// static 175scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() { 176 scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); 177 178 // Control channel. 179 result->mutable_control_configs()->push_back( 180 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 181 kControlStreamVersion, 182 ChannelConfig::CODEC_UNDEFINED)); 183 result->mutable_control_configs()->push_back( 184 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 185 kControlStreamVersionNoCapabilities, 186 ChannelConfig::CODEC_UNDEFINED)); 187 result->mutable_control_configs()->push_back( 188 ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 189 kControlStreamVersionNoCapabilities, 190 ChannelConfig::CODEC_UNDEFINED)); 191 192 // Event channel. 193 result->mutable_event_configs()->push_back( 194 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 195 kDefaultStreamVersion, 196 ChannelConfig::CODEC_UNDEFINED)); 197 result->mutable_event_configs()->push_back( 198 ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 199 kDefaultStreamVersion, 200 ChannelConfig::CODEC_UNDEFINED)); 201 202 // Video channel. 203 result->mutable_video_configs()->push_back( 204 ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 205 kDefaultStreamVersion, 206 ChannelConfig::CODEC_VP8)); 207 208 // Audio channel. 209 result->mutable_audio_configs()->push_back( 210 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 211 kDefaultStreamVersion, 212 ChannelConfig::CODEC_OPUS)); 213 result->mutable_audio_configs()->push_back( 214 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 215 kDefaultStreamVersion, 216 ChannelConfig::CODEC_SPEEX)); 217 result->mutable_audio_configs()->push_back( 218 ChannelConfig(ChannelConfig::TRANSPORT_STREAM, 219 kDefaultStreamVersion, 220 ChannelConfig::CODEC_SPEEX)); 221 result->mutable_audio_configs()->push_back( 222 ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, 223 kDefaultStreamVersion, 224 ChannelConfig::CODEC_VERBATIM)); 225 result->mutable_audio_configs()->push_back(ChannelConfig::None()); 226 227 return result.Pass(); 228} 229 230// static 231void CandidateSessionConfig::DisableAudioChannel( 232 CandidateSessionConfig* config) { 233 config->mutable_audio_configs()->clear(); 234 config->mutable_audio_configs()->push_back(ChannelConfig()); 235} 236 237} // namespace protocol 238} // namespace remoting 239