OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/protocol/content_description.h" | 5 #include "remoting/protocol/content_description.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
9 #include "remoting/base/constants.h" | 9 #include "remoting/base/constants.h" |
10 #include "remoting/protocol/authenticator.h" | 10 #include "remoting/protocol/authenticator.h" |
11 #include "remoting/protocol/name_value_map.h" | 11 #include "remoting/protocol/name_value_map.h" |
12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" | 12 #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" |
13 | 13 |
14 using buzz::QName; | 14 using buzz::QName; |
15 using buzz::XmlElement; | 15 using buzz::XmlElement; |
16 | 16 |
17 namespace remoting { | 17 namespace remoting { |
18 namespace protocol { | 18 namespace protocol { |
19 | 19 |
20 const char ContentDescription::kChromotingContentName[] = "chromoting"; | 20 const char ContentDescription::kChromotingContentName[] = "chromoting"; |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 const char kDefaultNs[] = ""; | 24 const char kDefaultNs[] = ""; |
25 | 25 |
26 // Following constants are used to format session description in XML. | 26 // Following constants are used to format session description in XML. |
27 const char kDescriptionTag[] = "description"; | 27 const char kDescriptionTag[] = "description"; |
28 const char kStandardIceTag[] = "standard-ice"; | |
29 const char kControlTag[] = "control"; | 28 const char kControlTag[] = "control"; |
30 const char kEventTag[] = "event"; | 29 const char kEventTag[] = "event"; |
31 const char kVideoTag[] = "video"; | 30 const char kVideoTag[] = "video"; |
32 const char kAudioTag[] = "audio"; | 31 const char kAudioTag[] = "audio"; |
33 const char kDeprecatedResolutionTag[] = "initial-resolution"; | 32 const char kDeprecatedResolutionTag[] = "initial-resolution"; |
34 | 33 |
35 const char kTransportAttr[] = "transport"; | 34 const char kTransportAttr[] = "transport"; |
36 const char kVersionAttr[] = "version"; | 35 const char kVersionAttr[] = "version"; |
37 const char kCodecAttr[] = "codec"; | 36 const char kCodecAttr[] = "codec"; |
38 const char kDeprecatedWidthAttr[] = "width"; | 37 const char kDeprecatedWidthAttr[] = "width"; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 | 114 |
116 ContentDescription::ContentDescription( | 115 ContentDescription::ContentDescription( |
117 scoped_ptr<CandidateSessionConfig> config, | 116 scoped_ptr<CandidateSessionConfig> config, |
118 scoped_ptr<buzz::XmlElement> authenticator_message) | 117 scoped_ptr<buzz::XmlElement> authenticator_message) |
119 : candidate_config_(config.Pass()), | 118 : candidate_config_(config.Pass()), |
120 authenticator_message_(authenticator_message.Pass()) { | 119 authenticator_message_(authenticator_message.Pass()) { |
121 } | 120 } |
122 | 121 |
123 ContentDescription::~ContentDescription() { } | 122 ContentDescription::~ContentDescription() { } |
124 | 123 |
| 124 ContentDescription* ContentDescription::Copy() const { |
| 125 if (!candidate_config_.get() || !authenticator_message_.get()) { |
| 126 return nullptr; |
| 127 } |
| 128 scoped_ptr<XmlElement> message(new XmlElement(*authenticator_message_)); |
| 129 return new ContentDescription(candidate_config_->Clone(), message.Pass()); |
| 130 } |
| 131 |
125 // ToXml() creates content description for chromoting session. The | 132 // ToXml() creates content description for chromoting session. The |
126 // description looks as follows: | 133 // description looks as follows: |
127 // <description xmlns="google:remoting"> | 134 // <description xmlns="google:remoting"> |
128 // <standard-ice/> | |
129 // <control transport="stream" version="1" /> | 135 // <control transport="stream" version="1" /> |
130 // <event transport="datagram" version="1" /> | 136 // <event transport="datagram" version="1" /> |
131 // <video transport="stream" codec="vp8" version="1" /> | 137 // <video transport="stream" codec="vp8" version="1" /> |
132 // <audio transport="stream" codec="opus" version="1" /> | 138 // <audio transport="stream" codec="opus" version="1" /> |
133 // <authentication> | 139 // <authentication> |
134 // Message created by Authenticator implementation. | 140 // Message created by Authenticator implementation. |
135 // </authentication> | 141 // </authentication> |
136 // </description> | 142 // </description> |
137 // | 143 // |
138 XmlElement* ContentDescription::ToXml() const { | 144 XmlElement* ContentDescription::ToXml() const { |
139 XmlElement* root = new XmlElement( | 145 XmlElement* root = new XmlElement( |
140 QName(kChromotingXmlNamespace, kDescriptionTag), true); | 146 QName(kChromotingXmlNamespace, kDescriptionTag), true); |
141 | 147 |
142 if (config()->standard_ice()) { | 148 std::list<ChannelConfig>::const_iterator it; |
143 root->AddElement( | 149 |
144 new buzz::XmlElement(QName(kChromotingXmlNamespace, kStandardIceTag))); | 150 for (it = config()->control_configs().begin(); |
| 151 it != config()->control_configs().end(); ++it) { |
| 152 root->AddElement(FormatChannelConfig(*it, kControlTag)); |
145 } | 153 } |
146 | 154 |
147 for (const ChannelConfig& channel_config : config()->control_configs()) { | 155 for (it = config()->event_configs().begin(); |
148 root->AddElement(FormatChannelConfig(channel_config, kControlTag)); | 156 it != config()->event_configs().end(); ++it) { |
| 157 root->AddElement(FormatChannelConfig(*it, kEventTag)); |
149 } | 158 } |
150 | 159 |
151 for (const ChannelConfig& channel_config : config()->event_configs()) { | 160 for (it = config()->video_configs().begin(); |
152 root->AddElement(FormatChannelConfig(channel_config, kEventTag)); | 161 it != config()->video_configs().end(); ++it) { |
| 162 root->AddElement(FormatChannelConfig(*it, kVideoTag)); |
153 } | 163 } |
154 | 164 |
155 for (const ChannelConfig& channel_config : config()->video_configs()) { | 165 for (it = config()->audio_configs().begin(); |
156 root->AddElement(FormatChannelConfig(channel_config, kVideoTag)); | 166 it != config()->audio_configs().end(); ++it) { |
157 } | 167 ChannelConfig config = *it; |
158 | 168 root->AddElement(FormatChannelConfig(config, kAudioTag)); |
159 for (const ChannelConfig& channel_config : config()->audio_configs()) { | |
160 root->AddElement(FormatChannelConfig(channel_config, kAudioTag)); | |
161 } | 169 } |
162 | 170 |
163 // Older endpoints require an initial-resolution tag, but otherwise ignore it. | 171 // Older endpoints require an initial-resolution tag, but otherwise ignore it. |
164 XmlElement* resolution_tag = new XmlElement( | 172 XmlElement* resolution_tag = new XmlElement( |
165 QName(kChromotingXmlNamespace, kDeprecatedResolutionTag)); | 173 QName(kChromotingXmlNamespace, kDeprecatedResolutionTag)); |
166 resolution_tag->AddAttr(QName(kDefaultNs, kDeprecatedWidthAttr), "640"); | 174 resolution_tag->AddAttr(QName(kDefaultNs, kDeprecatedWidthAttr), "640"); |
167 resolution_tag->AddAttr(QName(kDefaultNs, kDeprecatedHeightAttr), "480"); | 175 resolution_tag->AddAttr(QName(kDefaultNs, kDeprecatedHeightAttr), "480"); |
168 root->AddElement(resolution_tag); | 176 root->AddElement(resolution_tag); |
169 | 177 |
170 if (authenticator_message_.get()) { | 178 if (authenticator_message_.get()) { |
171 DCHECK(Authenticator::IsAuthenticatorMessage(authenticator_message_.get())); | 179 DCHECK(Authenticator::IsAuthenticatorMessage(authenticator_message_.get())); |
172 root->AddElement(new XmlElement(*authenticator_message_)); | 180 root->AddElement(new XmlElement(*authenticator_message_)); |
173 } | 181 } |
174 | 182 |
175 return root; | 183 return root; |
176 } | 184 } |
177 | 185 |
178 // static | 186 // static |
179 // Adds the channel configs corresponding to |tag_name|, | 187 // Adds the channel configs corresponding to |tag_name|, |
180 // found in |element|, to |configs|. | 188 // found in |element|, to |configs|. |
181 bool ContentDescription::ParseChannelConfigs( | 189 bool ContentDescription::ParseChannelConfigs( |
182 const XmlElement* const element, | 190 const XmlElement* const element, |
183 const char tag_name[], | 191 const char tag_name[], |
184 bool codec_required, | 192 bool codec_required, |
185 bool optional, | 193 bool optional, |
186 std::list<ChannelConfig>* const configs) { | 194 std::list<ChannelConfig>* const configs) { |
| 195 |
187 QName tag(kChromotingXmlNamespace, tag_name); | 196 QName tag(kChromotingXmlNamespace, tag_name); |
188 const XmlElement* child = element->FirstNamed(tag); | 197 const XmlElement* child = element->FirstNamed(tag); |
189 while (child) { | 198 while (child) { |
190 ChannelConfig channel_config; | 199 ChannelConfig channel_config; |
191 if (ParseChannelConfig(child, codec_required, &channel_config)) { | 200 if (ParseChannelConfig(child, codec_required, &channel_config)) { |
192 configs->push_back(channel_config); | 201 configs->push_back(channel_config); |
193 } | 202 } |
194 child = child->NextNamed(tag); | 203 child = child->NextNamed(tag); |
195 } | 204 } |
196 if (optional && configs->empty()) { | 205 if (optional && configs->empty()) { |
197 // If there's no mention of the tag, implicitly assume disabled channel. | 206 // If there's no mention of the tag, implicitly assume disabled channel. |
198 configs->push_back(ChannelConfig::None()); | 207 configs->push_back(ChannelConfig::None()); |
199 } | 208 } |
200 return true; | 209 return true; |
201 } | 210 } |
202 | 211 |
203 // static | 212 // static |
204 scoped_ptr<ContentDescription> ContentDescription::ParseXml( | 213 scoped_ptr<ContentDescription> ContentDescription::ParseXml( |
205 const XmlElement* element) { | 214 const XmlElement* element) { |
206 if (element->Name() != QName(kChromotingXmlNamespace, kDescriptionTag)) { | 215 if (element->Name() != QName(kChromotingXmlNamespace, kDescriptionTag)) { |
207 LOG(ERROR) << "Invalid description: " << element->Str(); | 216 LOG(ERROR) << "Invalid description: " << element->Str(); |
208 return nullptr; | 217 return nullptr; |
209 } | 218 } |
210 scoped_ptr<CandidateSessionConfig> config( | 219 scoped_ptr<CandidateSessionConfig> config( |
211 CandidateSessionConfig::CreateEmpty()); | 220 CandidateSessionConfig::CreateEmpty()); |
212 | |
213 config->set_standard_ice( | |
214 element->FirstNamed(QName(kChromotingXmlNamespace, kStandardIceTag)) != | |
215 nullptr); | |
216 | |
217 if (!ParseChannelConfigs(element, kControlTag, false, false, | 221 if (!ParseChannelConfigs(element, kControlTag, false, false, |
218 config->mutable_control_configs()) || | 222 config->mutable_control_configs()) || |
219 !ParseChannelConfigs(element, kEventTag, false, false, | 223 !ParseChannelConfigs(element, kEventTag, false, false, |
220 config->mutable_event_configs()) || | 224 config->mutable_event_configs()) || |
221 !ParseChannelConfigs(element, kVideoTag, true, false, | 225 !ParseChannelConfigs(element, kVideoTag, true, false, |
222 config->mutable_video_configs()) || | 226 config->mutable_video_configs()) || |
223 !ParseChannelConfigs(element, kAudioTag, true, true, | 227 !ParseChannelConfigs(element, kAudioTag, true, true, |
224 config->mutable_audio_configs())) { | 228 config->mutable_audio_configs())) { |
225 return nullptr; | 229 return nullptr; |
226 } | 230 } |
227 | 231 |
228 scoped_ptr<XmlElement> authenticator_message; | 232 scoped_ptr<XmlElement> authenticator_message; |
229 const XmlElement* child = Authenticator::FindAuthenticatorMessage(element); | 233 const XmlElement* child = Authenticator::FindAuthenticatorMessage(element); |
230 if (child) | 234 if (child) |
231 authenticator_message.reset(new XmlElement(*child)); | 235 authenticator_message.reset(new XmlElement(*child)); |
232 | 236 |
233 return make_scoped_ptr( | 237 return make_scoped_ptr( |
234 new ContentDescription(config.Pass(), authenticator_message.Pass())); | 238 new ContentDescription(config.Pass(), authenticator_message.Pass())); |
235 } | 239 } |
236 | 240 |
237 } // namespace protocol | 241 } // namespace protocol |
238 } // namespace remoting | 242 } // namespace remoting |
OLD | NEW |