1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/sessionmanager.h"
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/helpers.h"
32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "talk/base/stringencode.h"
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/p2p/base/constants.h"
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "talk/p2p/base/session.h"
35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "talk/p2p/base/sessionmessages.h"
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmpp/constants.h"
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/xmpp/jid.h"
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace cricket {
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSessionManager::SessionManager(PortAllocator *allocator,
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                               talk_base::Thread *worker) {
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  allocator_ = allocator;
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  signaling_thread_ = talk_base::Thread::Current();
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (worker == NULL) {
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    worker_thread_ = talk_base::Thread::Current();
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  } else {
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    worker_thread_ = worker;
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  timeout_ = 50;
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSessionManager::~SessionManager() {
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // Note: Session::Terminate occurs asynchronously, so it's too late to
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // delete them now.  They better be all gone.
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(session_map_.empty());
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // TerminateAll();
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SessionManager::AddClient(const std::string& content_type,
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                               SessionClient* client) {
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ASSERT(client_map_.find(content_type) == client_map_.end());
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  client_map_[content_type] = client;
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SessionManager::RemoveClient(const std::string& content_type) {
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientMap::iterator iter = client_map_.find(content_type);
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(iter != client_map_.end());
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  client_map_.erase(iter);
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickSessionClient* SessionManager::GetClient(const std::string& content_type) {
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ClientMap::iterator iter = client_map_.find(content_type);
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return (iter != client_map_.end()) ? iter->second : NULL;
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
77731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSession* SessionManager::CreateSession(const std::string& local_name,
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                       const std::string& content_type) {
79731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return CreateSession(local_name, local_name,
80731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                       talk_base::ToString(talk_base::CreateRandomId()),
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                       content_type, false);
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
84731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSession* SessionManager::CreateSession(
85731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& local_name, const std::string& initiator_name,
86731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const std::string& sid, const std::string& content_type,
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    bool received_initiate) {
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  SessionClient* client = GetClient(content_type);
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ASSERT(client != NULL);
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
91731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Session* session = new Session(this, local_name, initiator_name,
92731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                 sid, content_type, client);
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session_map_[session->id()] = session;
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->SignalRequestSignaling.connect(
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &SessionManager::OnRequestSignaling);
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->SignalOutgoingMessage.connect(
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      this, &SessionManager::OnOutgoingMessage);
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage);
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalSessionCreate(session, received_initiate);
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->client()->OnSessionCreate(session, received_initiate);
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return session;
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SessionManager::DestroySession(Session* session) {
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (session != NULL) {
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SessionMap::iterator it = session_map_.find(session->id());
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (it != session_map_.end()) {
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      SignalSessionDestroy(session);
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      session->client()->OnSessionDestroy(session);
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      session_map_.erase(it);
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      delete session;
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
116731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSession* SessionManager::GetSession(const std::string& sid) {
117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SessionMap::iterator it = session_map_.find(sid);
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (it != session_map_.end())
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return it->second;
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return NULL;
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::TerminateAll() {
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  while (session_map_.begin() != session_map_.end()) {
125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    Session* session = session_map_.begin()->second;
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    session->Terminate();
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) {
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return cricket::IsSessionMessage(stanza);
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochSession* SessionManager::FindSession(const std::string& sid,
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                     const std::string& remote_name) {
136731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  SessionMap::iterator iter = session_map_.find(sid);
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (iter == session_map_.end())
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return NULL;
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  Session* session = iter->second;
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (buzz::Jid(remote_name) != buzz::Jid(session->remote_name()))
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return NULL;
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return session;
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SessionMessage msg;
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ParseError error;
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ParseSessionMessage(stanza, &msg, &error)) {
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                     error.text, NULL);
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
157731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Session* session = FindSession(msg.sid, msg.from);
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (session) {
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    session->OnIncomingMessage(msg);
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (msg.type != ACTION_SESSION_INITIATE) {
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                     "unknown session", NULL);
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string content_type;
169731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!ParseContentType(msg.protocol, msg.action_elem,
170731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                        &content_type, &error)) {
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                     error.text, NULL);
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
1763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!GetClient(content_type)) {
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                     "unknown content type: " + content_type, NULL);
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
182731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  session = CreateSession(msg.to, msg.initiator, msg.sid,
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          content_type, true);
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  session->OnIncomingMessage(msg);
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const buzz::XmlElement* response_stanza) {
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // We don't do anything with the response now.  If we need to we can forward
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // it to the session.
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return;
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                  const buzz::XmlElement* error_stanza) {
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SessionMessage msg;
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ParseError error;
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
199731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;  // TODO: log somewhere?
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  Session* session = FindSession(msg.sid, msg.to);
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (session) {
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    talk_base::scoped_ptr<buzz::XmlElement> synthetic_error;
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!error_stanza) {
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // A failed send is semantically equivalent to an error response, so we
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      // can just turn the former into the latter.
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      synthetic_error.reset(
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch        CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                           "cancel", "Recipient did not respond", NULL));
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      error_stanza = synthetic_error.get();
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    }
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    session->OnFailedSend(orig_stanza, error_stanza);
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                      const buzz::QName& name,
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                      const std::string& type,
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                      const std::string& text,
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                      const buzz::XmlElement* extra_info) {
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  talk_base::scoped_ptr<buzz::XmlElement> msg(
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      CreateErrorMessage(stanza, name, type, text, extra_info));
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalOutgoingMessage(this, msg.get());
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbuzz::XmlElement* SessionManager::CreateErrorMessage(
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const buzz::XmlElement* stanza,
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const buzz::QName& name,
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const std::string& type,
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const std::string& text,
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    const buzz::XmlElement* extra_info) {
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ);
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM));
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  iq->SetAttr(buzz::QN_TYPE, "error");
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
239731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CopyXmlChildren(stanza, iq);
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  error->SetAttr(buzz::QN_TYPE, type);
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  iq->AddElement(error);
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // If the error name is not in the standard namespace, we have to first add
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // some error from that namespace.
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (name.Namespace() != buzz::NS_STANZA) {
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch     error->AddElement(
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch         new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION));
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  error->AddElement(new buzz::XmlElement(name));
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (extra_info)
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    error->AddElement(new buzz::XmlElement(*extra_info));
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (text.size() > 0) {
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // It's okay to always use English here.  This text is for debugging
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    // purposes only.
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT);
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    text_elem->SetAttr(buzz::QN_XML_LANG, "en");
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    text_elem->SetBodyText(text);
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    error->AddElement(text_elem);
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // TODO: Should we include error codes as well for SIP compatibility?
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return iq;
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnOutgoingMessage(Session* session,
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                       const buzz::XmlElement* stanza) {
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalOutgoingMessage(this, stanza);
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnErrorMessage(BaseSession* session,
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    const buzz::XmlElement* stanza,
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    const buzz::QName& name,
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    const std::string& type,
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    const std::string& text,
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                                    const buzz::XmlElement* extra_info) {
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SendErrorMessage(stanza, name, type, text, extra_info);
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnSignalingReady() {
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  for (SessionMap::iterator it = session_map_.begin();
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      it != session_map_.end();
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      ++it) {
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    it->second->OnSignalingReady();
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid SessionManager::OnRequestSignaling(Session* session) {
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  SignalRequestSignaling();
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}  // namespace cricket
297