Index: webrtc/libjingle/session/sessionmessages.cc |
diff --git a/webrtc/libjingle/session/sessionmessages.cc b/webrtc/libjingle/session/sessionmessages.cc |
deleted file mode 100644 |
index acc8afabcebd1b25555ec9865612d809ae335806..0000000000000000000000000000000000000000 |
--- a/webrtc/libjingle/session/sessionmessages.cc |
+++ /dev/null |
@@ -1,1132 +0,0 @@ |
-/* |
- * Copyright 2010 The WebRTC Project Authors. All rights reserved. |
- * |
- * Use of this source code is governed by a BSD-style license |
- * that can be found in the LICENSE file in the root of the source |
- * tree. An additional intellectual property rights grant can be found |
- * in the file PATENTS. All contributing project authors may |
- * be found in the AUTHORS file in the root of the source tree. |
- */ |
- |
-#include "webrtc/libjingle/session/sessionmessages.h" |
- |
-#include <stdio.h> |
-#include <string> |
- |
-#include "webrtc/base/logging.h" |
-#include "webrtc/base/scoped_ptr.h" |
-#include "webrtc/base/stringutils.h" |
-#include "webrtc/libjingle/session/parsing.h" |
-#include "webrtc/libjingle/session/sessionclient.h" |
-#include "webrtc/libjingle/xmllite/xmlconstants.h" |
-#include "webrtc/libjingle/xmpp/constants.h" |
-#include "webrtc/p2p/base/constants.h" |
-#include "webrtc/p2p/base/p2ptransport.h" |
-#include "webrtc/p2p/base/sessiondescription.h" |
-#include "webrtc/p2p/base/transport.h" |
- |
-namespace cricket { |
- |
-ActionType ToActionType(const std::string& type) { |
- if (type == GINGLE_ACTION_INITIATE) |
- return ACTION_SESSION_INITIATE; |
- if (type == GINGLE_ACTION_INFO) |
- return ACTION_SESSION_INFO; |
- if (type == GINGLE_ACTION_ACCEPT) |
- return ACTION_SESSION_ACCEPT; |
- if (type == GINGLE_ACTION_REJECT) |
- return ACTION_SESSION_REJECT; |
- if (type == GINGLE_ACTION_TERMINATE) |
- return ACTION_SESSION_TERMINATE; |
- if (type == GINGLE_ACTION_CANDIDATES) |
- return ACTION_TRANSPORT_INFO; |
- if (type == JINGLE_ACTION_SESSION_INITIATE) |
- return ACTION_SESSION_INITIATE; |
- if (type == JINGLE_ACTION_TRANSPORT_INFO) |
- return ACTION_TRANSPORT_INFO; |
- if (type == JINGLE_ACTION_TRANSPORT_ACCEPT) |
- return ACTION_TRANSPORT_ACCEPT; |
- if (type == JINGLE_ACTION_SESSION_INFO) |
- return ACTION_SESSION_INFO; |
- if (type == JINGLE_ACTION_SESSION_ACCEPT) |
- return ACTION_SESSION_ACCEPT; |
- if (type == JINGLE_ACTION_SESSION_TERMINATE) |
- return ACTION_SESSION_TERMINATE; |
- if (type == JINGLE_ACTION_TRANSPORT_INFO) |
- return ACTION_TRANSPORT_INFO; |
- if (type == JINGLE_ACTION_TRANSPORT_ACCEPT) |
- return ACTION_TRANSPORT_ACCEPT; |
- if (type == JINGLE_ACTION_DESCRIPTION_INFO) |
- return ACTION_DESCRIPTION_INFO; |
- if (type == GINGLE_ACTION_UPDATE) |
- return ACTION_DESCRIPTION_INFO; |
- |
- return ACTION_UNKNOWN; |
-} |
- |
-std::string ToJingleString(ActionType type) { |
- switch (type) { |
- case ACTION_SESSION_INITIATE: |
- return JINGLE_ACTION_SESSION_INITIATE; |
- case ACTION_SESSION_INFO: |
- return JINGLE_ACTION_SESSION_INFO; |
- case ACTION_DESCRIPTION_INFO: |
- return JINGLE_ACTION_DESCRIPTION_INFO; |
- case ACTION_SESSION_ACCEPT: |
- return JINGLE_ACTION_SESSION_ACCEPT; |
- // Notice that reject and terminate both go to |
- // "session-terminate", but there is no "session-reject". |
- case ACTION_SESSION_REJECT: |
- case ACTION_SESSION_TERMINATE: |
- return JINGLE_ACTION_SESSION_TERMINATE; |
- case ACTION_TRANSPORT_INFO: |
- return JINGLE_ACTION_TRANSPORT_INFO; |
- case ACTION_TRANSPORT_ACCEPT: |
- return JINGLE_ACTION_TRANSPORT_ACCEPT; |
- default: |
- return ""; |
- } |
-} |
- |
-std::string ToGingleString(ActionType type) { |
- switch (type) { |
- case ACTION_SESSION_INITIATE: |
- return GINGLE_ACTION_INITIATE; |
- case ACTION_SESSION_INFO: |
- return GINGLE_ACTION_INFO; |
- case ACTION_SESSION_ACCEPT: |
- return GINGLE_ACTION_ACCEPT; |
- case ACTION_SESSION_REJECT: |
- return GINGLE_ACTION_REJECT; |
- case ACTION_SESSION_TERMINATE: |
- return GINGLE_ACTION_TERMINATE; |
- case ACTION_TRANSPORT_INFO: |
- return GINGLE_ACTION_CANDIDATES; |
- default: |
- return ""; |
- } |
-} |
- |
- |
-bool IsJingleMessage(const buzz::XmlElement* stanza) { |
- const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE); |
- if (jingle == NULL) |
- return false; |
- |
- return (jingle->HasAttr(buzz::QN_ACTION) && jingle->HasAttr(QN_SID)); |
-} |
- |
-bool IsGingleMessage(const buzz::XmlElement* stanza) { |
- const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION); |
- if (session == NULL) |
- return false; |
- |
- return (session->HasAttr(buzz::QN_TYPE) && |
- session->HasAttr(buzz::QN_ID) && |
- session->HasAttr(QN_INITIATOR)); |
-} |
- |
-bool IsSessionMessage(const buzz::XmlElement* stanza) { |
- return (stanza->Name() == buzz::QN_IQ && |
- stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET && |
- (IsJingleMessage(stanza) || |
- IsGingleMessage(stanza))); |
-} |
- |
-bool ParseGingleSessionMessage(const buzz::XmlElement* session, |
- SessionMessage* msg, |
- ParseError* error) { |
- msg->protocol = PROTOCOL_GINGLE; |
- std::string type_string = session->Attr(buzz::QN_TYPE); |
- msg->type = ToActionType(type_string); |
- msg->sid = session->Attr(buzz::QN_ID); |
- msg->initiator = session->Attr(QN_INITIATOR); |
- msg->action_elem = session; |
- |
- if (msg->type == ACTION_UNKNOWN) |
- return BadParse("unknown action: " + type_string, error); |
- |
- return true; |
-} |
- |
-bool ParseJingleSessionMessage(const buzz::XmlElement* jingle, |
- SessionMessage* msg, |
- ParseError* error) { |
- msg->protocol = PROTOCOL_JINGLE; |
- std::string type_string = jingle->Attr(buzz::QN_ACTION); |
- msg->type = ToActionType(type_string); |
- msg->sid = jingle->Attr(QN_SID); |
- msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, buzz::STR_EMPTY); |
- msg->action_elem = jingle; |
- |
- if (msg->type == ACTION_UNKNOWN) |
- return BadParse("unknown action: " + type_string, error); |
- |
- return true; |
-} |
- |
-bool ParseHybridSessionMessage(const buzz::XmlElement* jingle, |
- SessionMessage* msg, |
- ParseError* error) { |
- if (!ParseJingleSessionMessage(jingle, msg, error)) |
- return false; |
- msg->protocol = PROTOCOL_HYBRID; |
- |
- return true; |
-} |
- |
-bool ParseSessionMessage(const buzz::XmlElement* stanza, |
- SessionMessage* msg, |
- ParseError* error) { |
- msg->id = stanza->Attr(buzz::QN_ID); |
- msg->from = stanza->Attr(buzz::QN_FROM); |
- msg->to = stanza->Attr(buzz::QN_TO); |
- msg->stanza = stanza; |
- |
- const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE); |
- const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION); |
- if (jingle && session) |
- return ParseHybridSessionMessage(jingle, msg, error); |
- if (jingle != NULL) |
- return ParseJingleSessionMessage(jingle, msg, error); |
- if (session != NULL) |
- return ParseGingleSessionMessage(session, msg, error); |
- return false; |
-} |
- |
-buzz::XmlElement* WriteGingleAction(const SessionMessage& msg, |
- const XmlElements& action_elems) { |
- buzz::XmlElement* session = new buzz::XmlElement(QN_GINGLE_SESSION, true); |
- session->AddAttr(buzz::QN_TYPE, ToGingleString(msg.type)); |
- session->AddAttr(buzz::QN_ID, msg.sid); |
- session->AddAttr(QN_INITIATOR, msg.initiator); |
- AddXmlChildren(session, action_elems); |
- return session; |
-} |
- |
-buzz::XmlElement* WriteJingleAction(const SessionMessage& msg, |
- const XmlElements& action_elems) { |
- buzz::XmlElement* jingle = new buzz::XmlElement(QN_JINGLE, true); |
- jingle->AddAttr(buzz::QN_ACTION, ToJingleString(msg.type)); |
- jingle->AddAttr(QN_SID, msg.sid); |
- if (msg.type == ACTION_SESSION_INITIATE) { |
- jingle->AddAttr(QN_INITIATOR, msg.initiator); |
- } |
- AddXmlChildren(jingle, action_elems); |
- return jingle; |
-} |
- |
-void WriteSessionMessage(const SessionMessage& msg, |
- const XmlElements& action_elems, |
- buzz::XmlElement* stanza) { |
- stanza->SetAttr(buzz::QN_TO, msg.to); |
- stanza->SetAttr(buzz::QN_TYPE, buzz::STR_SET); |
- |
- if (msg.protocol == PROTOCOL_GINGLE) { |
- stanza->AddElement(WriteGingleAction(msg, action_elems)); |
- } else { |
- stanza->AddElement(WriteJingleAction(msg, action_elems)); |
- } |
-} |
- |
- |
-TransportParser* GetTransportParser(const TransportParserMap& trans_parsers, |
- const std::string& transport_type) { |
- TransportParserMap::const_iterator map = trans_parsers.find(transport_type); |
- if (map == trans_parsers.end()) { |
- return NULL; |
- } else { |
- return map->second; |
- } |
-} |
- |
-CandidateTranslator* GetCandidateTranslator( |
- const CandidateTranslatorMap& translators, |
- const std::string& content_name) { |
- CandidateTranslatorMap::const_iterator map = translators.find(content_name); |
- if (map == translators.end()) { |
- return NULL; |
- } else { |
- return map->second; |
- } |
-} |
- |
-bool GetParserAndTranslator(const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- const std::string& transport_type, |
- const std::string& content_name, |
- TransportParser** parser, |
- CandidateTranslator** translator, |
- ParseError* error) { |
- *parser = GetTransportParser(trans_parsers, transport_type); |
- if (*parser == NULL) { |
- return BadParse("unknown transport type: " + transport_type, error); |
- } |
- // Not having a translator isn't fatal when parsing. If this is called for an |
- // initiate message, we won't have our proxies set up to do the translation. |
- // Fortunately, for the cases where translation is needed, candidates are |
- // never sent in initiates. |
- *translator = GetCandidateTranslator(translators, content_name); |
- return true; |
-} |
- |
-bool GetParserAndTranslator(const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- const std::string& transport_type, |
- const std::string& content_name, |
- TransportParser** parser, |
- CandidateTranslator** translator, |
- WriteError* error) { |
- *parser = GetTransportParser(trans_parsers, transport_type); |
- if (*parser == NULL) { |
- return BadWrite("unknown transport type: " + transport_type, error); |
- } |
- *translator = GetCandidateTranslator(translators, content_name); |
- if (*translator == NULL) { |
- return BadWrite("unknown content name: " + content_name, error); |
- } |
- return true; |
-} |
- |
-bool ParseGingleCandidate(const buzz::XmlElement* candidate_elem, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- const std::string& content_name, |
- Candidates* candidates, |
- ParseError* error) { |
- TransportParser* trans_parser; |
- CandidateTranslator* translator; |
- if (!GetParserAndTranslator(trans_parsers, translators, |
- NS_GINGLE_P2P, content_name, |
- &trans_parser, &translator, error)) |
- return false; |
- |
- Candidate candidate; |
- if (!trans_parser->ParseGingleCandidate( |
- candidate_elem, translator, &candidate, error)) { |
- return false; |
- } |
- |
- candidates->push_back(candidate); |
- return true; |
-} |
- |
-bool ParseGingleCandidates(const buzz::XmlElement* parent, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- const std::string& content_name, |
- Candidates* candidates, |
- ParseError* error) { |
- for (const buzz::XmlElement* candidate_elem = parent->FirstElement(); |
- candidate_elem != NULL; |
- candidate_elem = candidate_elem->NextElement()) { |
- if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) { |
- if (!ParseGingleCandidate(candidate_elem, trans_parsers, translators, |
- content_name, candidates, error)) { |
- return false; |
- } |
- } |
- } |
- return true; |
-} |
- |
-bool ParseGingleTransportInfos(const buzz::XmlElement* action_elem, |
- const ContentInfos& contents, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- TransportInfos* tinfos, |
- ParseError* error) { |
- bool has_audio = FindContentInfoByName(contents, CN_AUDIO) != NULL; |
- bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL; |
- |
- // If we don't have media, no need to separate the candidates. |
- if (!has_audio && !has_video) { |
- TransportInfo tinfo(CN_OTHER, |
- TransportDescription(NS_GINGLE_P2P, std::string(), std::string())); |
- if (!ParseGingleCandidates(action_elem, trans_parsers, translators, |
- CN_OTHER, &tinfo.description.candidates, |
- error)) { |
- return false; |
- } |
- |
- tinfos->push_back(tinfo); |
- return true; |
- } |
- |
- // If we have media, separate the candidates. |
- TransportInfo audio_tinfo( |
- CN_AUDIO, |
- TransportDescription(NS_GINGLE_P2P, std::string(), std::string())); |
- TransportInfo video_tinfo( |
- CN_VIDEO, |
- TransportDescription(NS_GINGLE_P2P, std::string(), std::string())); |
- for (const buzz::XmlElement* candidate_elem = action_elem->FirstElement(); |
- candidate_elem != NULL; |
- candidate_elem = candidate_elem->NextElement()) { |
- if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) { |
- const std::string& channel_name = candidate_elem->Attr(buzz::QN_NAME); |
- if (has_audio && |
- (channel_name == GICE_CHANNEL_NAME_RTP || |
- channel_name == GICE_CHANNEL_NAME_RTCP)) { |
- if (!ParseGingleCandidate( |
- candidate_elem, trans_parsers, |
- translators, CN_AUDIO, |
- &audio_tinfo.description.candidates, error)) { |
- return false; |
- } |
- } else if (has_video && |
- (channel_name == GICE_CHANNEL_NAME_VIDEO_RTP || |
- channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP)) { |
- if (!ParseGingleCandidate( |
- candidate_elem, trans_parsers, |
- translators, CN_VIDEO, |
- &video_tinfo.description.candidates, error)) { |
- return false; |
- } |
- } else { |
- return BadParse("Unknown channel name: " + channel_name, error); |
- } |
- } |
- } |
- |
- if (has_audio) { |
- tinfos->push_back(audio_tinfo); |
- } |
- if (has_video) { |
- tinfos->push_back(video_tinfo); |
- } |
- return true; |
-} |
- |
-bool ParseJingleTransportInfo(const buzz::XmlElement* trans_elem, |
- const std::string& content_name, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- TransportInfo* tinfo, |
- ParseError* error) { |
- TransportParser* trans_parser; |
- CandidateTranslator* translator; |
- if (!GetParserAndTranslator(trans_parsers, translators, |
- trans_elem->Name().Namespace(), content_name, |
- &trans_parser, &translator, error)) |
- return false; |
- |
- TransportDescription tdesc; |
- if (!trans_parser->ParseTransportDescription(trans_elem, translator, |
- &tdesc, error)) |
- return false; |
- |
- *tinfo = TransportInfo(content_name, tdesc); |
- return true; |
-} |
- |
-bool ParseJingleTransportInfos(const buzz::XmlElement* jingle, |
- const ContentInfos& contents, |
- const TransportParserMap trans_parsers, |
- const CandidateTranslatorMap& translators, |
- TransportInfos* tinfos, |
- ParseError* error) { |
- for (const buzz::XmlElement* pair_elem |
- = jingle->FirstNamed(QN_JINGLE_CONTENT); |
- pair_elem != NULL; |
- pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) { |
- std::string content_name; |
- if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME, |
- &content_name, error)) |
- return false; |
- |
- const ContentInfo* content = FindContentInfoByName(contents, content_name); |
- if (!content) |
- return BadParse("Unknown content name: " + content_name, error); |
- |
- const buzz::XmlElement* trans_elem; |
- if (!RequireXmlChild(pair_elem, LN_TRANSPORT, &trans_elem, error)) |
- return false; |
- |
- TransportInfo tinfo; |
- if (!ParseJingleTransportInfo(trans_elem, content->name, |
- trans_parsers, translators, |
- &tinfo, error)) |
- return false; |
- |
- tinfos->push_back(tinfo); |
- } |
- |
- return true; |
-} |
- |
-buzz::XmlElement* NewTransportElement(const std::string& name) { |
- return new buzz::XmlElement(buzz::QName(name, LN_TRANSPORT), true); |
-} |
- |
-bool WriteGingleCandidates(const Candidates& candidates, |
- const TransportParserMap& trans_parsers, |
- const std::string& transport_type, |
- const CandidateTranslatorMap& translators, |
- const std::string& content_name, |
- XmlElements* elems, |
- WriteError* error) { |
- TransportParser* trans_parser; |
- CandidateTranslator* translator; |
- if (!GetParserAndTranslator(trans_parsers, translators, |
- transport_type, content_name, |
- &trans_parser, &translator, error)) |
- return false; |
- |
- for (size_t i = 0; i < candidates.size(); ++i) { |
- rtc::scoped_ptr<buzz::XmlElement> element; |
- if (!trans_parser->WriteGingleCandidate(candidates[i], translator, |
- element.accept(), error)) { |
- return false; |
- } |
- |
- elems->push_back(element.release()); |
- } |
- |
- return true; |
-} |
- |
-bool WriteGingleTransportInfos(const TransportInfos& tinfos, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- XmlElements* elems, |
- WriteError* error) { |
- for (TransportInfos::const_iterator tinfo = tinfos.begin(); |
- tinfo != tinfos.end(); ++tinfo) { |
- if (!WriteGingleCandidates(tinfo->description.candidates, |
- trans_parsers, tinfo->description.transport_type, |
- translators, tinfo->content_name, |
- elems, error)) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-bool WriteJingleTransportInfo(const TransportInfo& tinfo, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- XmlElements* elems, |
- WriteError* error) { |
- std::string transport_type = tinfo.description.transport_type; |
- TransportParser* trans_parser; |
- CandidateTranslator* translator; |
- if (!GetParserAndTranslator(trans_parsers, translators, |
- transport_type, tinfo.content_name, |
- &trans_parser, &translator, error)) |
- return false; |
- |
- buzz::XmlElement* trans_elem; |
- if (!trans_parser->WriteTransportDescription(tinfo.description, translator, |
- &trans_elem, error)) { |
- return false; |
- } |
- |
- elems->push_back(trans_elem); |
- return true; |
-} |
- |
-void WriteJingleContent(const std::string name, |
- const XmlElements& child_elems, |
- XmlElements* elems) { |
- buzz::XmlElement* content_elem = new buzz::XmlElement(QN_JINGLE_CONTENT); |
- content_elem->SetAttr(QN_JINGLE_CONTENT_NAME, name); |
- content_elem->SetAttr(QN_CREATOR, LN_INITIATOR); |
- AddXmlChildren(content_elem, child_elems); |
- |
- elems->push_back(content_elem); |
-} |
- |
-bool WriteJingleTransportInfos(const TransportInfos& tinfos, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- XmlElements* elems, |
- WriteError* error) { |
- for (TransportInfos::const_iterator tinfo = tinfos.begin(); |
- tinfo != tinfos.end(); ++tinfo) { |
- XmlElements content_child_elems; |
- if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators, |
- &content_child_elems, error)) |
- |
- return false; |
- |
- WriteJingleContent(tinfo->content_name, content_child_elems, elems); |
- } |
- |
- return true; |
-} |
- |
-ContentParser* GetContentParser(const ContentParserMap& content_parsers, |
- const std::string& type) { |
- ContentParserMap::const_iterator map = content_parsers.find(type); |
- if (map == content_parsers.end()) { |
- return NULL; |
- } else { |
- return map->second; |
- } |
-} |
- |
-bool ParseContentInfo(SignalingProtocol protocol, |
- const std::string& name, |
- const std::string& type, |
- const buzz::XmlElement* elem, |
- const ContentParserMap& parsers, |
- ContentInfos* contents, |
- ParseError* error) { |
- ContentParser* parser = GetContentParser(parsers, type); |
- if (parser == NULL) |
- return BadParse("unknown application content: " + type, error); |
- |
- ContentDescription* desc; |
- if (!parser->ParseContent(protocol, elem, &desc, error)) |
- return false; |
- |
- contents->push_back(ContentInfo(name, type, desc)); |
- return true; |
-} |
- |
-bool ParseContentType(const buzz::XmlElement* parent_elem, |
- std::string* content_type, |
- const buzz::XmlElement** content_elem, |
- ParseError* error) { |
- if (!RequireXmlChild(parent_elem, LN_DESCRIPTION, content_elem, error)) |
- return false; |
- |
- *content_type = (*content_elem)->Name().Namespace(); |
- return true; |
-} |
- |
-bool ParseGingleContentInfos(const buzz::XmlElement* session, |
- const ContentParserMap& content_parsers, |
- ContentInfos* contents, |
- ParseError* error) { |
- std::string content_type; |
- const buzz::XmlElement* content_elem; |
- if (!ParseContentType(session, &content_type, &content_elem, error)) |
- return false; |
- |
- if (content_type == NS_GINGLE_VIDEO) { |
- // A parser parsing audio or video content should look at the |
- // namespace and only parse the codecs relevant to that namespace. |
- // We use this to control which codecs get parsed: first audio, |
- // then video. |
- rtc::scoped_ptr<buzz::XmlElement> audio_elem( |
- new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT)); |
- CopyXmlChildren(content_elem, audio_elem.get()); |
- if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP, |
- audio_elem.get(), content_parsers, |
- contents, error)) |
- return false; |
- |
- if (!ParseContentInfo(PROTOCOL_GINGLE, CN_VIDEO, NS_JINGLE_RTP, |
- content_elem, content_parsers, |
- contents, error)) |
- return false; |
- } else if (content_type == NS_GINGLE_AUDIO) { |
- if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP, |
- content_elem, content_parsers, |
- contents, error)) |
- return false; |
- } else { |
- if (!ParseContentInfo(PROTOCOL_GINGLE, CN_OTHER, content_type, |
- content_elem, content_parsers, |
- contents, error)) |
- return false; |
- } |
- return true; |
-} |
- |
-bool ParseJingleContentInfos(const buzz::XmlElement* jingle, |
- const ContentParserMap& content_parsers, |
- ContentInfos* contents, |
- ParseError* error) { |
- for (const buzz::XmlElement* pair_elem |
- = jingle->FirstNamed(QN_JINGLE_CONTENT); |
- pair_elem != NULL; |
- pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) { |
- std::string content_name; |
- if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME, |
- &content_name, error)) |
- return false; |
- |
- std::string content_type; |
- const buzz::XmlElement* content_elem; |
- if (!ParseContentType(pair_elem, &content_type, &content_elem, error)) |
- return false; |
- |
- if (!ParseContentInfo(PROTOCOL_JINGLE, content_name, content_type, |
- content_elem, content_parsers, |
- contents, error)) |
- return false; |
- } |
- return true; |
-} |
- |
-bool ParseJingleGroupInfos(const buzz::XmlElement* jingle, |
- ContentGroups* groups, |
- ParseError* error) { |
- for (const buzz::XmlElement* pair_elem |
- = jingle->FirstNamed(QN_JINGLE_DRAFT_GROUP); |
- pair_elem != NULL; |
- pair_elem = pair_elem->NextNamed(QN_JINGLE_DRAFT_GROUP)) { |
- std::string group_name; |
- if (!RequireXmlAttr(pair_elem, QN_JINGLE_DRAFT_GROUP_TYPE, |
- &group_name, error)) |
- return false; |
- |
- ContentGroup group(group_name); |
- for (const buzz::XmlElement* child_elem |
- = pair_elem->FirstNamed(QN_JINGLE_CONTENT); |
- child_elem != NULL; |
- child_elem = child_elem->NextNamed(QN_JINGLE_CONTENT)) { |
- std::string content_name; |
- if (!RequireXmlAttr(child_elem, QN_JINGLE_CONTENT_NAME, |
- &content_name, error)) |
- return false; |
- group.AddContentName(content_name); |
- } |
- groups->push_back(group); |
- } |
- return true; |
-} |
- |
-buzz::XmlElement* WriteContentInfo(SignalingProtocol protocol, |
- const ContentInfo& content, |
- const ContentParserMap& parsers, |
- WriteError* error) { |
- ContentParser* parser = GetContentParser(parsers, content.type); |
- if (parser == NULL) { |
- BadWrite("unknown content type: " + content.type, error); |
- return NULL; |
- } |
- |
- buzz::XmlElement* elem = NULL; |
- if (!parser->WriteContent(protocol, content.description, &elem, error)) |
- return NULL; |
- |
- return elem; |
-} |
- |
-bool IsWritable(SignalingProtocol protocol, |
- const ContentInfo& content, |
- const ContentParserMap& parsers) { |
- ContentParser* parser = GetContentParser(parsers, content.type); |
- if (parser == NULL) { |
- return false; |
- } |
- |
- return parser->IsWritable(protocol, content.description); |
-} |
- |
-bool WriteGingleContentInfos(const ContentInfos& contents, |
- const ContentParserMap& parsers, |
- XmlElements* elems, |
- WriteError* error) { |
- if (contents.size() == 1 || |
- (contents.size() == 2 && |
- !IsWritable(PROTOCOL_GINGLE, contents.at(1), parsers))) { |
- if (contents.front().rejected) { |
- return BadWrite("Gingle protocol may not reject individual contents.", |
- error); |
- } |
- buzz::XmlElement* elem = WriteContentInfo( |
- PROTOCOL_GINGLE, contents.front(), parsers, error); |
- if (!elem) |
- return false; |
- |
- elems->push_back(elem); |
- } else if (contents.size() >= 2 && |
- contents.at(0).type == NS_JINGLE_RTP && |
- contents.at(1).type == NS_JINGLE_RTP) { |
- // Special-case audio + video contents so that they are "merged" |
- // into one "video" content. |
- if (contents.at(0).rejected || contents.at(1).rejected) { |
- return BadWrite("Gingle protocol may not reject individual contents.", |
- error); |
- } |
- buzz::XmlElement* audio = WriteContentInfo( |
- PROTOCOL_GINGLE, contents.at(0), parsers, error); |
- if (!audio) |
- return false; |
- |
- buzz::XmlElement* video = WriteContentInfo( |
- PROTOCOL_GINGLE, contents.at(1), parsers, error); |
- if (!video) { |
- delete audio; |
- return false; |
- } |
- |
- CopyXmlChildren(audio, video); |
- elems->push_back(video); |
- delete audio; |
- } else { |
- return BadWrite("Gingle protocol may only have one content.", error); |
- } |
- |
- return true; |
-} |
- |
-const TransportInfo* GetTransportInfoByContentName( |
- const TransportInfos& tinfos, const std::string& content_name) { |
- for (TransportInfos::const_iterator tinfo = tinfos.begin(); |
- tinfo != tinfos.end(); ++tinfo) { |
- if (content_name == tinfo->content_name) { |
- return &*tinfo; |
- } |
- } |
- return NULL; |
-} |
- |
-bool WriteJingleContents(const ContentInfos& contents, |
- const ContentParserMap& content_parsers, |
- const TransportInfos& tinfos, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- XmlElements* elems, |
- WriteError* error) { |
- for (ContentInfos::const_iterator content = contents.begin(); |
- content != contents.end(); ++content) { |
- if (content->rejected) { |
- continue; |
- } |
- const TransportInfo* tinfo = |
- GetTransportInfoByContentName(tinfos, content->name); |
- if (!tinfo) |
- return BadWrite("No transport for content: " + content->name, error); |
- |
- XmlElements pair_elems; |
- buzz::XmlElement* elem = WriteContentInfo( |
- PROTOCOL_JINGLE, *content, content_parsers, error); |
- if (!elem) |
- return false; |
- pair_elems.push_back(elem); |
- |
- if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators, |
- &pair_elems, error)) |
- return false; |
- |
- WriteJingleContent(content->name, pair_elems, elems); |
- } |
- return true; |
-} |
- |
-bool WriteJingleContentInfos(const ContentInfos& contents, |
- const ContentParserMap& content_parsers, |
- XmlElements* elems, |
- WriteError* error) { |
- for (ContentInfos::const_iterator content = contents.begin(); |
- content != contents.end(); ++content) { |
- if (content->rejected) { |
- continue; |
- } |
- XmlElements content_child_elems; |
- buzz::XmlElement* elem = WriteContentInfo( |
- PROTOCOL_JINGLE, *content, content_parsers, error); |
- if (!elem) |
- return false; |
- content_child_elems.push_back(elem); |
- WriteJingleContent(content->name, content_child_elems, elems); |
- } |
- return true; |
-} |
- |
-bool WriteJingleGroupInfo(const ContentInfos& contents, |
- const ContentGroups& groups, |
- XmlElements* elems, |
- WriteError* error) { |
- if (!groups.empty()) { |
- buzz::XmlElement* pair_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_GROUP); |
- pair_elem->SetAttr(QN_JINGLE_DRAFT_GROUP_TYPE, GROUP_TYPE_BUNDLE); |
- |
- XmlElements pair_elems; |
- for (ContentInfos::const_iterator content = contents.begin(); |
- content != contents.end(); ++content) { |
- buzz::XmlElement* child_elem = |
- new buzz::XmlElement(QN_JINGLE_CONTENT, false); |
- child_elem->SetAttr(QN_JINGLE_CONTENT_NAME, content->name); |
- pair_elems.push_back(child_elem); |
- } |
- AddXmlChildren(pair_elem, pair_elems); |
- elems->push_back(pair_elem); |
- } |
- return true; |
-} |
- |
-bool ParseContentType(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- std::string* content_type, |
- ParseError* error) { |
- const buzz::XmlElement* content_elem; |
- if (protocol == PROTOCOL_GINGLE) { |
- if (!ParseContentType(action_elem, content_type, &content_elem, error)) |
- return false; |
- |
- // Internally, we only use NS_JINGLE_RTP. |
- if (*content_type == NS_GINGLE_AUDIO || |
- *content_type == NS_GINGLE_VIDEO) |
- *content_type = NS_JINGLE_RTP; |
- } else { |
- const buzz::XmlElement* pair_elem |
- = action_elem->FirstNamed(QN_JINGLE_CONTENT); |
- if (pair_elem == NULL) |
- return BadParse("No contents found", error); |
- |
- if (!ParseContentType(pair_elem, content_type, &content_elem, error)) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-static bool ParseContentMessage( |
- SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- bool expect_transports, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- SessionInitiate* init, |
- ParseError* error) { |
- init->owns_contents = true; |
- if (protocol == PROTOCOL_GINGLE) { |
- if (!ParseGingleContentInfos(action_elem, content_parsers, |
- &init->contents, error)) |
- return false; |
- |
- if (expect_transports && |
- !ParseGingleTransportInfos(action_elem, init->contents, |
- trans_parsers, translators, |
- &init->transports, error)) |
- return false; |
- } else { |
- if (!ParseJingleContentInfos(action_elem, content_parsers, |
- &init->contents, error)) |
- return false; |
- if (!ParseJingleGroupInfos(action_elem, &init->groups, error)) |
- return false; |
- |
- if (expect_transports && |
- !ParseJingleTransportInfos(action_elem, init->contents, |
- trans_parsers, translators, |
- &init->transports, error)) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-static bool WriteContentMessage( |
- SignalingProtocol protocol, |
- const ContentInfos& contents, |
- const TransportInfos& tinfos, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& transport_parsers, |
- const CandidateTranslatorMap& translators, |
- const ContentGroups& groups, |
- XmlElements* elems, |
- WriteError* error) { |
- if (protocol == PROTOCOL_GINGLE) { |
- if (!WriteGingleContentInfos(contents, content_parsers, elems, error)) |
- return false; |
- |
- if (!WriteGingleTransportInfos(tinfos, transport_parsers, translators, |
- elems, error)) |
- return false; |
- } else { |
- if (!WriteJingleContents(contents, content_parsers, |
- tinfos, transport_parsers, translators, |
- elems, error)) |
- return false; |
- if (!WriteJingleGroupInfo(contents, groups, elems, error)) |
- return false; |
- } |
- |
- return true; |
-} |
- |
-bool ParseSessionInitiate(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- SessionInitiate* init, |
- ParseError* error) { |
- bool expect_transports = true; |
- return ParseContentMessage(protocol, action_elem, expect_transports, |
- content_parsers, trans_parsers, translators, |
- init, error); |
-} |
- |
- |
-bool WriteSessionInitiate(SignalingProtocol protocol, |
- const ContentInfos& contents, |
- const TransportInfos& tinfos, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& transport_parsers, |
- const CandidateTranslatorMap& translators, |
- const ContentGroups& groups, |
- XmlElements* elems, |
- WriteError* error) { |
- return WriteContentMessage(protocol, contents, tinfos, |
- content_parsers, transport_parsers, translators, |
- groups, |
- elems, error); |
-} |
- |
-bool ParseSessionAccept(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& transport_parsers, |
- const CandidateTranslatorMap& translators, |
- SessionAccept* accept, |
- ParseError* error) { |
- bool expect_transports = true; |
- return ParseContentMessage(protocol, action_elem, expect_transports, |
- content_parsers, transport_parsers, translators, |
- accept, error); |
-} |
- |
-bool WriteSessionAccept(SignalingProtocol protocol, |
- const ContentInfos& contents, |
- const TransportInfos& tinfos, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& transport_parsers, |
- const CandidateTranslatorMap& translators, |
- const ContentGroups& groups, |
- XmlElements* elems, |
- WriteError* error) { |
- return WriteContentMessage(protocol, contents, tinfos, |
- content_parsers, transport_parsers, translators, |
- groups, |
- elems, error); |
-} |
- |
-bool ParseSessionTerminate(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- SessionTerminate* term, |
- ParseError* error) { |
- if (protocol == PROTOCOL_GINGLE) { |
- const buzz::XmlElement* reason_elem = action_elem->FirstElement(); |
- if (reason_elem != NULL) { |
- term->reason = reason_elem->Name().LocalPart(); |
- const buzz::XmlElement *debug_elem = reason_elem->FirstElement(); |
- if (debug_elem != NULL) { |
- term->debug_reason = debug_elem->Name().LocalPart(); |
- } |
- } |
- return true; |
- } else { |
- const buzz::XmlElement* reason_elem = |
- action_elem->FirstNamed(QN_JINGLE_REASON); |
- if (reason_elem) { |
- reason_elem = reason_elem->FirstElement(); |
- if (reason_elem) { |
- term->reason = reason_elem->Name().LocalPart(); |
- } |
- } |
- return true; |
- } |
-} |
- |
-void WriteSessionTerminate(SignalingProtocol protocol, |
- const SessionTerminate& term, |
- XmlElements* elems) { |
- if (protocol == PROTOCOL_GINGLE) { |
- elems->push_back(new buzz::XmlElement(buzz::QName(NS_GINGLE, term.reason))); |
- } else { |
- if (!term.reason.empty()) { |
- buzz::XmlElement* reason_elem = new buzz::XmlElement(QN_JINGLE_REASON); |
- reason_elem->AddElement(new buzz::XmlElement( |
- buzz::QName(NS_JINGLE, term.reason))); |
- elems->push_back(reason_elem); |
- } |
- } |
-} |
- |
-bool ParseDescriptionInfo(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- const ContentParserMap& content_parsers, |
- const TransportParserMap& transport_parsers, |
- const CandidateTranslatorMap& translators, |
- DescriptionInfo* description_info, |
- ParseError* error) { |
- bool expect_transports = false; |
- return ParseContentMessage(protocol, action_elem, expect_transports, |
- content_parsers, transport_parsers, translators, |
- description_info, error); |
-} |
- |
-bool WriteDescriptionInfo(SignalingProtocol protocol, |
- const ContentInfos& contents, |
- const ContentParserMap& content_parsers, |
- XmlElements* elems, |
- WriteError* error) { |
- if (protocol == PROTOCOL_GINGLE) { |
- return WriteGingleContentInfos(contents, content_parsers, elems, error); |
- } else { |
- return WriteJingleContentInfos(contents, content_parsers, elems, error); |
- } |
-} |
- |
-bool ParseTransportInfos(SignalingProtocol protocol, |
- const buzz::XmlElement* action_elem, |
- const ContentInfos& contents, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- TransportInfos* tinfos, |
- ParseError* error) { |
- if (protocol == PROTOCOL_GINGLE) { |
- return ParseGingleTransportInfos( |
- action_elem, contents, trans_parsers, translators, tinfos, error); |
- } else { |
- return ParseJingleTransportInfos( |
- action_elem, contents, trans_parsers, translators, tinfos, error); |
- } |
-} |
- |
-bool WriteTransportInfos(SignalingProtocol protocol, |
- const TransportInfos& tinfos, |
- const TransportParserMap& trans_parsers, |
- const CandidateTranslatorMap& translators, |
- XmlElements* elems, |
- WriteError* error) { |
- if (protocol == PROTOCOL_GINGLE) { |
- return WriteGingleTransportInfos(tinfos, trans_parsers, translators, |
- elems, error); |
- } else { |
- return WriteJingleTransportInfos(tinfos, trans_parsers, translators, |
- elems, error); |
- } |
-} |
- |
-bool GetUriTarget(const std::string& prefix, const std::string& str, |
- std::string* after) { |
- size_t pos = str.find(prefix); |
- if (pos == std::string::npos) |
- return false; |
- |
- *after = str.substr(pos + prefix.size(), std::string::npos); |
- return true; |
-} |
- |
-bool FindSessionRedirect(const buzz::XmlElement* stanza, |
- SessionRedirect* redirect) { |
- const buzz::XmlElement* error_elem = GetXmlChild(stanza, LN_ERROR); |
- if (error_elem == NULL) |
- return false; |
- |
- const buzz::XmlElement* redirect_elem = |
- error_elem->FirstNamed(QN_GINGLE_REDIRECT); |
- if (redirect_elem == NULL) |
- redirect_elem = error_elem->FirstNamed(buzz::QN_STANZA_REDIRECT); |
- if (redirect_elem == NULL) |
- return false; |
- |
- if (!GetUriTarget(STR_REDIRECT_PREFIX, redirect_elem->BodyText(), |
- &redirect->target)) |
- return false; |
- |
- return true; |
-} |
- |
-} // namespace cricket |