Home | History | Annotate | Download | only in protocol
      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 
      9 namespace remoting {
     10 namespace protocol {
     11 
     12 const int kDefaultStreamVersion = 2;
     13 
     14 // The control channel version that supports the "capabilities" message.
     15 const int kControlStreamVersion = 3;
     16 const int kControlStreamVersionNoCapabilities = kDefaultStreamVersion;
     17 
     18 ChannelConfig ChannelConfig::None() {
     19   return ChannelConfig();
     20 }
     21 
     22 ChannelConfig::ChannelConfig()
     23     : transport(TRANSPORT_NONE),
     24       version(0),
     25       codec(CODEC_UNDEFINED) {
     26 }
     27 
     28 ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec)
     29     : transport(transport),
     30       version(version),
     31       codec(codec) {
     32 }
     33 
     34 bool 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 
     41 SessionConfig::SessionConfig() {
     42 }
     43 
     44 bool SessionConfig::SupportsCapabilities() const {
     45   return control_config_.version >= kControlStreamVersion;
     46 }
     47 
     48 // static
     49 SessionConfig 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 
     66 CandidateSessionConfig::CandidateSessionConfig() { }
     67 
     68 CandidateSessionConfig::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 
     76 CandidateSessionConfig::~CandidateSessionConfig() { }
     77 
     78 bool 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 
    105 bool 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 
    114 bool 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
    131 bool 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
    148 bool 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 
    154 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const {
    155   return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig(*this));
    156 }
    157 
    158 // static
    159 scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateEmpty() {
    160   return scoped_ptr<CandidateSessionConfig>(new CandidateSessionConfig());
    161 }
    162 
    163 // static
    164 scoped_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
    175 scoped_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
    231 void 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