Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: webrtc/libjingle/session/sessionmessages.cc

Issue 1175243003: Remove webrtc/libjingle/{examples,session}. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/libjingle/session/sessionmessages.h ('k') | webrtc/libjingle/session/sessionsendtask.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2010 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/libjingle/session/sessionmessages.h"
12
13 #include <stdio.h>
14 #include <string>
15
16 #include "webrtc/base/logging.h"
17 #include "webrtc/base/scoped_ptr.h"
18 #include "webrtc/base/stringutils.h"
19 #include "webrtc/libjingle/session/parsing.h"
20 #include "webrtc/libjingle/session/sessionclient.h"
21 #include "webrtc/libjingle/xmllite/xmlconstants.h"
22 #include "webrtc/libjingle/xmpp/constants.h"
23 #include "webrtc/p2p/base/constants.h"
24 #include "webrtc/p2p/base/p2ptransport.h"
25 #include "webrtc/p2p/base/sessiondescription.h"
26 #include "webrtc/p2p/base/transport.h"
27
28 namespace cricket {
29
30 ActionType ToActionType(const std::string& type) {
31 if (type == GINGLE_ACTION_INITIATE)
32 return ACTION_SESSION_INITIATE;
33 if (type == GINGLE_ACTION_INFO)
34 return ACTION_SESSION_INFO;
35 if (type == GINGLE_ACTION_ACCEPT)
36 return ACTION_SESSION_ACCEPT;
37 if (type == GINGLE_ACTION_REJECT)
38 return ACTION_SESSION_REJECT;
39 if (type == GINGLE_ACTION_TERMINATE)
40 return ACTION_SESSION_TERMINATE;
41 if (type == GINGLE_ACTION_CANDIDATES)
42 return ACTION_TRANSPORT_INFO;
43 if (type == JINGLE_ACTION_SESSION_INITIATE)
44 return ACTION_SESSION_INITIATE;
45 if (type == JINGLE_ACTION_TRANSPORT_INFO)
46 return ACTION_TRANSPORT_INFO;
47 if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
48 return ACTION_TRANSPORT_ACCEPT;
49 if (type == JINGLE_ACTION_SESSION_INFO)
50 return ACTION_SESSION_INFO;
51 if (type == JINGLE_ACTION_SESSION_ACCEPT)
52 return ACTION_SESSION_ACCEPT;
53 if (type == JINGLE_ACTION_SESSION_TERMINATE)
54 return ACTION_SESSION_TERMINATE;
55 if (type == JINGLE_ACTION_TRANSPORT_INFO)
56 return ACTION_TRANSPORT_INFO;
57 if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
58 return ACTION_TRANSPORT_ACCEPT;
59 if (type == JINGLE_ACTION_DESCRIPTION_INFO)
60 return ACTION_DESCRIPTION_INFO;
61 if (type == GINGLE_ACTION_UPDATE)
62 return ACTION_DESCRIPTION_INFO;
63
64 return ACTION_UNKNOWN;
65 }
66
67 std::string ToJingleString(ActionType type) {
68 switch (type) {
69 case ACTION_SESSION_INITIATE:
70 return JINGLE_ACTION_SESSION_INITIATE;
71 case ACTION_SESSION_INFO:
72 return JINGLE_ACTION_SESSION_INFO;
73 case ACTION_DESCRIPTION_INFO:
74 return JINGLE_ACTION_DESCRIPTION_INFO;
75 case ACTION_SESSION_ACCEPT:
76 return JINGLE_ACTION_SESSION_ACCEPT;
77 // Notice that reject and terminate both go to
78 // "session-terminate", but there is no "session-reject".
79 case ACTION_SESSION_REJECT:
80 case ACTION_SESSION_TERMINATE:
81 return JINGLE_ACTION_SESSION_TERMINATE;
82 case ACTION_TRANSPORT_INFO:
83 return JINGLE_ACTION_TRANSPORT_INFO;
84 case ACTION_TRANSPORT_ACCEPT:
85 return JINGLE_ACTION_TRANSPORT_ACCEPT;
86 default:
87 return "";
88 }
89 }
90
91 std::string ToGingleString(ActionType type) {
92 switch (type) {
93 case ACTION_SESSION_INITIATE:
94 return GINGLE_ACTION_INITIATE;
95 case ACTION_SESSION_INFO:
96 return GINGLE_ACTION_INFO;
97 case ACTION_SESSION_ACCEPT:
98 return GINGLE_ACTION_ACCEPT;
99 case ACTION_SESSION_REJECT:
100 return GINGLE_ACTION_REJECT;
101 case ACTION_SESSION_TERMINATE:
102 return GINGLE_ACTION_TERMINATE;
103 case ACTION_TRANSPORT_INFO:
104 return GINGLE_ACTION_CANDIDATES;
105 default:
106 return "";
107 }
108 }
109
110
111 bool IsJingleMessage(const buzz::XmlElement* stanza) {
112 const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
113 if (jingle == NULL)
114 return false;
115
116 return (jingle->HasAttr(buzz::QN_ACTION) && jingle->HasAttr(QN_SID));
117 }
118
119 bool IsGingleMessage(const buzz::XmlElement* stanza) {
120 const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
121 if (session == NULL)
122 return false;
123
124 return (session->HasAttr(buzz::QN_TYPE) &&
125 session->HasAttr(buzz::QN_ID) &&
126 session->HasAttr(QN_INITIATOR));
127 }
128
129 bool IsSessionMessage(const buzz::XmlElement* stanza) {
130 return (stanza->Name() == buzz::QN_IQ &&
131 stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET &&
132 (IsJingleMessage(stanza) ||
133 IsGingleMessage(stanza)));
134 }
135
136 bool ParseGingleSessionMessage(const buzz::XmlElement* session,
137 SessionMessage* msg,
138 ParseError* error) {
139 msg->protocol = PROTOCOL_GINGLE;
140 std::string type_string = session->Attr(buzz::QN_TYPE);
141 msg->type = ToActionType(type_string);
142 msg->sid = session->Attr(buzz::QN_ID);
143 msg->initiator = session->Attr(QN_INITIATOR);
144 msg->action_elem = session;
145
146 if (msg->type == ACTION_UNKNOWN)
147 return BadParse("unknown action: " + type_string, error);
148
149 return true;
150 }
151
152 bool ParseJingleSessionMessage(const buzz::XmlElement* jingle,
153 SessionMessage* msg,
154 ParseError* error) {
155 msg->protocol = PROTOCOL_JINGLE;
156 std::string type_string = jingle->Attr(buzz::QN_ACTION);
157 msg->type = ToActionType(type_string);
158 msg->sid = jingle->Attr(QN_SID);
159 msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, buzz::STR_EMPTY);
160 msg->action_elem = jingle;
161
162 if (msg->type == ACTION_UNKNOWN)
163 return BadParse("unknown action: " + type_string, error);
164
165 return true;
166 }
167
168 bool ParseHybridSessionMessage(const buzz::XmlElement* jingle,
169 SessionMessage* msg,
170 ParseError* error) {
171 if (!ParseJingleSessionMessage(jingle, msg, error))
172 return false;
173 msg->protocol = PROTOCOL_HYBRID;
174
175 return true;
176 }
177
178 bool ParseSessionMessage(const buzz::XmlElement* stanza,
179 SessionMessage* msg,
180 ParseError* error) {
181 msg->id = stanza->Attr(buzz::QN_ID);
182 msg->from = stanza->Attr(buzz::QN_FROM);
183 msg->to = stanza->Attr(buzz::QN_TO);
184 msg->stanza = stanza;
185
186 const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
187 const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
188 if (jingle && session)
189 return ParseHybridSessionMessage(jingle, msg, error);
190 if (jingle != NULL)
191 return ParseJingleSessionMessage(jingle, msg, error);
192 if (session != NULL)
193 return ParseGingleSessionMessage(session, msg, error);
194 return false;
195 }
196
197 buzz::XmlElement* WriteGingleAction(const SessionMessage& msg,
198 const XmlElements& action_elems) {
199 buzz::XmlElement* session = new buzz::XmlElement(QN_GINGLE_SESSION, true);
200 session->AddAttr(buzz::QN_TYPE, ToGingleString(msg.type));
201 session->AddAttr(buzz::QN_ID, msg.sid);
202 session->AddAttr(QN_INITIATOR, msg.initiator);
203 AddXmlChildren(session, action_elems);
204 return session;
205 }
206
207 buzz::XmlElement* WriteJingleAction(const SessionMessage& msg,
208 const XmlElements& action_elems) {
209 buzz::XmlElement* jingle = new buzz::XmlElement(QN_JINGLE, true);
210 jingle->AddAttr(buzz::QN_ACTION, ToJingleString(msg.type));
211 jingle->AddAttr(QN_SID, msg.sid);
212 if (msg.type == ACTION_SESSION_INITIATE) {
213 jingle->AddAttr(QN_INITIATOR, msg.initiator);
214 }
215 AddXmlChildren(jingle, action_elems);
216 return jingle;
217 }
218
219 void WriteSessionMessage(const SessionMessage& msg,
220 const XmlElements& action_elems,
221 buzz::XmlElement* stanza) {
222 stanza->SetAttr(buzz::QN_TO, msg.to);
223 stanza->SetAttr(buzz::QN_TYPE, buzz::STR_SET);
224
225 if (msg.protocol == PROTOCOL_GINGLE) {
226 stanza->AddElement(WriteGingleAction(msg, action_elems));
227 } else {
228 stanza->AddElement(WriteJingleAction(msg, action_elems));
229 }
230 }
231
232
233 TransportParser* GetTransportParser(const TransportParserMap& trans_parsers,
234 const std::string& transport_type) {
235 TransportParserMap::const_iterator map = trans_parsers.find(transport_type);
236 if (map == trans_parsers.end()) {
237 return NULL;
238 } else {
239 return map->second;
240 }
241 }
242
243 CandidateTranslator* GetCandidateTranslator(
244 const CandidateTranslatorMap& translators,
245 const std::string& content_name) {
246 CandidateTranslatorMap::const_iterator map = translators.find(content_name);
247 if (map == translators.end()) {
248 return NULL;
249 } else {
250 return map->second;
251 }
252 }
253
254 bool GetParserAndTranslator(const TransportParserMap& trans_parsers,
255 const CandidateTranslatorMap& translators,
256 const std::string& transport_type,
257 const std::string& content_name,
258 TransportParser** parser,
259 CandidateTranslator** translator,
260 ParseError* error) {
261 *parser = GetTransportParser(trans_parsers, transport_type);
262 if (*parser == NULL) {
263 return BadParse("unknown transport type: " + transport_type, error);
264 }
265 // Not having a translator isn't fatal when parsing. If this is called for an
266 // initiate message, we won't have our proxies set up to do the translation.
267 // Fortunately, for the cases where translation is needed, candidates are
268 // never sent in initiates.
269 *translator = GetCandidateTranslator(translators, content_name);
270 return true;
271 }
272
273 bool GetParserAndTranslator(const TransportParserMap& trans_parsers,
274 const CandidateTranslatorMap& translators,
275 const std::string& transport_type,
276 const std::string& content_name,
277 TransportParser** parser,
278 CandidateTranslator** translator,
279 WriteError* error) {
280 *parser = GetTransportParser(trans_parsers, transport_type);
281 if (*parser == NULL) {
282 return BadWrite("unknown transport type: " + transport_type, error);
283 }
284 *translator = GetCandidateTranslator(translators, content_name);
285 if (*translator == NULL) {
286 return BadWrite("unknown content name: " + content_name, error);
287 }
288 return true;
289 }
290
291 bool ParseGingleCandidate(const buzz::XmlElement* candidate_elem,
292 const TransportParserMap& trans_parsers,
293 const CandidateTranslatorMap& translators,
294 const std::string& content_name,
295 Candidates* candidates,
296 ParseError* error) {
297 TransportParser* trans_parser;
298 CandidateTranslator* translator;
299 if (!GetParserAndTranslator(trans_parsers, translators,
300 NS_GINGLE_P2P, content_name,
301 &trans_parser, &translator, error))
302 return false;
303
304 Candidate candidate;
305 if (!trans_parser->ParseGingleCandidate(
306 candidate_elem, translator, &candidate, error)) {
307 return false;
308 }
309
310 candidates->push_back(candidate);
311 return true;
312 }
313
314 bool ParseGingleCandidates(const buzz::XmlElement* parent,
315 const TransportParserMap& trans_parsers,
316 const CandidateTranslatorMap& translators,
317 const std::string& content_name,
318 Candidates* candidates,
319 ParseError* error) {
320 for (const buzz::XmlElement* candidate_elem = parent->FirstElement();
321 candidate_elem != NULL;
322 candidate_elem = candidate_elem->NextElement()) {
323 if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
324 if (!ParseGingleCandidate(candidate_elem, trans_parsers, translators,
325 content_name, candidates, error)) {
326 return false;
327 }
328 }
329 }
330 return true;
331 }
332
333 bool ParseGingleTransportInfos(const buzz::XmlElement* action_elem,
334 const ContentInfos& contents,
335 const TransportParserMap& trans_parsers,
336 const CandidateTranslatorMap& translators,
337 TransportInfos* tinfos,
338 ParseError* error) {
339 bool has_audio = FindContentInfoByName(contents, CN_AUDIO) != NULL;
340 bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL;
341
342 // If we don't have media, no need to separate the candidates.
343 if (!has_audio && !has_video) {
344 TransportInfo tinfo(CN_OTHER,
345 TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
346 if (!ParseGingleCandidates(action_elem, trans_parsers, translators,
347 CN_OTHER, &tinfo.description.candidates,
348 error)) {
349 return false;
350 }
351
352 tinfos->push_back(tinfo);
353 return true;
354 }
355
356 // If we have media, separate the candidates.
357 TransportInfo audio_tinfo(
358 CN_AUDIO,
359 TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
360 TransportInfo video_tinfo(
361 CN_VIDEO,
362 TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
363 for (const buzz::XmlElement* candidate_elem = action_elem->FirstElement();
364 candidate_elem != NULL;
365 candidate_elem = candidate_elem->NextElement()) {
366 if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
367 const std::string& channel_name = candidate_elem->Attr(buzz::QN_NAME);
368 if (has_audio &&
369 (channel_name == GICE_CHANNEL_NAME_RTP ||
370 channel_name == GICE_CHANNEL_NAME_RTCP)) {
371 if (!ParseGingleCandidate(
372 candidate_elem, trans_parsers,
373 translators, CN_AUDIO,
374 &audio_tinfo.description.candidates, error)) {
375 return false;
376 }
377 } else if (has_video &&
378 (channel_name == GICE_CHANNEL_NAME_VIDEO_RTP ||
379 channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP)) {
380 if (!ParseGingleCandidate(
381 candidate_elem, trans_parsers,
382 translators, CN_VIDEO,
383 &video_tinfo.description.candidates, error)) {
384 return false;
385 }
386 } else {
387 return BadParse("Unknown channel name: " + channel_name, error);
388 }
389 }
390 }
391
392 if (has_audio) {
393 tinfos->push_back(audio_tinfo);
394 }
395 if (has_video) {
396 tinfos->push_back(video_tinfo);
397 }
398 return true;
399 }
400
401 bool ParseJingleTransportInfo(const buzz::XmlElement* trans_elem,
402 const std::string& content_name,
403 const TransportParserMap& trans_parsers,
404 const CandidateTranslatorMap& translators,
405 TransportInfo* tinfo,
406 ParseError* error) {
407 TransportParser* trans_parser;
408 CandidateTranslator* translator;
409 if (!GetParserAndTranslator(trans_parsers, translators,
410 trans_elem->Name().Namespace(), content_name,
411 &trans_parser, &translator, error))
412 return false;
413
414 TransportDescription tdesc;
415 if (!trans_parser->ParseTransportDescription(trans_elem, translator,
416 &tdesc, error))
417 return false;
418
419 *tinfo = TransportInfo(content_name, tdesc);
420 return true;
421 }
422
423 bool ParseJingleTransportInfos(const buzz::XmlElement* jingle,
424 const ContentInfos& contents,
425 const TransportParserMap trans_parsers,
426 const CandidateTranslatorMap& translators,
427 TransportInfos* tinfos,
428 ParseError* error) {
429 for (const buzz::XmlElement* pair_elem
430 = jingle->FirstNamed(QN_JINGLE_CONTENT);
431 pair_elem != NULL;
432 pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
433 std::string content_name;
434 if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
435 &content_name, error))
436 return false;
437
438 const ContentInfo* content = FindContentInfoByName(contents, content_name);
439 if (!content)
440 return BadParse("Unknown content name: " + content_name, error);
441
442 const buzz::XmlElement* trans_elem;
443 if (!RequireXmlChild(pair_elem, LN_TRANSPORT, &trans_elem, error))
444 return false;
445
446 TransportInfo tinfo;
447 if (!ParseJingleTransportInfo(trans_elem, content->name,
448 trans_parsers, translators,
449 &tinfo, error))
450 return false;
451
452 tinfos->push_back(tinfo);
453 }
454
455 return true;
456 }
457
458 buzz::XmlElement* NewTransportElement(const std::string& name) {
459 return new buzz::XmlElement(buzz::QName(name, LN_TRANSPORT), true);
460 }
461
462 bool WriteGingleCandidates(const Candidates& candidates,
463 const TransportParserMap& trans_parsers,
464 const std::string& transport_type,
465 const CandidateTranslatorMap& translators,
466 const std::string& content_name,
467 XmlElements* elems,
468 WriteError* error) {
469 TransportParser* trans_parser;
470 CandidateTranslator* translator;
471 if (!GetParserAndTranslator(trans_parsers, translators,
472 transport_type, content_name,
473 &trans_parser, &translator, error))
474 return false;
475
476 for (size_t i = 0; i < candidates.size(); ++i) {
477 rtc::scoped_ptr<buzz::XmlElement> element;
478 if (!trans_parser->WriteGingleCandidate(candidates[i], translator,
479 element.accept(), error)) {
480 return false;
481 }
482
483 elems->push_back(element.release());
484 }
485
486 return true;
487 }
488
489 bool WriteGingleTransportInfos(const TransportInfos& tinfos,
490 const TransportParserMap& trans_parsers,
491 const CandidateTranslatorMap& translators,
492 XmlElements* elems,
493 WriteError* error) {
494 for (TransportInfos::const_iterator tinfo = tinfos.begin();
495 tinfo != tinfos.end(); ++tinfo) {
496 if (!WriteGingleCandidates(tinfo->description.candidates,
497 trans_parsers, tinfo->description.transport_type,
498 translators, tinfo->content_name,
499 elems, error))
500 return false;
501 }
502
503 return true;
504 }
505
506 bool WriteJingleTransportInfo(const TransportInfo& tinfo,
507 const TransportParserMap& trans_parsers,
508 const CandidateTranslatorMap& translators,
509 XmlElements* elems,
510 WriteError* error) {
511 std::string transport_type = tinfo.description.transport_type;
512 TransportParser* trans_parser;
513 CandidateTranslator* translator;
514 if (!GetParserAndTranslator(trans_parsers, translators,
515 transport_type, tinfo.content_name,
516 &trans_parser, &translator, error))
517 return false;
518
519 buzz::XmlElement* trans_elem;
520 if (!trans_parser->WriteTransportDescription(tinfo.description, translator,
521 &trans_elem, error)) {
522 return false;
523 }
524
525 elems->push_back(trans_elem);
526 return true;
527 }
528
529 void WriteJingleContent(const std::string name,
530 const XmlElements& child_elems,
531 XmlElements* elems) {
532 buzz::XmlElement* content_elem = new buzz::XmlElement(QN_JINGLE_CONTENT);
533 content_elem->SetAttr(QN_JINGLE_CONTENT_NAME, name);
534 content_elem->SetAttr(QN_CREATOR, LN_INITIATOR);
535 AddXmlChildren(content_elem, child_elems);
536
537 elems->push_back(content_elem);
538 }
539
540 bool WriteJingleTransportInfos(const TransportInfos& tinfos,
541 const TransportParserMap& trans_parsers,
542 const CandidateTranslatorMap& translators,
543 XmlElements* elems,
544 WriteError* error) {
545 for (TransportInfos::const_iterator tinfo = tinfos.begin();
546 tinfo != tinfos.end(); ++tinfo) {
547 XmlElements content_child_elems;
548 if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
549 &content_child_elems, error))
550
551 return false;
552
553 WriteJingleContent(tinfo->content_name, content_child_elems, elems);
554 }
555
556 return true;
557 }
558
559 ContentParser* GetContentParser(const ContentParserMap& content_parsers,
560 const std::string& type) {
561 ContentParserMap::const_iterator map = content_parsers.find(type);
562 if (map == content_parsers.end()) {
563 return NULL;
564 } else {
565 return map->second;
566 }
567 }
568
569 bool ParseContentInfo(SignalingProtocol protocol,
570 const std::string& name,
571 const std::string& type,
572 const buzz::XmlElement* elem,
573 const ContentParserMap& parsers,
574 ContentInfos* contents,
575 ParseError* error) {
576 ContentParser* parser = GetContentParser(parsers, type);
577 if (parser == NULL)
578 return BadParse("unknown application content: " + type, error);
579
580 ContentDescription* desc;
581 if (!parser->ParseContent(protocol, elem, &desc, error))
582 return false;
583
584 contents->push_back(ContentInfo(name, type, desc));
585 return true;
586 }
587
588 bool ParseContentType(const buzz::XmlElement* parent_elem,
589 std::string* content_type,
590 const buzz::XmlElement** content_elem,
591 ParseError* error) {
592 if (!RequireXmlChild(parent_elem, LN_DESCRIPTION, content_elem, error))
593 return false;
594
595 *content_type = (*content_elem)->Name().Namespace();
596 return true;
597 }
598
599 bool ParseGingleContentInfos(const buzz::XmlElement* session,
600 const ContentParserMap& content_parsers,
601 ContentInfos* contents,
602 ParseError* error) {
603 std::string content_type;
604 const buzz::XmlElement* content_elem;
605 if (!ParseContentType(session, &content_type, &content_elem, error))
606 return false;
607
608 if (content_type == NS_GINGLE_VIDEO) {
609 // A parser parsing audio or video content should look at the
610 // namespace and only parse the codecs relevant to that namespace.
611 // We use this to control which codecs get parsed: first audio,
612 // then video.
613 rtc::scoped_ptr<buzz::XmlElement> audio_elem(
614 new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT));
615 CopyXmlChildren(content_elem, audio_elem.get());
616 if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
617 audio_elem.get(), content_parsers,
618 contents, error))
619 return false;
620
621 if (!ParseContentInfo(PROTOCOL_GINGLE, CN_VIDEO, NS_JINGLE_RTP,
622 content_elem, content_parsers,
623 contents, error))
624 return false;
625 } else if (content_type == NS_GINGLE_AUDIO) {
626 if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
627 content_elem, content_parsers,
628 contents, error))
629 return false;
630 } else {
631 if (!ParseContentInfo(PROTOCOL_GINGLE, CN_OTHER, content_type,
632 content_elem, content_parsers,
633 contents, error))
634 return false;
635 }
636 return true;
637 }
638
639 bool ParseJingleContentInfos(const buzz::XmlElement* jingle,
640 const ContentParserMap& content_parsers,
641 ContentInfos* contents,
642 ParseError* error) {
643 for (const buzz::XmlElement* pair_elem
644 = jingle->FirstNamed(QN_JINGLE_CONTENT);
645 pair_elem != NULL;
646 pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
647 std::string content_name;
648 if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
649 &content_name, error))
650 return false;
651
652 std::string content_type;
653 const buzz::XmlElement* content_elem;
654 if (!ParseContentType(pair_elem, &content_type, &content_elem, error))
655 return false;
656
657 if (!ParseContentInfo(PROTOCOL_JINGLE, content_name, content_type,
658 content_elem, content_parsers,
659 contents, error))
660 return false;
661 }
662 return true;
663 }
664
665 bool ParseJingleGroupInfos(const buzz::XmlElement* jingle,
666 ContentGroups* groups,
667 ParseError* error) {
668 for (const buzz::XmlElement* pair_elem
669 = jingle->FirstNamed(QN_JINGLE_DRAFT_GROUP);
670 pair_elem != NULL;
671 pair_elem = pair_elem->NextNamed(QN_JINGLE_DRAFT_GROUP)) {
672 std::string group_name;
673 if (!RequireXmlAttr(pair_elem, QN_JINGLE_DRAFT_GROUP_TYPE,
674 &group_name, error))
675 return false;
676
677 ContentGroup group(group_name);
678 for (const buzz::XmlElement* child_elem
679 = pair_elem->FirstNamed(QN_JINGLE_CONTENT);
680 child_elem != NULL;
681 child_elem = child_elem->NextNamed(QN_JINGLE_CONTENT)) {
682 std::string content_name;
683 if (!RequireXmlAttr(child_elem, QN_JINGLE_CONTENT_NAME,
684 &content_name, error))
685 return false;
686 group.AddContentName(content_name);
687 }
688 groups->push_back(group);
689 }
690 return true;
691 }
692
693 buzz::XmlElement* WriteContentInfo(SignalingProtocol protocol,
694 const ContentInfo& content,
695 const ContentParserMap& parsers,
696 WriteError* error) {
697 ContentParser* parser = GetContentParser(parsers, content.type);
698 if (parser == NULL) {
699 BadWrite("unknown content type: " + content.type, error);
700 return NULL;
701 }
702
703 buzz::XmlElement* elem = NULL;
704 if (!parser->WriteContent(protocol, content.description, &elem, error))
705 return NULL;
706
707 return elem;
708 }
709
710 bool IsWritable(SignalingProtocol protocol,
711 const ContentInfo& content,
712 const ContentParserMap& parsers) {
713 ContentParser* parser = GetContentParser(parsers, content.type);
714 if (parser == NULL) {
715 return false;
716 }
717
718 return parser->IsWritable(protocol, content.description);
719 }
720
721 bool WriteGingleContentInfos(const ContentInfos& contents,
722 const ContentParserMap& parsers,
723 XmlElements* elems,
724 WriteError* error) {
725 if (contents.size() == 1 ||
726 (contents.size() == 2 &&
727 !IsWritable(PROTOCOL_GINGLE, contents.at(1), parsers))) {
728 if (contents.front().rejected) {
729 return BadWrite("Gingle protocol may not reject individual contents.",
730 error);
731 }
732 buzz::XmlElement* elem = WriteContentInfo(
733 PROTOCOL_GINGLE, contents.front(), parsers, error);
734 if (!elem)
735 return false;
736
737 elems->push_back(elem);
738 } else if (contents.size() >= 2 &&
739 contents.at(0).type == NS_JINGLE_RTP &&
740 contents.at(1).type == NS_JINGLE_RTP) {
741 // Special-case audio + video contents so that they are "merged"
742 // into one "video" content.
743 if (contents.at(0).rejected || contents.at(1).rejected) {
744 return BadWrite("Gingle protocol may not reject individual contents.",
745 error);
746 }
747 buzz::XmlElement* audio = WriteContentInfo(
748 PROTOCOL_GINGLE, contents.at(0), parsers, error);
749 if (!audio)
750 return false;
751
752 buzz::XmlElement* video = WriteContentInfo(
753 PROTOCOL_GINGLE, contents.at(1), parsers, error);
754 if (!video) {
755 delete audio;
756 return false;
757 }
758
759 CopyXmlChildren(audio, video);
760 elems->push_back(video);
761 delete audio;
762 } else {
763 return BadWrite("Gingle protocol may only have one content.", error);
764 }
765
766 return true;
767 }
768
769 const TransportInfo* GetTransportInfoByContentName(
770 const TransportInfos& tinfos, const std::string& content_name) {
771 for (TransportInfos::const_iterator tinfo = tinfos.begin();
772 tinfo != tinfos.end(); ++tinfo) {
773 if (content_name == tinfo->content_name) {
774 return &*tinfo;
775 }
776 }
777 return NULL;
778 }
779
780 bool WriteJingleContents(const ContentInfos& contents,
781 const ContentParserMap& content_parsers,
782 const TransportInfos& tinfos,
783 const TransportParserMap& trans_parsers,
784 const CandidateTranslatorMap& translators,
785 XmlElements* elems,
786 WriteError* error) {
787 for (ContentInfos::const_iterator content = contents.begin();
788 content != contents.end(); ++content) {
789 if (content->rejected) {
790 continue;
791 }
792 const TransportInfo* tinfo =
793 GetTransportInfoByContentName(tinfos, content->name);
794 if (!tinfo)
795 return BadWrite("No transport for content: " + content->name, error);
796
797 XmlElements pair_elems;
798 buzz::XmlElement* elem = WriteContentInfo(
799 PROTOCOL_JINGLE, *content, content_parsers, error);
800 if (!elem)
801 return false;
802 pair_elems.push_back(elem);
803
804 if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
805 &pair_elems, error))
806 return false;
807
808 WriteJingleContent(content->name, pair_elems, elems);
809 }
810 return true;
811 }
812
813 bool WriteJingleContentInfos(const ContentInfos& contents,
814 const ContentParserMap& content_parsers,
815 XmlElements* elems,
816 WriteError* error) {
817 for (ContentInfos::const_iterator content = contents.begin();
818 content != contents.end(); ++content) {
819 if (content->rejected) {
820 continue;
821 }
822 XmlElements content_child_elems;
823 buzz::XmlElement* elem = WriteContentInfo(
824 PROTOCOL_JINGLE, *content, content_parsers, error);
825 if (!elem)
826 return false;
827 content_child_elems.push_back(elem);
828 WriteJingleContent(content->name, content_child_elems, elems);
829 }
830 return true;
831 }
832
833 bool WriteJingleGroupInfo(const ContentInfos& contents,
834 const ContentGroups& groups,
835 XmlElements* elems,
836 WriteError* error) {
837 if (!groups.empty()) {
838 buzz::XmlElement* pair_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_GROUP);
839 pair_elem->SetAttr(QN_JINGLE_DRAFT_GROUP_TYPE, GROUP_TYPE_BUNDLE);
840
841 XmlElements pair_elems;
842 for (ContentInfos::const_iterator content = contents.begin();
843 content != contents.end(); ++content) {
844 buzz::XmlElement* child_elem =
845 new buzz::XmlElement(QN_JINGLE_CONTENT, false);
846 child_elem->SetAttr(QN_JINGLE_CONTENT_NAME, content->name);
847 pair_elems.push_back(child_elem);
848 }
849 AddXmlChildren(pair_elem, pair_elems);
850 elems->push_back(pair_elem);
851 }
852 return true;
853 }
854
855 bool ParseContentType(SignalingProtocol protocol,
856 const buzz::XmlElement* action_elem,
857 std::string* content_type,
858 ParseError* error) {
859 const buzz::XmlElement* content_elem;
860 if (protocol == PROTOCOL_GINGLE) {
861 if (!ParseContentType(action_elem, content_type, &content_elem, error))
862 return false;
863
864 // Internally, we only use NS_JINGLE_RTP.
865 if (*content_type == NS_GINGLE_AUDIO ||
866 *content_type == NS_GINGLE_VIDEO)
867 *content_type = NS_JINGLE_RTP;
868 } else {
869 const buzz::XmlElement* pair_elem
870 = action_elem->FirstNamed(QN_JINGLE_CONTENT);
871 if (pair_elem == NULL)
872 return BadParse("No contents found", error);
873
874 if (!ParseContentType(pair_elem, content_type, &content_elem, error))
875 return false;
876 }
877
878 return true;
879 }
880
881 static bool ParseContentMessage(
882 SignalingProtocol protocol,
883 const buzz::XmlElement* action_elem,
884 bool expect_transports,
885 const ContentParserMap& content_parsers,
886 const TransportParserMap& trans_parsers,
887 const CandidateTranslatorMap& translators,
888 SessionInitiate* init,
889 ParseError* error) {
890 init->owns_contents = true;
891 if (protocol == PROTOCOL_GINGLE) {
892 if (!ParseGingleContentInfos(action_elem, content_parsers,
893 &init->contents, error))
894 return false;
895
896 if (expect_transports &&
897 !ParseGingleTransportInfos(action_elem, init->contents,
898 trans_parsers, translators,
899 &init->transports, error))
900 return false;
901 } else {
902 if (!ParseJingleContentInfos(action_elem, content_parsers,
903 &init->contents, error))
904 return false;
905 if (!ParseJingleGroupInfos(action_elem, &init->groups, error))
906 return false;
907
908 if (expect_transports &&
909 !ParseJingleTransportInfos(action_elem, init->contents,
910 trans_parsers, translators,
911 &init->transports, error))
912 return false;
913 }
914
915 return true;
916 }
917
918 static bool WriteContentMessage(
919 SignalingProtocol protocol,
920 const ContentInfos& contents,
921 const TransportInfos& tinfos,
922 const ContentParserMap& content_parsers,
923 const TransportParserMap& transport_parsers,
924 const CandidateTranslatorMap& translators,
925 const ContentGroups& groups,
926 XmlElements* elems,
927 WriteError* error) {
928 if (protocol == PROTOCOL_GINGLE) {
929 if (!WriteGingleContentInfos(contents, content_parsers, elems, error))
930 return false;
931
932 if (!WriteGingleTransportInfos(tinfos, transport_parsers, translators,
933 elems, error))
934 return false;
935 } else {
936 if (!WriteJingleContents(contents, content_parsers,
937 tinfos, transport_parsers, translators,
938 elems, error))
939 return false;
940 if (!WriteJingleGroupInfo(contents, groups, elems, error))
941 return false;
942 }
943
944 return true;
945 }
946
947 bool ParseSessionInitiate(SignalingProtocol protocol,
948 const buzz::XmlElement* action_elem,
949 const ContentParserMap& content_parsers,
950 const TransportParserMap& trans_parsers,
951 const CandidateTranslatorMap& translators,
952 SessionInitiate* init,
953 ParseError* error) {
954 bool expect_transports = true;
955 return ParseContentMessage(protocol, action_elem, expect_transports,
956 content_parsers, trans_parsers, translators,
957 init, error);
958 }
959
960
961 bool WriteSessionInitiate(SignalingProtocol protocol,
962 const ContentInfos& contents,
963 const TransportInfos& tinfos,
964 const ContentParserMap& content_parsers,
965 const TransportParserMap& transport_parsers,
966 const CandidateTranslatorMap& translators,
967 const ContentGroups& groups,
968 XmlElements* elems,
969 WriteError* error) {
970 return WriteContentMessage(protocol, contents, tinfos,
971 content_parsers, transport_parsers, translators,
972 groups,
973 elems, error);
974 }
975
976 bool ParseSessionAccept(SignalingProtocol protocol,
977 const buzz::XmlElement* action_elem,
978 const ContentParserMap& content_parsers,
979 const TransportParserMap& transport_parsers,
980 const CandidateTranslatorMap& translators,
981 SessionAccept* accept,
982 ParseError* error) {
983 bool expect_transports = true;
984 return ParseContentMessage(protocol, action_elem, expect_transports,
985 content_parsers, transport_parsers, translators,
986 accept, error);
987 }
988
989 bool WriteSessionAccept(SignalingProtocol protocol,
990 const ContentInfos& contents,
991 const TransportInfos& tinfos,
992 const ContentParserMap& content_parsers,
993 const TransportParserMap& transport_parsers,
994 const CandidateTranslatorMap& translators,
995 const ContentGroups& groups,
996 XmlElements* elems,
997 WriteError* error) {
998 return WriteContentMessage(protocol, contents, tinfos,
999 content_parsers, transport_parsers, translators,
1000 groups,
1001 elems, error);
1002 }
1003
1004 bool ParseSessionTerminate(SignalingProtocol protocol,
1005 const buzz::XmlElement* action_elem,
1006 SessionTerminate* term,
1007 ParseError* error) {
1008 if (protocol == PROTOCOL_GINGLE) {
1009 const buzz::XmlElement* reason_elem = action_elem->FirstElement();
1010 if (reason_elem != NULL) {
1011 term->reason = reason_elem->Name().LocalPart();
1012 const buzz::XmlElement *debug_elem = reason_elem->FirstElement();
1013 if (debug_elem != NULL) {
1014 term->debug_reason = debug_elem->Name().LocalPart();
1015 }
1016 }
1017 return true;
1018 } else {
1019 const buzz::XmlElement* reason_elem =
1020 action_elem->FirstNamed(QN_JINGLE_REASON);
1021 if (reason_elem) {
1022 reason_elem = reason_elem->FirstElement();
1023 if (reason_elem) {
1024 term->reason = reason_elem->Name().LocalPart();
1025 }
1026 }
1027 return true;
1028 }
1029 }
1030
1031 void WriteSessionTerminate(SignalingProtocol protocol,
1032 const SessionTerminate& term,
1033 XmlElements* elems) {
1034 if (protocol == PROTOCOL_GINGLE) {
1035 elems->push_back(new buzz::XmlElement(buzz::QName(NS_GINGLE, term.reason)));
1036 } else {
1037 if (!term.reason.empty()) {
1038 buzz::XmlElement* reason_elem = new buzz::XmlElement(QN_JINGLE_REASON);
1039 reason_elem->AddElement(new buzz::XmlElement(
1040 buzz::QName(NS_JINGLE, term.reason)));
1041 elems->push_back(reason_elem);
1042 }
1043 }
1044 }
1045
1046 bool ParseDescriptionInfo(SignalingProtocol protocol,
1047 const buzz::XmlElement* action_elem,
1048 const ContentParserMap& content_parsers,
1049 const TransportParserMap& transport_parsers,
1050 const CandidateTranslatorMap& translators,
1051 DescriptionInfo* description_info,
1052 ParseError* error) {
1053 bool expect_transports = false;
1054 return ParseContentMessage(protocol, action_elem, expect_transports,
1055 content_parsers, transport_parsers, translators,
1056 description_info, error);
1057 }
1058
1059 bool WriteDescriptionInfo(SignalingProtocol protocol,
1060 const ContentInfos& contents,
1061 const ContentParserMap& content_parsers,
1062 XmlElements* elems,
1063 WriteError* error) {
1064 if (protocol == PROTOCOL_GINGLE) {
1065 return WriteGingleContentInfos(contents, content_parsers, elems, error);
1066 } else {
1067 return WriteJingleContentInfos(contents, content_parsers, elems, error);
1068 }
1069 }
1070
1071 bool ParseTransportInfos(SignalingProtocol protocol,
1072 const buzz::XmlElement* action_elem,
1073 const ContentInfos& contents,
1074 const TransportParserMap& trans_parsers,
1075 const CandidateTranslatorMap& translators,
1076 TransportInfos* tinfos,
1077 ParseError* error) {
1078 if (protocol == PROTOCOL_GINGLE) {
1079 return ParseGingleTransportInfos(
1080 action_elem, contents, trans_parsers, translators, tinfos, error);
1081 } else {
1082 return ParseJingleTransportInfos(
1083 action_elem, contents, trans_parsers, translators, tinfos, error);
1084 }
1085 }
1086
1087 bool WriteTransportInfos(SignalingProtocol protocol,
1088 const TransportInfos& tinfos,
1089 const TransportParserMap& trans_parsers,
1090 const CandidateTranslatorMap& translators,
1091 XmlElements* elems,
1092 WriteError* error) {
1093 if (protocol == PROTOCOL_GINGLE) {
1094 return WriteGingleTransportInfos(tinfos, trans_parsers, translators,
1095 elems, error);
1096 } else {
1097 return WriteJingleTransportInfos(tinfos, trans_parsers, translators,
1098 elems, error);
1099 }
1100 }
1101
1102 bool GetUriTarget(const std::string& prefix, const std::string& str,
1103 std::string* after) {
1104 size_t pos = str.find(prefix);
1105 if (pos == std::string::npos)
1106 return false;
1107
1108 *after = str.substr(pos + prefix.size(), std::string::npos);
1109 return true;
1110 }
1111
1112 bool FindSessionRedirect(const buzz::XmlElement* stanza,
1113 SessionRedirect* redirect) {
1114 const buzz::XmlElement* error_elem = GetXmlChild(stanza, LN_ERROR);
1115 if (error_elem == NULL)
1116 return false;
1117
1118 const buzz::XmlElement* redirect_elem =
1119 error_elem->FirstNamed(QN_GINGLE_REDIRECT);
1120 if (redirect_elem == NULL)
1121 redirect_elem = error_elem->FirstNamed(buzz::QN_STANZA_REDIRECT);
1122 if (redirect_elem == NULL)
1123 return false;
1124
1125 if (!GetUriTarget(STR_REDIRECT_PREFIX, redirect_elem->BodyText(),
1126 &redirect->target))
1127 return false;
1128
1129 return true;
1130 }
1131
1132 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/libjingle/session/sessionmessages.h ('k') | webrtc/libjingle/session/sessionsendtask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698