10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2010, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/sessionmessages.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <stdio.h>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <string>
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/constants.h"
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/p2ptransport.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/parsing.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/sessionclient.h"
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/sessiondescription.h"
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/p2p/base/transport.h"
3913b2d035e2e7f2f18e3a4d3377bc1a09f43a4ff9buildbot@webrtc.org#include "webrtc/libjingle/xmllite/xmlconstants.h"
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/xmpp/constants.h"
41cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h"
42cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/scoped_ptr.h"
43cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/stringutils.h"
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgActionType ToActionType(const std::string& type) {
480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_INITIATE)
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_INITIATE;
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_INFO)
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_INFO;
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_ACCEPT)
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_ACCEPT;
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_REJECT)
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_REJECT;
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_TERMINATE)
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_TERMINATE;
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_CANDIDATES)
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_TRANSPORT_INFO;
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_SESSION_INITIATE)
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_INITIATE;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_TRANSPORT_INFO)
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_TRANSPORT_INFO;
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_TRANSPORT_ACCEPT;
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_SESSION_INFO)
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_INFO;
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_SESSION_ACCEPT)
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_ACCEPT;
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_SESSION_TERMINATE)
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_SESSION_TERMINATE;
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_TRANSPORT_INFO)
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_TRANSPORT_INFO;
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_TRANSPORT_ACCEPT;
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == JINGLE_ACTION_DESCRIPTION_INFO)
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_DESCRIPTION_INFO;
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (type == GINGLE_ACTION_UPDATE)
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ACTION_DESCRIPTION_INFO;
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ACTION_UNKNOWN;
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ToJingleString(ActionType type) {
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (type) {
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_INITIATE:
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_SESSION_INITIATE;
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_INFO:
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_SESSION_INFO;
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_DESCRIPTION_INFO:
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_DESCRIPTION_INFO;
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_ACCEPT:
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_SESSION_ACCEPT;
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Notice that reject and terminate both go to
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // "session-terminate", but there is no "session-reject".
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_REJECT:
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_TERMINATE:
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_SESSION_TERMINATE;
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_TRANSPORT_INFO:
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_TRANSPORT_INFO;
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_TRANSPORT_ACCEPT:
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return JINGLE_ACTION_TRANSPORT_ACCEPT;
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "";
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ToGingleString(ActionType type) {
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (type) {
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_INITIATE:
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_INITIATE;
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_INFO:
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_INFO;
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_ACCEPT:
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_ACCEPT;
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_REJECT:
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_REJECT;
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_SESSION_TERMINATE:
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_TERMINATE;
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case ACTION_TRANSPORT_INFO:
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return GINGLE_ACTION_CANDIDATES;
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return "";
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool IsJingleMessage(const buzz::XmlElement* stanza) {
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (jingle == NULL)
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (jingle->HasAttr(buzz::QN_ACTION) && jingle->HasAttr(QN_SID));
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool IsGingleMessage(const buzz::XmlElement* stanza) {
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session == NULL)
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (session->HasAttr(buzz::QN_TYPE) &&
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          session->HasAttr(buzz::QN_ID)   &&
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          session->HasAttr(QN_INITIATOR));
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool IsSessionMessage(const buzz::XmlElement* stanza) {
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return (stanza->Name() == buzz::QN_IQ &&
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET &&
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (IsJingleMessage(stanza) ||
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           IsGingleMessage(stanza)));
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleSessionMessage(const buzz::XmlElement* session,
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               SessionMessage* msg,
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               ParseError* error) {
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->protocol = PROTOCOL_GINGLE;
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string type_string = session->Attr(buzz::QN_TYPE);
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->type = ToActionType(type_string);
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->sid = session->Attr(buzz::QN_ID);
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->initiator = session->Attr(QN_INITIATOR);
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->action_elem = session;
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (msg->type == ACTION_UNKNOWN)
1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("unknown action: " + type_string, error);
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleSessionMessage(const buzz::XmlElement* jingle,
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               SessionMessage* msg,
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               ParseError* error) {
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->protocol = PROTOCOL_JINGLE;
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string type_string = jingle->Attr(buzz::QN_ACTION);
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->type = ToActionType(type_string);
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->sid = jingle->Attr(QN_SID);
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, buzz::STR_EMPTY);
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->action_elem = jingle;
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (msg->type == ACTION_UNKNOWN)
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("unknown action: " + type_string, error);
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseHybridSessionMessage(const buzz::XmlElement* jingle,
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               SessionMessage* msg,
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               ParseError* error) {
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ParseJingleSessionMessage(jingle, msg, error))
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->protocol = PROTOCOL_HYBRID;
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseSessionMessage(const buzz::XmlElement* stanza,
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         SessionMessage* msg,
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         ParseError* error) {
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->id = stanza->Attr(buzz::QN_ID);
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->from = stanza->Attr(buzz::QN_FROM);
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->to = stanza->Attr(buzz::QN_TO);
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  msg->stanza = stanza;
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (jingle && session)
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ParseHybridSessionMessage(jingle, msg, error);
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (jingle != NULL)
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ParseJingleSessionMessage(jingle, msg, error);
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (session != NULL)
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ParseGingleSessionMessage(session, msg, error);
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return false;
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* WriteGingleAction(const SessionMessage& msg,
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                    const XmlElements& action_elems) {
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* session = new buzz::XmlElement(QN_GINGLE_SESSION, true);
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session->AddAttr(buzz::QN_TYPE, ToGingleString(msg.type));
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session->AddAttr(buzz::QN_ID, msg.sid);
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  session->AddAttr(QN_INITIATOR, msg.initiator);
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddXmlChildren(session, action_elems);
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return session;
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* WriteJingleAction(const SessionMessage& msg,
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                    const XmlElements& action_elems) {
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* jingle = new buzz::XmlElement(QN_JINGLE, true);
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  jingle->AddAttr(buzz::QN_ACTION, ToJingleString(msg.type));
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  jingle->AddAttr(QN_SID, msg.sid);
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (msg.type == ACTION_SESSION_INITIATE) {
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    jingle->AddAttr(QN_INITIATOR, msg.initiator);
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddXmlChildren(jingle, action_elems);
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return jingle;
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WriteSessionMessage(const SessionMessage& msg,
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const XmlElements& action_elems,
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         buzz::XmlElement* stanza) {
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stanza->SetAttr(buzz::QN_TO, msg.to);
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  stanza->SetAttr(buzz::QN_TYPE, buzz::STR_SET);
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (msg.protocol == PROTOCOL_GINGLE) {
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stanza->AddElement(WriteGingleAction(msg, action_elems));
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    stanza->AddElement(WriteJingleAction(msg, action_elems));
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgTransportParser* GetTransportParser(const TransportParserMap& trans_parsers,
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                    const std::string& transport_type) {
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportParserMap::const_iterator map = trans_parsers.find(transport_type);
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (map == trans_parsers.end()) {
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return map->second;
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCandidateTranslator* GetCandidateTranslator(
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const CandidateTranslatorMap& translators,
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& content_name) {
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CandidateTranslatorMap::const_iterator map = translators.find(content_name);
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (map == translators.end()) {
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return map->second;
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GetParserAndTranslator(const TransportParserMap& trans_parsers,
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const CandidateTranslatorMap& translators,
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const std::string& transport_type,
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const std::string& content_name,
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            TransportParser** parser,
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            CandidateTranslator** translator,
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            ParseError* error) {
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *parser = GetTransportParser(trans_parsers, transport_type);
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (*parser == NULL) {
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("unknown transport type: " + transport_type, error);
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Not having a translator isn't fatal when parsing. If this is called for an
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // initiate message, we won't have our proxies set up to do the translation.
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Fortunately, for the cases where translation is needed, candidates are
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // never sent in initiates.
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *translator = GetCandidateTranslator(translators, content_name);
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GetParserAndTranslator(const TransportParserMap& trans_parsers,
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const CandidateTranslatorMap& translators,
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const std::string& transport_type,
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            const std::string& content_name,
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            TransportParser** parser,
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            CandidateTranslator** translator,
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                            WriteError* error) {
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *parser = GetTransportParser(trans_parsers, transport_type);
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (*parser == NULL) {
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadWrite("unknown transport type: " + transport_type, error);
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *translator = GetCandidateTranslator(translators, content_name);
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (*translator == NULL) {
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadWrite("unknown content name: " + content_name, error);
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleCandidate(const buzz::XmlElement* candidate_elem,
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const TransportParserMap& trans_parsers,
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const CandidateTranslatorMap& translators,
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const std::string& content_name,
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          Candidates* candidates,
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          ParseError* error) {
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportParser* trans_parser;
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CandidateTranslator* translator;
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetParserAndTranslator(trans_parsers, translators,
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              NS_GINGLE_P2P, content_name,
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              &trans_parser, &translator, error))
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Candidate candidate;
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!trans_parser->ParseGingleCandidate(
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          candidate_elem, translator, &candidate, error)) {
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  candidates->push_back(candidate);
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleCandidates(const buzz::XmlElement* parent,
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const TransportParserMap& trans_parsers,
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const CandidateTranslatorMap& translators,
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const std::string& content_name,
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           Candidates* candidates,
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ParseError* error) {
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const buzz::XmlElement* candidate_elem = parent->FirstElement();
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       candidate_elem != NULL;
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       candidate_elem = candidate_elem->NextElement()) {
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!ParseGingleCandidate(candidate_elem, trans_parsers, translators,
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                content_name, candidates, error)) {
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleTransportInfos(const buzz::XmlElement* action_elem,
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const ContentInfos& contents,
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const TransportParserMap& trans_parsers,
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const CandidateTranslatorMap& translators,
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               TransportInfos* tinfos,
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               ParseError* error) {
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool has_audio = FindContentInfoByName(contents, CN_AUDIO) != NULL;
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL;
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we don't have media, no need to separate the candidates.
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!has_audio && !has_video) {
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportInfo tinfo(CN_OTHER,
362a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org        TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseGingleCandidates(action_elem, trans_parsers, translators,
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               CN_OTHER, &tinfo.description.candidates,
3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               error)) {
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tinfos->push_back(tinfo);
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we have media, separate the candidates.
374a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  TransportInfo audio_tinfo(
375a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      CN_AUDIO,
376a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
377a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org  TransportInfo video_tinfo(
378a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      CN_VIDEO,
379a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org      TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const buzz::XmlElement* candidate_elem = action_elem->FirstElement();
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       candidate_elem != NULL;
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       candidate_elem = candidate_elem->NextElement()) {
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      const std::string& channel_name = candidate_elem->Attr(buzz::QN_NAME);
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (has_audio &&
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          (channel_name == GICE_CHANNEL_NAME_RTP ||
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           channel_name == GICE_CHANNEL_NAME_RTCP)) {
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!ParseGingleCandidate(
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                candidate_elem, trans_parsers,
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                translators, CN_AUDIO,
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                &audio_tinfo.description.candidates, error)) {
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return false;
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else if (has_video &&
3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 (channel_name == GICE_CHANNEL_NAME_VIDEO_RTP ||
3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP)) {
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        if (!ParseGingleCandidate(
3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                candidate_elem, trans_parsers,
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                translators, CN_VIDEO,
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                &video_tinfo.description.candidates, error)) {
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          return false;
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        }
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      } else {
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return BadParse("Unknown channel name: " + channel_name, error);
4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (has_audio) {
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tinfos->push_back(audio_tinfo);
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (has_video) {
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tinfos->push_back(video_tinfo);
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleTransportInfo(const buzz::XmlElement* trans_elem,
4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const std::string& content_name,
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const TransportParserMap& trans_parsers,
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const CandidateTranslatorMap& translators,
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              TransportInfo* tinfo,
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              ParseError* error) {
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportParser* trans_parser;
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CandidateTranslator* translator;
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetParserAndTranslator(trans_parsers, translators,
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              trans_elem->Name().Namespace(), content_name,
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              &trans_parser, &translator, error))
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportDescription tdesc;
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!trans_parser->ParseTransportDescription(trans_elem, translator,
4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                               &tdesc, error))
4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *tinfo = TransportInfo(content_name, tdesc);
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleTransportInfos(const buzz::XmlElement* jingle,
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const ContentInfos& contents,
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const TransportParserMap trans_parsers,
4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const CandidateTranslatorMap& translators,
4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               TransportInfos* tinfos,
4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               ParseError* error) {
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const buzz::XmlElement* pair_elem
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           = jingle->FirstNamed(QN_JINGLE_CONTENT);
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem != NULL;
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string content_name;
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        &content_name, error))
4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ContentInfo* content = FindContentInfoByName(contents, content_name);
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!content)
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return BadParse("Unknown content name: " + content_name, error);
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* trans_elem;
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!RequireXmlChild(pair_elem, LN_TRANSPORT, &trans_elem, error))
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    TransportInfo tinfo;
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseJingleTransportInfo(trans_elem, content->name,
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  trans_parsers, translators,
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  &tinfo, error))
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    tinfos->push_back(tinfo);
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* NewTransportElement(const std::string& name) {
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return new buzz::XmlElement(buzz::QName(name, LN_TRANSPORT), true);
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteGingleCandidates(const Candidates& candidates,
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const TransportParserMap& trans_parsers,
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const std::string& transport_type,
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const CandidateTranslatorMap& translators,
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const std::string& content_name,
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           XmlElements* elems,
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           WriteError* error) {
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportParser* trans_parser;
4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CandidateTranslator* translator;
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetParserAndTranslator(trans_parsers, translators,
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              transport_type, content_name,
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              &trans_parser, &translator, error))
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < candidates.size(); ++i) {
4942a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::scoped_ptr<buzz::XmlElement> element;
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!trans_parser->WriteGingleCandidate(candidates[i], translator,
4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                            element.accept(), error)) {
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    elems->push_back(element.release());
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteGingleTransportInfos(const TransportInfos& tinfos,
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const TransportParserMap& trans_parsers,
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const CandidateTranslatorMap& translators,
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               XmlElements* elems,
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               WriteError* error) {
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (TransportInfos::const_iterator tinfo = tinfos.begin();
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       tinfo != tinfos.end(); ++tinfo) {
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteGingleCandidates(tinfo->description.candidates,
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               trans_parsers, tinfo->description.transport_type,
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               translators, tinfo->content_name,
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               elems, error))
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteJingleTransportInfo(const TransportInfo& tinfo,
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const TransportParserMap& trans_parsers,
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              const CandidateTranslatorMap& translators,
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              XmlElements* elems,
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              WriteError* error) {
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string transport_type = tinfo.description.transport_type;
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  TransportParser* trans_parser;
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CandidateTranslator* translator;
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetParserAndTranslator(trans_parsers, translators,
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              transport_type, tinfo.content_name,
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                              &trans_parser, &translator, error))
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* trans_elem;
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!trans_parser->WriteTransportDescription(tinfo.description, translator,
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                               &trans_elem, error)) {
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  elems->push_back(trans_elem);
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WriteJingleContent(const std::string name,
5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const XmlElements& child_elems,
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        XmlElements* elems) {
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* content_elem = new buzz::XmlElement(QN_JINGLE_CONTENT);
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  content_elem->SetAttr(QN_JINGLE_CONTENT_NAME, name);
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  content_elem->SetAttr(QN_CREATOR, LN_INITIATOR);
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddXmlChildren(content_elem, child_elems);
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  elems->push_back(content_elem);
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteJingleTransportInfos(const TransportInfos& tinfos,
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const TransportParserMap& trans_parsers,
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               const CandidateTranslatorMap& translators,
5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               XmlElements* elems,
5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               WriteError* error) {
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (TransportInfos::const_iterator tinfo = tinfos.begin();
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       tinfo != tinfos.end(); ++tinfo) {
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElements content_child_elems;
5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  &content_child_elems, error))
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WriteJingleContent(tinfo->content_name, content_child_elems, elems);
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgContentParser* GetContentParser(const ContentParserMap& content_parsers,
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                const std::string& type) {
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ContentParserMap::const_iterator map = content_parsers.find(type);
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (map == content_parsers.end()) {
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return map->second;
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseContentInfo(SignalingProtocol protocol,
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const std::string& name,
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const std::string& type,
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const buzz::XmlElement* elem,
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const ContentParserMap& parsers,
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      ContentInfos* contents,
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      ParseError* error) {
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ContentParser* parser = GetContentParser(parsers, type);
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (parser == NULL)
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadParse("unknown application content: " + type, error);
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ContentDescription* desc;
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parser->ParseContent(protocol, elem, &desc, error))
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  contents->push_back(ContentInfo(name, type, desc));
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseContentType(const buzz::XmlElement* parent_elem,
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      std::string* content_type,
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const buzz::XmlElement** content_elem,
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      ParseError* error) {
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!RequireXmlChild(parent_elem, LN_DESCRIPTION, content_elem, error))
6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *content_type = (*content_elem)->Name().Namespace();
6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseGingleContentInfos(const buzz::XmlElement* session,
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const ContentParserMap& content_parsers,
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ContentInfos* contents,
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ParseError* error) {
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string content_type;
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* content_elem;
6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ParseContentType(session, &content_type, &content_elem, error))
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (content_type == NS_GINGLE_VIDEO) {
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // A parser parsing audio or video content should look at the
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // namespace and only parse the codecs relevant to that namespace.
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We use this to control which codecs get parsed: first audio,
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // then video.
6302a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::scoped_ptr<buzz::XmlElement> audio_elem(
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT));
6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CopyXmlChildren(content_elem, audio_elem.get());
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          audio_elem.get(), content_parsers,
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          contents, error))
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_VIDEO, NS_JINGLE_RTP,
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          content_elem, content_parsers,
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          contents, error))
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (content_type == NS_GINGLE_AUDIO) {
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          content_elem, content_parsers,
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          contents, error))
6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_OTHER, content_type,
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          content_elem, content_parsers,
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          contents, error))
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleContentInfos(const buzz::XmlElement* jingle,
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const ContentParserMap& content_parsers,
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ContentInfos* contents,
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             ParseError* error) {
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const buzz::XmlElement* pair_elem
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           = jingle->FirstNamed(QN_JINGLE_CONTENT);
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem != NULL;
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string content_name;
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        &content_name, error))
6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string content_type;
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* content_elem;
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentType(pair_elem, &content_type, &content_elem, error))
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentInfo(PROTOCOL_JINGLE, content_name, content_type,
6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          content_elem, content_parsers,
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          contents, error))
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseJingleGroupInfos(const buzz::XmlElement* jingle,
6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ContentGroups* groups,
6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ParseError* error) {
6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (const buzz::XmlElement* pair_elem
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           = jingle->FirstNamed(QN_JINGLE_DRAFT_GROUP);
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem != NULL;
6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       pair_elem = pair_elem->NextNamed(QN_JINGLE_DRAFT_GROUP)) {
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::string group_name;
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!RequireXmlAttr(pair_elem, QN_JINGLE_DRAFT_GROUP_TYPE,
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        &group_name, error))
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ContentGroup group(group_name);
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (const buzz::XmlElement* child_elem
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org             = pair_elem->FirstNamed(QN_JINGLE_CONTENT);
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        child_elem != NULL;
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        child_elem = child_elem->NextNamed(QN_JINGLE_CONTENT)) {
6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string content_name;
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (!RequireXmlAttr(child_elem, QN_JINGLE_CONTENT_NAME,
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          &content_name, error))
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        return false;
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      group.AddContentName(content_name);
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    groups->push_back(group);
7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbuzz::XmlElement* WriteContentInfo(SignalingProtocol protocol,
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const ContentInfo& content,
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   const ContentParserMap& parsers,
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   WriteError* error) {
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ContentParser* parser = GetContentParser(parsers, content.type);
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (parser == NULL) {
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    BadWrite("unknown content type: " + content.type, error);
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  buzz::XmlElement* elem = NULL;
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!parser->WriteContent(protocol, content.description, &elem, error))
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return NULL;
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return elem;
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool IsWritable(SignalingProtocol protocol,
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                const ContentInfo& content,
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                const ContentParserMap& parsers) {
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ContentParser* parser = GetContentParser(parsers, content.type);
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (parser == NULL) {
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return parser->IsWritable(protocol, content.description);
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteGingleContentInfos(const ContentInfos& contents,
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const ContentParserMap& parsers,
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             XmlElements* elems,
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             WriteError* error) {
7420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (contents.size() == 1 ||
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (contents.size() == 2 &&
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       !IsWritable(PROTOCOL_GINGLE, contents.at(1), parsers))) {
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (contents.front().rejected) {
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return BadWrite("Gingle protocol may not reject individual contents.",
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      error);
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* elem = WriteContentInfo(
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        PROTOCOL_GINGLE, contents.front(), parsers, error);
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!elem)
7520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    elems->push_back(elem);
7550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (contents.size() >= 2 &&
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org             contents.at(0).type == NS_JINGLE_RTP &&
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org             contents.at(1).type == NS_JINGLE_RTP) {
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     // Special-case audio + video contents so that they are "merged"
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org     // into one "video" content.
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (contents.at(0).rejected || contents.at(1).rejected) {
7610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return BadWrite("Gingle protocol may not reject individual contents.",
7620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      error);
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* audio = WriteContentInfo(
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        PROTOCOL_GINGLE, contents.at(0), parsers, error);
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!audio)
7670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* video = WriteContentInfo(
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        PROTOCOL_GINGLE, contents.at(1), parsers, error);
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!video) {
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      delete audio;
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CopyXmlChildren(audio, video);
7770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    elems->push_back(video);
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete audio;
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return BadWrite("Gingle protocol may only have one content.", error);
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst TransportInfo* GetTransportInfoByContentName(
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportInfos& tinfos, const std::string& content_name) {
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (TransportInfos::const_iterator tinfo = tinfos.begin();
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       tinfo != tinfos.end(); ++tinfo) {
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (content_name == tinfo->content_name) {
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return &*tinfo;
7920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return NULL;
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteJingleContents(const ContentInfos& contents,
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const ContentParserMap& content_parsers,
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const TransportInfos& tinfos,
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const TransportParserMap& trans_parsers,
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const CandidateTranslatorMap& translators,
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         XmlElements* elems,
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         WriteError* error) {
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ContentInfos::const_iterator content = contents.begin();
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       content != contents.end(); ++content) {
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (content->rejected) {
8070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      continue;
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportInfo* tinfo =
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        GetTransportInfoByContentName(tinfos, content->name);
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!tinfo)
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return BadWrite("No transport for content: " + content->name, error);
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElements pair_elems;
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* elem = WriteContentInfo(
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        PROTOCOL_JINGLE, *content, content_parsers, error);
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!elem)
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    pair_elems.push_back(elem);
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  &pair_elems, error))
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WriteJingleContent(content->name, pair_elems, elems);
8260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteJingleContentInfos(const ContentInfos& contents,
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             const ContentParserMap& content_parsers,
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             XmlElements* elems,
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             WriteError* error) {
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (ContentInfos::const_iterator content = contents.begin();
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       content != contents.end(); ++content) {
8360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (content->rejected) {
8370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      continue;
8380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElements content_child_elems;
8400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* elem = WriteContentInfo(
8410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        PROTOCOL_JINGLE, *content, content_parsers, error);
8420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!elem)
8430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
8440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    content_child_elems.push_back(elem);
8450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WriteJingleContent(content->name, content_child_elems, elems);
8460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteJingleGroupInfo(const ContentInfos& contents,
8510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentGroups& groups,
8520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          XmlElements* elems,
8530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          WriteError* error) {
8540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!groups.empty()) {
8550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    buzz::XmlElement* pair_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_GROUP);
8560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    pair_elem->SetAttr(QN_JINGLE_DRAFT_GROUP_TYPE, GROUP_TYPE_BUNDLE);
8570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElements pair_elems;
8590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (ContentInfos::const_iterator content = contents.begin();
8600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         content != contents.end(); ++content) {
8610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buzz::XmlElement* child_elem =
8620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          new buzz::XmlElement(QN_JINGLE_CONTENT, false);
8630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      child_elem->SetAttr(QN_JINGLE_CONTENT_NAME, content->name);
8640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      pair_elems.push_back(child_elem);
8650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
8660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    AddXmlChildren(pair_elem, pair_elems);
8670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    elems->push_back(pair_elem);
8680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseContentType(SignalingProtocol protocol,
8730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      const buzz::XmlElement* action_elem,
8740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      std::string* content_type,
8750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                      ParseError* error) {
8760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* content_elem;
8770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
8780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentType(action_elem, content_type, &content_elem, error))
8790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
8800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Internally, we only use NS_JINGLE_RTP.
8820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (*content_type == NS_GINGLE_AUDIO ||
8830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        *content_type == NS_GINGLE_VIDEO)
8840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *content_type = NS_JINGLE_RTP;
8850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* pair_elem
8870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        = action_elem->FirstNamed(QN_JINGLE_CONTENT);
8880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (pair_elem == NULL)
8890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return BadParse("No contents found", error);
8900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseContentType(pair_elem, content_type, &content_elem, error))
8920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
8930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
8960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool ParseContentMessage(
8990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalingProtocol protocol,
9000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* action_elem,
9010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    bool expect_transports,
9020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ContentParserMap& content_parsers,
9030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportParserMap& trans_parsers,
9040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const CandidateTranslatorMap& translators,
9050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SessionInitiate* init,
9060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ParseError* error) {
9070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  init->owns_contents = true;
9080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
9090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseGingleContentInfos(action_elem, content_parsers,
9100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 &init->contents, error))
9110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (expect_transports &&
9140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        !ParseGingleTransportInfos(action_elem, init->contents,
9150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   trans_parsers, translators,
9160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   &init->transports, error))
9170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
9190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseJingleContentInfos(action_elem, content_parsers,
9200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 &init->contents, error))
9210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!ParseJingleGroupInfos(action_elem, &init->groups, error))
9230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (expect_transports &&
9260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        !ParseJingleTransportInfos(action_elem, init->contents,
9270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   trans_parsers, translators,
9280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   &init->transports, error))
9290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic bool WriteContentMessage(
9360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalingProtocol protocol,
9370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ContentInfos& contents,
9380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportInfos& tinfos,
9390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ContentParserMap& content_parsers,
9400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const TransportParserMap& transport_parsers,
9410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const CandidateTranslatorMap& translators,
9420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ContentGroups& groups,
9430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    XmlElements* elems,
9440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    WriteError* error) {
9450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
9460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteGingleContentInfos(contents, content_parsers, elems, error))
9470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteGingleTransportInfos(tinfos, transport_parsers, translators,
9500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   elems, error))
9510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
9530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteJingleContents(contents, content_parsers,
9540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             tinfos, transport_parsers, translators,
9550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             elems, error))
9560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!WriteJingleGroupInfo(contents, groups, elems, error))
9580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return false;
9590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
9600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
9620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseSessionInitiate(SignalingProtocol protocol,
9650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const buzz::XmlElement* action_elem,
9660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentParserMap& content_parsers,
9670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const TransportParserMap& trans_parsers,
9680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const CandidateTranslatorMap& translators,
9690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          SessionInitiate* init,
9700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          ParseError* error) {
9710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool expect_transports = true;
9720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ParseContentMessage(protocol, action_elem, expect_transports,
9730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             content_parsers, trans_parsers, translators,
9740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             init, error);
9750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteSessionInitiate(SignalingProtocol protocol,
9790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentInfos& contents,
9800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const TransportInfos& tinfos,
9810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentParserMap& content_parsers,
9820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const TransportParserMap& transport_parsers,
9830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const CandidateTranslatorMap& translators,
9840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentGroups& groups,
9850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          XmlElements* elems,
9860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          WriteError* error) {
9870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return WriteContentMessage(protocol, contents, tinfos,
9880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             content_parsers, transport_parsers, translators,
9890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             groups,
9900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             elems, error);
9910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
9920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
9930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseSessionAccept(SignalingProtocol protocol,
9940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const buzz::XmlElement* action_elem,
9950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const ContentParserMap& content_parsers,
9960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const TransportParserMap& transport_parsers,
9970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const CandidateTranslatorMap& translators,
9980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        SessionAccept* accept,
9990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        ParseError* error) {
10000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool expect_transports = true;
10010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ParseContentMessage(protocol, action_elem, expect_transports,
10020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             content_parsers, transport_parsers, translators,
10030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             accept, error);
10040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteSessionAccept(SignalingProtocol protocol,
10070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const ContentInfos& contents,
10080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const TransportInfos& tinfos,
10090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const ContentParserMap& content_parsers,
10100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const TransportParserMap& transport_parsers,
10110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const CandidateTranslatorMap& translators,
10120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        const ContentGroups& groups,
10130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        XmlElements* elems,
10140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                        WriteError* error) {
10150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return WriteContentMessage(protocol, contents, tinfos,
10160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             content_parsers, transport_parsers, translators,
10170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             groups,
10180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             elems, error);
10190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseSessionTerminate(SignalingProtocol protocol,
10220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const buzz::XmlElement* action_elem,
10230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           SessionTerminate* term,
10240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           ParseError* error) {
10250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
10260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* reason_elem = action_elem->FirstElement();
10270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (reason_elem != NULL) {
10280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      term->reason = reason_elem->Name().LocalPart();
10290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      const buzz::XmlElement *debug_elem = reason_elem->FirstElement();
10300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (debug_elem != NULL) {
10310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        term->debug_reason = debug_elem->Name().LocalPart();
10320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
10330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
10350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const buzz::XmlElement* reason_elem =
10370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        action_elem->FirstNamed(QN_JINGLE_REASON);
10380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (reason_elem) {
10390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      reason_elem = reason_elem->FirstElement();
10400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (reason_elem) {
10410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        term->reason = reason_elem->Name().LocalPart();
10420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
10430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return true;
10450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid WriteSessionTerminate(SignalingProtocol protocol,
10490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           const SessionTerminate& term,
10500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           XmlElements* elems) {
10510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
10520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    elems->push_back(new buzz::XmlElement(buzz::QName(NS_GINGLE, term.reason)));
10530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!term.reason.empty()) {
10550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      buzz::XmlElement* reason_elem = new buzz::XmlElement(QN_JINGLE_REASON);
10560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      reason_elem->AddElement(new buzz::XmlElement(
10570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org          buzz::QName(NS_JINGLE, term.reason)));
10580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      elems->push_back(reason_elem);
10590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
10600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseDescriptionInfo(SignalingProtocol protocol,
10640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const buzz::XmlElement* action_elem,
10650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentParserMap& content_parsers,
10660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const TransportParserMap& transport_parsers,
10670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const CandidateTranslatorMap& translators,
10680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          DescriptionInfo* description_info,
10690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          ParseError* error) {
10700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool expect_transports = false;
10710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return ParseContentMessage(protocol, action_elem, expect_transports,
10720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             content_parsers, transport_parsers, translators,
10730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                             description_info, error);
10740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteDescriptionInfo(SignalingProtocol protocol,
10770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentInfos& contents,
10780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const ContentParserMap& content_parsers,
10790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          XmlElements* elems,
10800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          WriteError* error) {
10810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
10820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return WriteGingleContentInfos(contents, content_parsers, elems, error);
10830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return WriteJingleContentInfos(contents, content_parsers, elems, error);
10850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
10860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
10870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
10880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ParseTransportInfos(SignalingProtocol protocol,
10890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const buzz::XmlElement* action_elem,
10900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const ContentInfos& contents,
10910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const TransportParserMap& trans_parsers,
10920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const CandidateTranslatorMap& translators,
10930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         TransportInfos* tinfos,
10940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         ParseError* error) {
10950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
10960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ParseGingleTransportInfos(
10970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        action_elem, contents, trans_parsers, translators, tinfos, error);
10980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
10990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return ParseJingleTransportInfos(
11000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        action_elem, contents, trans_parsers, translators, tinfos, error);
11010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool WriteTransportInfos(SignalingProtocol protocol,
11050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const TransportInfos& tinfos,
11060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const TransportParserMap& trans_parsers,
11070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         const CandidateTranslatorMap& translators,
11080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         XmlElements* elems,
11090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         WriteError* error) {
11100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (protocol == PROTOCOL_GINGLE) {
11110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return WriteGingleTransportInfos(tinfos, trans_parsers, translators,
11120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     elems, error);
11130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
11140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return WriteJingleTransportInfos(tinfos, trans_parsers, translators,
11150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     elems, error);
11160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
11170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool GetUriTarget(const std::string& prefix, const std::string& str,
11200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  std::string* after) {
11210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t pos = str.find(prefix);
11220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (pos == std::string::npos)
11230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  *after = str.substr(pos + prefix.size(), std::string::npos);
11260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
11270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool FindSessionRedirect(const buzz::XmlElement* stanza,
11300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                         SessionRedirect* redirect) {
11310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* error_elem = GetXmlChild(stanza, LN_ERROR);
11320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (error_elem == NULL)
11330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const buzz::XmlElement* redirect_elem =
11360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      error_elem->FirstNamed(QN_GINGLE_REDIRECT);
11370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (redirect_elem == NULL)
11380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    redirect_elem = error_elem->FirstNamed(buzz::QN_STANZA_REDIRECT);
11390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (redirect_elem == NULL)
11400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetUriTarget(STR_REDIRECT_PREFIX, redirect_elem->BodyText(),
11430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    &redirect->target))
11440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
11450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
11470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
11480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
11490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
1150