/*
 *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/libjingle/session/sessionmessages.h"

#include <stdio.h>
#include <string>

#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringutils.h"
#include "webrtc/libjingle/session/parsing.h"
#include "webrtc/libjingle/session/sessionclient.h"
#include "webrtc/libjingle/xmllite/xmlconstants.h"
#include "webrtc/libjingle/xmpp/constants.h"
#include "webrtc/p2p/base/constants.h"
#include "webrtc/p2p/base/p2ptransport.h"
#include "webrtc/p2p/base/sessiondescription.h"
#include "webrtc/p2p/base/transport.h"

namespace cricket {

ActionType ToActionType(const std::string& type) {
  if (type == GINGLE_ACTION_INITIATE)
    return ACTION_SESSION_INITIATE;
  if (type == GINGLE_ACTION_INFO)
    return ACTION_SESSION_INFO;
  if (type == GINGLE_ACTION_ACCEPT)
    return ACTION_SESSION_ACCEPT;
  if (type == GINGLE_ACTION_REJECT)
    return ACTION_SESSION_REJECT;
  if (type == GINGLE_ACTION_TERMINATE)
    return ACTION_SESSION_TERMINATE;
  if (type == GINGLE_ACTION_CANDIDATES)
    return ACTION_TRANSPORT_INFO;
  if (type == JINGLE_ACTION_SESSION_INITIATE)
    return ACTION_SESSION_INITIATE;
  if (type == JINGLE_ACTION_TRANSPORT_INFO)
    return ACTION_TRANSPORT_INFO;
  if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
    return ACTION_TRANSPORT_ACCEPT;
  if (type == JINGLE_ACTION_SESSION_INFO)
    return ACTION_SESSION_INFO;
  if (type == JINGLE_ACTION_SESSION_ACCEPT)
    return ACTION_SESSION_ACCEPT;
  if (type == JINGLE_ACTION_SESSION_TERMINATE)
    return ACTION_SESSION_TERMINATE;
  if (type == JINGLE_ACTION_TRANSPORT_INFO)
    return ACTION_TRANSPORT_INFO;
  if (type == JINGLE_ACTION_TRANSPORT_ACCEPT)
    return ACTION_TRANSPORT_ACCEPT;
  if (type == JINGLE_ACTION_DESCRIPTION_INFO)
    return ACTION_DESCRIPTION_INFO;
  if (type == GINGLE_ACTION_UPDATE)
    return ACTION_DESCRIPTION_INFO;

  return ACTION_UNKNOWN;
}

std::string ToJingleString(ActionType type) {
  switch (type) {
    case ACTION_SESSION_INITIATE:
      return JINGLE_ACTION_SESSION_INITIATE;
    case ACTION_SESSION_INFO:
      return JINGLE_ACTION_SESSION_INFO;
    case ACTION_DESCRIPTION_INFO:
      return JINGLE_ACTION_DESCRIPTION_INFO;
    case ACTION_SESSION_ACCEPT:
      return JINGLE_ACTION_SESSION_ACCEPT;
    // Notice that reject and terminate both go to
    // "session-terminate", but there is no "session-reject".
    case ACTION_SESSION_REJECT:
    case ACTION_SESSION_TERMINATE:
      return JINGLE_ACTION_SESSION_TERMINATE;
    case ACTION_TRANSPORT_INFO:
      return JINGLE_ACTION_TRANSPORT_INFO;
    case ACTION_TRANSPORT_ACCEPT:
      return JINGLE_ACTION_TRANSPORT_ACCEPT;
    default:
      return "";
  }
}

std::string ToGingleString(ActionType type) {
  switch (type) {
    case ACTION_SESSION_INITIATE:
      return GINGLE_ACTION_INITIATE;
    case ACTION_SESSION_INFO:
      return GINGLE_ACTION_INFO;
    case ACTION_SESSION_ACCEPT:
      return GINGLE_ACTION_ACCEPT;
    case ACTION_SESSION_REJECT:
      return GINGLE_ACTION_REJECT;
    case ACTION_SESSION_TERMINATE:
      return GINGLE_ACTION_TERMINATE;
    case ACTION_TRANSPORT_INFO:
      return GINGLE_ACTION_CANDIDATES;
    default:
      return "";
  }
}


bool IsJingleMessage(const buzz::XmlElement* stanza) {
  const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
  if (jingle == NULL)
    return false;

  return (jingle->HasAttr(buzz::QN_ACTION) && jingle->HasAttr(QN_SID));
}

bool IsGingleMessage(const buzz::XmlElement* stanza) {
  const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
  if (session == NULL)
    return false;

  return (session->HasAttr(buzz::QN_TYPE) &&
          session->HasAttr(buzz::QN_ID)   &&
          session->HasAttr(QN_INITIATOR));
}

bool IsSessionMessage(const buzz::XmlElement* stanza) {
  return (stanza->Name() == buzz::QN_IQ &&
          stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET &&
          (IsJingleMessage(stanza) ||
           IsGingleMessage(stanza)));
}

bool ParseGingleSessionMessage(const buzz::XmlElement* session,
                               SessionMessage* msg,
                               ParseError* error) {
  msg->protocol = PROTOCOL_GINGLE;
  std::string type_string = session->Attr(buzz::QN_TYPE);
  msg->type = ToActionType(type_string);
  msg->sid = session->Attr(buzz::QN_ID);
  msg->initiator = session->Attr(QN_INITIATOR);
  msg->action_elem = session;

  if (msg->type == ACTION_UNKNOWN)
    return BadParse("unknown action: " + type_string, error);

  return true;
}

bool ParseJingleSessionMessage(const buzz::XmlElement* jingle,
                               SessionMessage* msg,
                               ParseError* error) {
  msg->protocol = PROTOCOL_JINGLE;
  std::string type_string = jingle->Attr(buzz::QN_ACTION);
  msg->type = ToActionType(type_string);
  msg->sid = jingle->Attr(QN_SID);
  msg->initiator = GetXmlAttr(jingle, QN_INITIATOR, buzz::STR_EMPTY);
  msg->action_elem = jingle;

  if (msg->type == ACTION_UNKNOWN)
    return BadParse("unknown action: " + type_string, error);

  return true;
}

bool ParseHybridSessionMessage(const buzz::XmlElement* jingle,
                               SessionMessage* msg,
                               ParseError* error) {
  if (!ParseJingleSessionMessage(jingle, msg, error))
    return false;
  msg->protocol = PROTOCOL_HYBRID;

  return true;
}

bool ParseSessionMessage(const buzz::XmlElement* stanza,
                         SessionMessage* msg,
                         ParseError* error) {
  msg->id = stanza->Attr(buzz::QN_ID);
  msg->from = stanza->Attr(buzz::QN_FROM);
  msg->to = stanza->Attr(buzz::QN_TO);
  msg->stanza = stanza;

  const buzz::XmlElement* jingle = stanza->FirstNamed(QN_JINGLE);
  const buzz::XmlElement* session = stanza->FirstNamed(QN_GINGLE_SESSION);
  if (jingle && session)
    return ParseHybridSessionMessage(jingle, msg, error);
  if (jingle != NULL)
    return ParseJingleSessionMessage(jingle, msg, error);
  if (session != NULL)
    return ParseGingleSessionMessage(session, msg, error);
  return false;
}

buzz::XmlElement* WriteGingleAction(const SessionMessage& msg,
                                    const XmlElements& action_elems) {
  buzz::XmlElement* session = new buzz::XmlElement(QN_GINGLE_SESSION, true);
  session->AddAttr(buzz::QN_TYPE, ToGingleString(msg.type));
  session->AddAttr(buzz::QN_ID, msg.sid);
  session->AddAttr(QN_INITIATOR, msg.initiator);
  AddXmlChildren(session, action_elems);
  return session;
}

buzz::XmlElement* WriteJingleAction(const SessionMessage& msg,
                                    const XmlElements& action_elems) {
  buzz::XmlElement* jingle = new buzz::XmlElement(QN_JINGLE, true);
  jingle->AddAttr(buzz::QN_ACTION, ToJingleString(msg.type));
  jingle->AddAttr(QN_SID, msg.sid);
  if (msg.type == ACTION_SESSION_INITIATE) {
    jingle->AddAttr(QN_INITIATOR, msg.initiator);
  }
  AddXmlChildren(jingle, action_elems);
  return jingle;
}

void WriteSessionMessage(const SessionMessage& msg,
                         const XmlElements& action_elems,
                         buzz::XmlElement* stanza) {
  stanza->SetAttr(buzz::QN_TO, msg.to);
  stanza->SetAttr(buzz::QN_TYPE, buzz::STR_SET);

  if (msg.protocol == PROTOCOL_GINGLE) {
    stanza->AddElement(WriteGingleAction(msg, action_elems));
  } else {
    stanza->AddElement(WriteJingleAction(msg, action_elems));
  }
}


TransportParser* GetTransportParser(const TransportParserMap& trans_parsers,
                                    const std::string& transport_type) {
  TransportParserMap::const_iterator map = trans_parsers.find(transport_type);
  if (map == trans_parsers.end()) {
    return NULL;
  } else {
    return map->second;
  }
}

CandidateTranslator* GetCandidateTranslator(
    const CandidateTranslatorMap& translators,
    const std::string& content_name) {
  CandidateTranslatorMap::const_iterator map = translators.find(content_name);
  if (map == translators.end()) {
    return NULL;
  } else {
    return map->second;
  }
}

bool GetParserAndTranslator(const TransportParserMap& trans_parsers,
                            const CandidateTranslatorMap& translators,
                            const std::string& transport_type,
                            const std::string& content_name,
                            TransportParser** parser,
                            CandidateTranslator** translator,
                            ParseError* error) {
  *parser = GetTransportParser(trans_parsers, transport_type);
  if (*parser == NULL) {
    return BadParse("unknown transport type: " + transport_type, error);
  }
  // Not having a translator isn't fatal when parsing. If this is called for an
  // initiate message, we won't have our proxies set up to do the translation.
  // Fortunately, for the cases where translation is needed, candidates are
  // never sent in initiates.
  *translator = GetCandidateTranslator(translators, content_name);
  return true;
}

bool GetParserAndTranslator(const TransportParserMap& trans_parsers,
                            const CandidateTranslatorMap& translators,
                            const std::string& transport_type,
                            const std::string& content_name,
                            TransportParser** parser,
                            CandidateTranslator** translator,
                            WriteError* error) {
  *parser = GetTransportParser(trans_parsers, transport_type);
  if (*parser == NULL) {
    return BadWrite("unknown transport type: " + transport_type, error);
  }
  *translator = GetCandidateTranslator(translators, content_name);
  if (*translator == NULL) {
    return BadWrite("unknown content name: " + content_name, error);
  }
  return true;
}

bool ParseGingleCandidate(const buzz::XmlElement* candidate_elem,
                          const TransportParserMap& trans_parsers,
                          const CandidateTranslatorMap& translators,
                          const std::string& content_name,
                          Candidates* candidates,
                          ParseError* error) {
  TransportParser* trans_parser;
  CandidateTranslator* translator;
  if (!GetParserAndTranslator(trans_parsers, translators,
                              NS_GINGLE_P2P, content_name,
                              &trans_parser, &translator, error))
    return false;

  Candidate candidate;
  if (!trans_parser->ParseGingleCandidate(
          candidate_elem, translator, &candidate, error)) {
    return false;
  }

  candidates->push_back(candidate);
  return true;
}

bool ParseGingleCandidates(const buzz::XmlElement* parent,
                           const TransportParserMap& trans_parsers,
                           const CandidateTranslatorMap& translators,
                           const std::string& content_name,
                           Candidates* candidates,
                           ParseError* error) {
  for (const buzz::XmlElement* candidate_elem = parent->FirstElement();
       candidate_elem != NULL;
       candidate_elem = candidate_elem->NextElement()) {
    if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
      if (!ParseGingleCandidate(candidate_elem, trans_parsers, translators,
                                content_name, candidates, error)) {
        return false;
      }
    }
  }
  return true;
}

bool ParseGingleTransportInfos(const buzz::XmlElement* action_elem,
                               const ContentInfos& contents,
                               const TransportParserMap& trans_parsers,
                               const CandidateTranslatorMap& translators,
                               TransportInfos* tinfos,
                               ParseError* error) {
  bool has_audio = FindContentInfoByName(contents, CN_AUDIO) != NULL;
  bool has_video = FindContentInfoByName(contents, CN_VIDEO) != NULL;

  // If we don't have media, no need to separate the candidates.
  if (!has_audio && !has_video) {
    TransportInfo tinfo(CN_OTHER,
        TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
    if (!ParseGingleCandidates(action_elem, trans_parsers, translators,
                               CN_OTHER, &tinfo.description.candidates,
                               error)) {
      return false;
    }

    tinfos->push_back(tinfo);
    return true;
  }

  // If we have media, separate the candidates.
  TransportInfo audio_tinfo(
      CN_AUDIO,
      TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
  TransportInfo video_tinfo(
      CN_VIDEO,
      TransportDescription(NS_GINGLE_P2P, std::string(), std::string()));
  for (const buzz::XmlElement* candidate_elem = action_elem->FirstElement();
       candidate_elem != NULL;
       candidate_elem = candidate_elem->NextElement()) {
    if (candidate_elem->Name().LocalPart() == LN_CANDIDATE) {
      const std::string& channel_name = candidate_elem->Attr(buzz::QN_NAME);
      if (has_audio &&
          (channel_name == GICE_CHANNEL_NAME_RTP ||
           channel_name == GICE_CHANNEL_NAME_RTCP)) {
        if (!ParseGingleCandidate(
                candidate_elem, trans_parsers,
                translators, CN_AUDIO,
                &audio_tinfo.description.candidates, error)) {
          return false;
        }
      } else if (has_video &&
                 (channel_name == GICE_CHANNEL_NAME_VIDEO_RTP ||
                  channel_name == GICE_CHANNEL_NAME_VIDEO_RTCP)) {
        if (!ParseGingleCandidate(
                candidate_elem, trans_parsers,
                translators, CN_VIDEO,
                &video_tinfo.description.candidates, error)) {
          return false;
        }
      } else {
        return BadParse("Unknown channel name: " + channel_name, error);
      }
    }
  }

  if (has_audio) {
    tinfos->push_back(audio_tinfo);
  }
  if (has_video) {
    tinfos->push_back(video_tinfo);
  }
  return true;
}

bool ParseJingleTransportInfo(const buzz::XmlElement* trans_elem,
                              const std::string& content_name,
                              const TransportParserMap& trans_parsers,
                              const CandidateTranslatorMap& translators,
                              TransportInfo* tinfo,
                              ParseError* error) {
  TransportParser* trans_parser;
  CandidateTranslator* translator;
  if (!GetParserAndTranslator(trans_parsers, translators,
                              trans_elem->Name().Namespace(), content_name,
                              &trans_parser, &translator, error))
    return false;

  TransportDescription tdesc;
  if (!trans_parser->ParseTransportDescription(trans_elem, translator,
                                               &tdesc, error))
    return false;

  *tinfo = TransportInfo(content_name, tdesc);
  return true;
}

bool ParseJingleTransportInfos(const buzz::XmlElement* jingle,
                               const ContentInfos& contents,
                               const TransportParserMap trans_parsers,
                               const CandidateTranslatorMap& translators,
                               TransportInfos* tinfos,
                               ParseError* error) {
  for (const buzz::XmlElement* pair_elem
           = jingle->FirstNamed(QN_JINGLE_CONTENT);
       pair_elem != NULL;
       pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
    std::string content_name;
    if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
                        &content_name, error))
      return false;

    const ContentInfo* content = FindContentInfoByName(contents, content_name);
    if (!content)
      return BadParse("Unknown content name: " + content_name, error);

    const buzz::XmlElement* trans_elem;
    if (!RequireXmlChild(pair_elem, LN_TRANSPORT, &trans_elem, error))
      return false;

    TransportInfo tinfo;
    if (!ParseJingleTransportInfo(trans_elem, content->name,
                                  trans_parsers, translators,
                                  &tinfo, error))
      return false;

    tinfos->push_back(tinfo);
  }

  return true;
}

buzz::XmlElement* NewTransportElement(const std::string& name) {
  return new buzz::XmlElement(buzz::QName(name, LN_TRANSPORT), true);
}

bool WriteGingleCandidates(const Candidates& candidates,
                           const TransportParserMap& trans_parsers,
                           const std::string& transport_type,
                           const CandidateTranslatorMap& translators,
                           const std::string& content_name,
                           XmlElements* elems,
                           WriteError* error) {
  TransportParser* trans_parser;
  CandidateTranslator* translator;
  if (!GetParserAndTranslator(trans_parsers, translators,
                              transport_type, content_name,
                              &trans_parser, &translator, error))
    return false;

  for (size_t i = 0; i < candidates.size(); ++i) {
    rtc::scoped_ptr<buzz::XmlElement> element;
    if (!trans_parser->WriteGingleCandidate(candidates[i], translator,
                                            element.accept(), error)) {
      return false;
    }

    elems->push_back(element.release());
  }

  return true;
}

bool WriteGingleTransportInfos(const TransportInfos& tinfos,
                               const TransportParserMap& trans_parsers,
                               const CandidateTranslatorMap& translators,
                               XmlElements* elems,
                               WriteError* error) {
  for (TransportInfos::const_iterator tinfo = tinfos.begin();
       tinfo != tinfos.end(); ++tinfo) {
    if (!WriteGingleCandidates(tinfo->description.candidates,
                               trans_parsers, tinfo->description.transport_type,
                               translators, tinfo->content_name,
                               elems, error))
      return false;
  }

  return true;
}

bool WriteJingleTransportInfo(const TransportInfo& tinfo,
                              const TransportParserMap& trans_parsers,
                              const CandidateTranslatorMap& translators,
                              XmlElements* elems,
                              WriteError* error) {
  std::string transport_type = tinfo.description.transport_type;
  TransportParser* trans_parser;
  CandidateTranslator* translator;
  if (!GetParserAndTranslator(trans_parsers, translators,
                              transport_type, tinfo.content_name,
                              &trans_parser, &translator, error))
    return false;

  buzz::XmlElement* trans_elem;
  if (!trans_parser->WriteTransportDescription(tinfo.description, translator,
                                               &trans_elem, error)) {
    return false;
  }

  elems->push_back(trans_elem);
  return true;
}

void WriteJingleContent(const std::string name,
                        const XmlElements& child_elems,
                        XmlElements* elems) {
  buzz::XmlElement* content_elem = new buzz::XmlElement(QN_JINGLE_CONTENT);
  content_elem->SetAttr(QN_JINGLE_CONTENT_NAME, name);
  content_elem->SetAttr(QN_CREATOR, LN_INITIATOR);
  AddXmlChildren(content_elem, child_elems);

  elems->push_back(content_elem);
}

bool WriteJingleTransportInfos(const TransportInfos& tinfos,
                               const TransportParserMap& trans_parsers,
                               const CandidateTranslatorMap& translators,
                               XmlElements* elems,
                               WriteError* error) {
  for (TransportInfos::const_iterator tinfo = tinfos.begin();
       tinfo != tinfos.end(); ++tinfo) {
    XmlElements content_child_elems;
    if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
                                  &content_child_elems, error))

      return false;

    WriteJingleContent(tinfo->content_name, content_child_elems, elems);
  }

  return true;
}

ContentParser* GetContentParser(const ContentParserMap& content_parsers,
                                const std::string& type) {
  ContentParserMap::const_iterator map = content_parsers.find(type);
  if (map == content_parsers.end()) {
    return NULL;
  } else {
    return map->second;
  }
}

bool ParseContentInfo(SignalingProtocol protocol,
                      const std::string& name,
                      const std::string& type,
                      const buzz::XmlElement* elem,
                      const ContentParserMap& parsers,
                      ContentInfos* contents,
                      ParseError* error) {
  ContentParser* parser = GetContentParser(parsers, type);
  if (parser == NULL)
    return BadParse("unknown application content: " + type, error);

  ContentDescription* desc;
  if (!parser->ParseContent(protocol, elem, &desc, error))
    return false;

  contents->push_back(ContentInfo(name, type, desc));
  return true;
}

bool ParseContentType(const buzz::XmlElement* parent_elem,
                      std::string* content_type,
                      const buzz::XmlElement** content_elem,
                      ParseError* error) {
  if (!RequireXmlChild(parent_elem, LN_DESCRIPTION, content_elem, error))
    return false;

  *content_type = (*content_elem)->Name().Namespace();
  return true;
}

bool ParseGingleContentInfos(const buzz::XmlElement* session,
                             const ContentParserMap& content_parsers,
                             ContentInfos* contents,
                             ParseError* error) {
  std::string content_type;
  const buzz::XmlElement* content_elem;
  if (!ParseContentType(session, &content_type, &content_elem, error))
    return false;

  if (content_type == NS_GINGLE_VIDEO) {
    // A parser parsing audio or video content should look at the
    // namespace and only parse the codecs relevant to that namespace.
    // We use this to control which codecs get parsed: first audio,
    // then video.
    rtc::scoped_ptr<buzz::XmlElement> audio_elem(
        new buzz::XmlElement(QN_GINGLE_AUDIO_CONTENT));
    CopyXmlChildren(content_elem, audio_elem.get());
    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
                          audio_elem.get(), content_parsers,
                          contents, error))
      return false;

    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_VIDEO, NS_JINGLE_RTP,
                          content_elem, content_parsers,
                          contents, error))
      return false;
  } else if (content_type == NS_GINGLE_AUDIO) {
    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_AUDIO, NS_JINGLE_RTP,
                          content_elem, content_parsers,
                          contents, error))
      return false;
  } else {
    if (!ParseContentInfo(PROTOCOL_GINGLE, CN_OTHER, content_type,
                          content_elem, content_parsers,
                          contents, error))
      return false;
  }
  return true;
}

bool ParseJingleContentInfos(const buzz::XmlElement* jingle,
                             const ContentParserMap& content_parsers,
                             ContentInfos* contents,
                             ParseError* error) {
  for (const buzz::XmlElement* pair_elem
           = jingle->FirstNamed(QN_JINGLE_CONTENT);
       pair_elem != NULL;
       pair_elem = pair_elem->NextNamed(QN_JINGLE_CONTENT)) {
    std::string content_name;
    if (!RequireXmlAttr(pair_elem, QN_JINGLE_CONTENT_NAME,
                        &content_name, error))
      return false;

    std::string content_type;
    const buzz::XmlElement* content_elem;
    if (!ParseContentType(pair_elem, &content_type, &content_elem, error))
      return false;

    if (!ParseContentInfo(PROTOCOL_JINGLE, content_name, content_type,
                          content_elem, content_parsers,
                          contents, error))
      return false;
  }
  return true;
}

bool ParseJingleGroupInfos(const buzz::XmlElement* jingle,
                           ContentGroups* groups,
                           ParseError* error) {
  for (const buzz::XmlElement* pair_elem
           = jingle->FirstNamed(QN_JINGLE_DRAFT_GROUP);
       pair_elem != NULL;
       pair_elem = pair_elem->NextNamed(QN_JINGLE_DRAFT_GROUP)) {
    std::string group_name;
    if (!RequireXmlAttr(pair_elem, QN_JINGLE_DRAFT_GROUP_TYPE,
                        &group_name, error))
      return false;

    ContentGroup group(group_name);
    for (const buzz::XmlElement* child_elem
             = pair_elem->FirstNamed(QN_JINGLE_CONTENT);
        child_elem != NULL;
        child_elem = child_elem->NextNamed(QN_JINGLE_CONTENT)) {
      std::string content_name;
      if (!RequireXmlAttr(child_elem, QN_JINGLE_CONTENT_NAME,
                          &content_name, error))
        return false;
      group.AddContentName(content_name);
    }
    groups->push_back(group);
  }
  return true;
}

buzz::XmlElement* WriteContentInfo(SignalingProtocol protocol,
                                   const ContentInfo& content,
                                   const ContentParserMap& parsers,
                                   WriteError* error) {
  ContentParser* parser = GetContentParser(parsers, content.type);
  if (parser == NULL) {
    BadWrite("unknown content type: " + content.type, error);
    return NULL;
  }

  buzz::XmlElement* elem = NULL;
  if (!parser->WriteContent(protocol, content.description, &elem, error))
    return NULL;

  return elem;
}

bool IsWritable(SignalingProtocol protocol,
                const ContentInfo& content,
                const ContentParserMap& parsers) {
  ContentParser* parser = GetContentParser(parsers, content.type);
  if (parser == NULL) {
    return false;
  }

  return parser->IsWritable(protocol, content.description);
}

bool WriteGingleContentInfos(const ContentInfos& contents,
                             const ContentParserMap& parsers,
                             XmlElements* elems,
                             WriteError* error) {
  if (contents.size() == 1 ||
      (contents.size() == 2 &&
       !IsWritable(PROTOCOL_GINGLE, contents.at(1), parsers))) {
    if (contents.front().rejected) {
      return BadWrite("Gingle protocol may not reject individual contents.",
                      error);
    }
    buzz::XmlElement* elem = WriteContentInfo(
        PROTOCOL_GINGLE, contents.front(), parsers, error);
    if (!elem)
      return false;

    elems->push_back(elem);
  } else if (contents.size() >= 2 &&
             contents.at(0).type == NS_JINGLE_RTP &&
             contents.at(1).type == NS_JINGLE_RTP) {
     // Special-case audio + video contents so that they are "merged"
     // into one "video" content.
    if (contents.at(0).rejected || contents.at(1).rejected) {
      return BadWrite("Gingle protocol may not reject individual contents.",
                      error);
    }
    buzz::XmlElement* audio = WriteContentInfo(
        PROTOCOL_GINGLE, contents.at(0), parsers, error);
    if (!audio)
      return false;

    buzz::XmlElement* video = WriteContentInfo(
        PROTOCOL_GINGLE, contents.at(1), parsers, error);
    if (!video) {
      delete audio;
      return false;
    }

    CopyXmlChildren(audio, video);
    elems->push_back(video);
    delete audio;
  } else {
    return BadWrite("Gingle protocol may only have one content.", error);
  }

  return true;
}

const TransportInfo* GetTransportInfoByContentName(
    const TransportInfos& tinfos, const std::string& content_name) {
  for (TransportInfos::const_iterator tinfo = tinfos.begin();
       tinfo != tinfos.end(); ++tinfo) {
    if (content_name == tinfo->content_name) {
      return &*tinfo;
    }
  }
  return NULL;
}

bool WriteJingleContents(const ContentInfos& contents,
                         const ContentParserMap& content_parsers,
                         const TransportInfos& tinfos,
                         const TransportParserMap& trans_parsers,
                         const CandidateTranslatorMap& translators,
                         XmlElements* elems,
                         WriteError* error) {
  for (ContentInfos::const_iterator content = contents.begin();
       content != contents.end(); ++content) {
    if (content->rejected) {
      continue;
    }
    const TransportInfo* tinfo =
        GetTransportInfoByContentName(tinfos, content->name);
    if (!tinfo)
      return BadWrite("No transport for content: " + content->name, error);

    XmlElements pair_elems;
    buzz::XmlElement* elem = WriteContentInfo(
        PROTOCOL_JINGLE, *content, content_parsers, error);
    if (!elem)
      return false;
    pair_elems.push_back(elem);

    if (!WriteJingleTransportInfo(*tinfo, trans_parsers, translators,
                                  &pair_elems, error))
      return false;

    WriteJingleContent(content->name, pair_elems, elems);
  }
  return true;
}

bool WriteJingleContentInfos(const ContentInfos& contents,
                             const ContentParserMap& content_parsers,
                             XmlElements* elems,
                             WriteError* error) {
  for (ContentInfos::const_iterator content = contents.begin();
       content != contents.end(); ++content) {
    if (content->rejected) {
      continue;
    }
    XmlElements content_child_elems;
    buzz::XmlElement* elem = WriteContentInfo(
        PROTOCOL_JINGLE, *content, content_parsers, error);
    if (!elem)
      return false;
    content_child_elems.push_back(elem);
    WriteJingleContent(content->name, content_child_elems, elems);
  }
  return true;
}

bool WriteJingleGroupInfo(const ContentInfos& contents,
                          const ContentGroups& groups,
                          XmlElements* elems,
                          WriteError* error) {
  if (!groups.empty()) {
    buzz::XmlElement* pair_elem = new buzz::XmlElement(QN_JINGLE_DRAFT_GROUP);
    pair_elem->SetAttr(QN_JINGLE_DRAFT_GROUP_TYPE, GROUP_TYPE_BUNDLE);

    XmlElements pair_elems;
    for (ContentInfos::const_iterator content = contents.begin();
         content != contents.end(); ++content) {
      buzz::XmlElement* child_elem =
          new buzz::XmlElement(QN_JINGLE_CONTENT, false);
      child_elem->SetAttr(QN_JINGLE_CONTENT_NAME, content->name);
      pair_elems.push_back(child_elem);
    }
    AddXmlChildren(pair_elem, pair_elems);
    elems->push_back(pair_elem);
  }
  return true;
}

bool ParseContentType(SignalingProtocol protocol,
                      const buzz::XmlElement* action_elem,
                      std::string* content_type,
                      ParseError* error) {
  const buzz::XmlElement* content_elem;
  if (protocol == PROTOCOL_GINGLE) {
    if (!ParseContentType(action_elem, content_type, &content_elem, error))
      return false;

    // Internally, we only use NS_JINGLE_RTP.
    if (*content_type == NS_GINGLE_AUDIO ||
        *content_type == NS_GINGLE_VIDEO)
      *content_type = NS_JINGLE_RTP;
  } else {
    const buzz::XmlElement* pair_elem
        = action_elem->FirstNamed(QN_JINGLE_CONTENT);
    if (pair_elem == NULL)
      return BadParse("No contents found", error);

    if (!ParseContentType(pair_elem, content_type, &content_elem, error))
      return false;
  }

  return true;
}

static bool ParseContentMessage(
    SignalingProtocol protocol,
    const buzz::XmlElement* action_elem,
    bool expect_transports,
    const ContentParserMap& content_parsers,
    const TransportParserMap& trans_parsers,
    const CandidateTranslatorMap& translators,
    SessionInitiate* init,
    ParseError* error) {
  init->owns_contents = true;
  if (protocol == PROTOCOL_GINGLE) {
    if (!ParseGingleContentInfos(action_elem, content_parsers,
                                 &init->contents, error))
      return false;

    if (expect_transports &&
        !ParseGingleTransportInfos(action_elem, init->contents,
                                   trans_parsers, translators,
                                   &init->transports, error))
      return false;
  } else {
    if (!ParseJingleContentInfos(action_elem, content_parsers,
                                 &init->contents, error))
      return false;
    if (!ParseJingleGroupInfos(action_elem, &init->groups, error))
      return false;

    if (expect_transports &&
        !ParseJingleTransportInfos(action_elem, init->contents,
                                   trans_parsers, translators,
                                   &init->transports, error))
      return false;
  }

  return true;
}

static bool WriteContentMessage(
    SignalingProtocol protocol,
    const ContentInfos& contents,
    const TransportInfos& tinfos,
    const ContentParserMap& content_parsers,
    const TransportParserMap& transport_parsers,
    const CandidateTranslatorMap& translators,
    const ContentGroups& groups,
    XmlElements* elems,
    WriteError* error) {
  if (protocol == PROTOCOL_GINGLE) {
    if (!WriteGingleContentInfos(contents, content_parsers, elems, error))
      return false;

    if (!WriteGingleTransportInfos(tinfos, transport_parsers, translators,
                                   elems, error))
      return false;
  } else {
    if (!WriteJingleContents(contents, content_parsers,
                             tinfos, transport_parsers, translators,
                             elems, error))
      return false;
    if (!WriteJingleGroupInfo(contents, groups, elems, error))
      return false;
  }

  return true;
}

bool ParseSessionInitiate(SignalingProtocol protocol,
                          const buzz::XmlElement* action_elem,
                          const ContentParserMap& content_parsers,
                          const TransportParserMap& trans_parsers,
                          const CandidateTranslatorMap& translators,
                          SessionInitiate* init,
                          ParseError* error) {
  bool expect_transports = true;
  return ParseContentMessage(protocol, action_elem, expect_transports,
                             content_parsers, trans_parsers, translators,
                             init, error);
}


bool WriteSessionInitiate(SignalingProtocol protocol,
                          const ContentInfos& contents,
                          const TransportInfos& tinfos,
                          const ContentParserMap& content_parsers,
                          const TransportParserMap& transport_parsers,
                          const CandidateTranslatorMap& translators,
                          const ContentGroups& groups,
                          XmlElements* elems,
                          WriteError* error) {
  return WriteContentMessage(protocol, contents, tinfos,
                             content_parsers, transport_parsers, translators,
                             groups,
                             elems, error);
}

bool ParseSessionAccept(SignalingProtocol protocol,
                        const buzz::XmlElement* action_elem,
                        const ContentParserMap& content_parsers,
                        const TransportParserMap& transport_parsers,
                        const CandidateTranslatorMap& translators,
                        SessionAccept* accept,
                        ParseError* error) {
  bool expect_transports = true;
  return ParseContentMessage(protocol, action_elem, expect_transports,
                             content_parsers, transport_parsers, translators,
                             accept, error);
}

bool WriteSessionAccept(SignalingProtocol protocol,
                        const ContentInfos& contents,
                        const TransportInfos& tinfos,
                        const ContentParserMap& content_parsers,
                        const TransportParserMap& transport_parsers,
                        const CandidateTranslatorMap& translators,
                        const ContentGroups& groups,
                        XmlElements* elems,
                        WriteError* error) {
  return WriteContentMessage(protocol, contents, tinfos,
                             content_parsers, transport_parsers, translators,
                             groups,
                             elems, error);
}

bool ParseSessionTerminate(SignalingProtocol protocol,
                           const buzz::XmlElement* action_elem,
                           SessionTerminate* term,
                           ParseError* error) {
  if (protocol == PROTOCOL_GINGLE) {
    const buzz::XmlElement* reason_elem = action_elem->FirstElement();
    if (reason_elem != NULL) {
      term->reason = reason_elem->Name().LocalPart();
      const buzz::XmlElement *debug_elem = reason_elem->FirstElement();
      if (debug_elem != NULL) {
        term->debug_reason = debug_elem->Name().LocalPart();
      }
    }
    return true;
  } else {
    const buzz::XmlElement* reason_elem =
        action_elem->FirstNamed(QN_JINGLE_REASON);
    if (reason_elem) {
      reason_elem = reason_elem->FirstElement();
      if (reason_elem) {
        term->reason = reason_elem->Name().LocalPart();
      }
    }
    return true;
  }
}

void WriteSessionTerminate(SignalingProtocol protocol,
                           const SessionTerminate& term,
                           XmlElements* elems) {
  if (protocol == PROTOCOL_GINGLE) {
    elems->push_back(new buzz::XmlElement(buzz::QName(NS_GINGLE, term.reason)));
  } else {
    if (!term.reason.empty()) {
      buzz::XmlElement* reason_elem = new buzz::XmlElement(QN_JINGLE_REASON);
      reason_elem->AddElement(new buzz::XmlElement(
          buzz::QName(NS_JINGLE, term.reason)));
      elems->push_back(reason_elem);
    }
  }
}

bool ParseDescriptionInfo(SignalingProtocol protocol,
                          const buzz::XmlElement* action_elem,
                          const ContentParserMap& content_parsers,
                          const TransportParserMap& transport_parsers,
                          const CandidateTranslatorMap& translators,
                          DescriptionInfo* description_info,
                          ParseError* error) {
  bool expect_transports = false;
  return ParseContentMessage(protocol, action_elem, expect_transports,
                             content_parsers, transport_parsers, translators,
                             description_info, error);
}

bool WriteDescriptionInfo(SignalingProtocol protocol,
                          const ContentInfos& contents,
                          const ContentParserMap& content_parsers,
                          XmlElements* elems,
                          WriteError* error) {
  if (protocol == PROTOCOL_GINGLE) {
    return WriteGingleContentInfos(contents, content_parsers, elems, error);
  } else {
    return WriteJingleContentInfos(contents, content_parsers, elems, error);
  }
}

bool ParseTransportInfos(SignalingProtocol protocol,
                         const buzz::XmlElement* action_elem,
                         const ContentInfos& contents,
                         const TransportParserMap& trans_parsers,
                         const CandidateTranslatorMap& translators,
                         TransportInfos* tinfos,
                         ParseError* error) {
  if (protocol == PROTOCOL_GINGLE) {
    return ParseGingleTransportInfos(
        action_elem, contents, trans_parsers, translators, tinfos, error);
  } else {
    return ParseJingleTransportInfos(
        action_elem, contents, trans_parsers, translators, tinfos, error);
  }
}

bool WriteTransportInfos(SignalingProtocol protocol,
                         const TransportInfos& tinfos,
                         const TransportParserMap& trans_parsers,
                         const CandidateTranslatorMap& translators,
                         XmlElements* elems,
                         WriteError* error) {
  if (protocol == PROTOCOL_GINGLE) {
    return WriteGingleTransportInfos(tinfos, trans_parsers, translators,
                                     elems, error);
  } else {
    return WriteJingleTransportInfos(tinfos, trans_parsers, translators,
                                     elems, error);
  }
}

bool GetUriTarget(const std::string& prefix, const std::string& str,
                  std::string* after) {
  size_t pos = str.find(prefix);
  if (pos == std::string::npos)
    return false;

  *after = str.substr(pos + prefix.size(), std::string::npos);
  return true;
}

bool FindSessionRedirect(const buzz::XmlElement* stanza,
                         SessionRedirect* redirect) {
  const buzz::XmlElement* error_elem = GetXmlChild(stanza, LN_ERROR);
  if (error_elem == NULL)
    return false;

  const buzz::XmlElement* redirect_elem =
      error_elem->FirstNamed(QN_GINGLE_REDIRECT);
  if (redirect_elem == NULL)
    redirect_elem = error_elem->FirstNamed(buzz::QN_STANZA_REDIRECT);
  if (redirect_elem == NULL)
    return false;

  if (!GetUriTarget(STR_REDIRECT_PREFIX, redirect_elem->BodyText(),
                    &redirect->target))
    return false;

  return true;
}

}  // namespace cricket
