15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/sessionmanager.h"
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h"
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/helpers.h"
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/scoped_ptr.h"
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/stringencode.h"
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/constants.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/session.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/p2p/base/sessionmessages.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/constants.h"
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/jid.h"
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace cricket {
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSessionManager::SessionManager(PortAllocator *allocator,
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               talk_base::Thread *worker) {
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  allocator_ = allocator;
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  signaling_thread_ = talk_base::Thread::Current();
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (worker == NULL) {
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    worker_thread_ = talk_base::Thread::Current();
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    worker_thread_ = worker;
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  timeout_ = 50;
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSessionManager::~SessionManager() {
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Note: Session::Terminate occurs asynchronously, so it's too late to
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // delete them now.  They better be all gone.
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(session_map_.empty());
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TerminateAll();
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalDestroyed();
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::AddClient(const std::string& content_type,
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                               SessionClient* client) {
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(client_map_.find(content_type) == client_map_.end());
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  client_map_[content_type] = client;
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::RemoveClient(const std::string& content_type) {
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ClientMap::iterator iter = client_map_.find(content_type);
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(iter != client_map_.end());
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  client_map_.erase(iter);
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSessionClient* SessionManager::GetClient(const std::string& content_type) {
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ClientMap::iterator iter = client_map_.find(content_type);
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (iter != client_map_.end()) ? iter->second : NULL;
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSession* SessionManager::CreateSession(const std::string& local_name,
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                       const std::string& content_type) {
82c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  std::string id;
83c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return CreateSession(id, local_name, content_type);
84c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org}
85c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org
86c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.orgSession* SessionManager::CreateSession(const std::string& id,
87c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                                       const std::string& local_name,
88c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org                                       const std::string& content_type) {
89c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  std::string sid =
90c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org      id.empty() ? talk_base::ToString(talk_base::CreateRandomId64()) : id;
91c237f0ad875cde990bf9d89f41424b18809cc345henrike@webrtc.org  return CreateSession(local_name, local_name, sid, content_type, false);
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSession* SessionManager::CreateSession(
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& local_name, const std::string& initiator_name,
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& sid, const std::string& content_type,
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    bool received_initiate) {
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionClient* client = GetClient(content_type);
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(client != NULL);
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = new Session(this, local_name, initiator_name,
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                 sid, content_type, client);
1037bf94f9c4ab08aa82f78018d8ba363b5b60b05edwu@webrtc.org  session->SetIdentity(transport_desc_factory_.identity());
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session_map_[session->id()] = session;
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->SignalRequestSignaling.connect(
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      this, &SessionManager::OnRequestSignaling);
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->SignalOutgoingMessage.connect(
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      this, &SessionManager::OnOutgoingMessage);
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage);
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalSessionCreate(session, received_initiate);
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->client()->OnSessionCreate(session, received_initiate);
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return session;
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::DestroySession(Session* session) {
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (session != NULL) {
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SessionMap::iterator it = session_map_.find(session->id());
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (it != session_map_.end()) {
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      SignalSessionDestroy(session);
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session->client()->OnSessionDestroy(session);
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      session_map_.erase(it);
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete session;
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSession* SessionManager::GetSession(const std::string& sid) {
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionMap::iterator it = session_map_.find(sid);
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (it != session_map_.end())
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return it->second;
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return NULL;
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::TerminateAll() {
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (session_map_.begin() != session_map_.end()) {
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Session* session = session_map_.begin()->second;
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->Terminate();
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) {
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return cricket::IsSessionMessage(stanza);
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgSession* SessionManager::FindSession(const std::string& sid,
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                     const std::string& remote_name) {
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionMap::iterator iter = session_map_.find(sid);
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (iter == session_map_.end())
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = iter->second;
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (buzz::Jid(remote_name) != buzz::Jid(session->remote_name()))
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return session;
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionMessage msg;
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ParseError error;
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseSessionMessage(stanza, &msg, &error)) {
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     error.text, NULL);
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = FindSession(msg.sid, msg.from);
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (session) {
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->OnIncomingMessage(msg);
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (msg.type != ACTION_SESSION_INITIATE) {
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     "unknown session", NULL);
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  std::string content_type;
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseContentType(msg.protocol, msg.action_elem,
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                        &content_type, &error)) {
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     error.text, NULL);
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!GetClient(content_type)) {
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     "unknown content type: " + content_type, NULL);
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session = CreateSession(msg.to, msg.initiator, msg.sid,
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          content_type, true);
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  session->OnIncomingMessage(msg);
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const buzz::XmlElement* response_stanza) {
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (orig_stanza == NULL || response_stanza == NULL) {
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionMessage msg;
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ParseError error;
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    LOG(LS_WARNING) << "Error parsing incoming response: " << error.text
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                    << ":" << orig_stanza;
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = FindSession(msg.sid, msg.to);
213204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org  if (!session) {
214204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    // Also try the QN_FROM in the response stanza, in case we sent the request
215204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    // to a bare JID but got the response from a full JID.
216204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    std::string ack_from = response_stanza->Attr(buzz::QN_FROM);
217204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    session = FindSession(msg.sid, ack_from);
218204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org  }
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (session) {
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->OnIncomingResponse(orig_stanza, response_stanza, msg);
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                  const buzz::XmlElement* error_stanza) {
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SessionMessage msg;
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ParseError error;
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;  // TODO: log somewhere?
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Session* session = FindSession(msg.sid, msg.to);
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (session) {
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    talk_base::scoped_ptr<buzz::XmlElement> synthetic_error;
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!error_stanza) {
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // A failed send is semantically equivalent to an error response, so we
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // can just turn the former into the latter.
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      synthetic_error.reset(
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                           "cancel", "Recipient did not respond", NULL));
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      error_stanza = synthetic_error.get();
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    session->OnFailedSend(orig_stanza, error_stanza);
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      const buzz::QName& name,
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      const std::string& type,
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      const std::string& text,
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                      const buzz::XmlElement* extra_info) {
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  talk_base::scoped_ptr<buzz::XmlElement> msg(
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      CreateErrorMessage(stanza, name, type, text, extra_info));
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalOutgoingMessage(this, msg.get());
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbuzz::XmlElement* SessionManager::CreateErrorMessage(
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const buzz::XmlElement* stanza,
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const buzz::QName& name,
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& type,
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& text,
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const buzz::XmlElement* extra_info) {
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ);
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM));
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  iq->SetAttr(buzz::QN_TYPE, "error");
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  CopyXmlChildren(stanza, iq);
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  error->SetAttr(buzz::QN_TYPE, type);
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  iq->AddElement(error);
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If the error name is not in the standard namespace, we have to first add
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // some error from that namespace.
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (name.Namespace() != buzz::NS_STANZA) {
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     error->AddElement(
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION));
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  error->AddElement(new buzz::XmlElement(name));
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (extra_info)
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error->AddElement(new buzz::XmlElement(*extra_info));
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (text.size() > 0) {
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // It's okay to always use English here.  This text is for debugging
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // purposes only.
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT);
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    text_elem->SetAttr(buzz::QN_XML_LANG, "en");
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    text_elem->SetBodyText(text);
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    error->AddElement(text_elem);
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO: Should we include error codes as well for SIP compatibility?
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return iq;
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnOutgoingMessage(Session* session,
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                       const buzz::XmlElement* stanza) {
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalOutgoingMessage(this, stanza);
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnErrorMessage(BaseSession* session,
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const buzz::XmlElement* stanza,
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const buzz::QName& name,
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const std::string& type,
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const std::string& text,
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                    const buzz::XmlElement* extra_info) {
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SendErrorMessage(stanza, name, type, text, extra_info);
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnSignalingReady() {
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (SessionMap::iterator it = session_map_.begin();
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      it != session_map_.end();
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ++it) {
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    it->second->OnSignalingReady();
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid SessionManager::OnRequestSignaling(Session* session) {
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  SignalRequestSignaling();
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // namespace cricket
327