Split up (Jingle)Session from BaseSession.  This is part of an ongoing effort to move Jingle-specific code out of WebRTC and into its own repository.

This is an un-revert of r7992 and r7993.

R=henrike@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/32869004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7939 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/session/media/call.h b/talk/session/media/call.h
index f992043..382cdc5 100644
--- a/talk/session/media/call.h
+++ b/talk/session/media/call.h
@@ -37,12 +37,12 @@
 #include "talk/media/base/screencastid.h"
 #include "talk/media/base/streamparams.h"
 #include "talk/media/base/videocommon.h"
-#include "webrtc/p2p/base/session.h"
 #include "webrtc/p2p/client/socketmonitor.h"
 #include "talk/session/media/audiomonitor.h"
 #include "talk/session/media/currentspeakermonitor.h"
 #include "talk/session/media/mediamessages.h"
 #include "talk/session/media/mediasession.h"
+#include "webrtc/libjingle/session/session.h"
 #include "webrtc/libjingle/xmpp/jid.h"
 #include "webrtc/base/messagequeue.h"
 
@@ -160,9 +160,9 @@
   sigslot::signal0<> SignalSetupToCallVoicemail;
   sigslot::signal2<Call*, Session*> SignalAddSession;
   sigslot::signal2<Call*, Session*> SignalRemoveSession;
-  sigslot::signal3<Call*, Session*, Session::State>
+  sigslot::signal3<Call*, Session*, BaseSession::State>
       SignalSessionState;
-  sigslot::signal3<Call*, Session*, Session::Error>
+  sigslot::signal3<Call*, Session*, BaseSession::Error>
       SignalSessionError;
   sigslot::signal3<Call*, Session*, const std::string &>
       SignalReceivedTerminateReason;
@@ -192,7 +192,7 @@
  private:
   void OnMessage(rtc::Message* message);
   void OnSessionState(BaseSession* base_session, BaseSession::State state);
-  void OnSessionError(BaseSession* base_session, Session::Error error);
+  void OnSessionError(BaseSession* base_session, BaseSession::Error error);
   void OnSessionInfoMessage(
       Session* session, const buzz::XmlElement* action_elem);
   void OnViewRequest(
diff --git a/talk/session/media/channel_unittest.cc b/talk/session/media/channel_unittest.cc
index b652b74..b8428a8 100644
--- a/talk/session/media/channel_unittest.cc
+++ b/talk/session/media/channel_unittest.cc
@@ -1555,21 +1555,21 @@
     // Test failures in SetLocalContent.
     media_channel1_->set_fail_set_recv_codecs(true);
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_SENTINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_SENTINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
     media_channel1_->set_fail_set_recv_codecs(true);
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_SENTACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_SENTACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
 
     // Test failures in SetRemoteContent.
     media_channel1_->set_fail_set_send_codecs(true);
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
     media_channel1_->set_fail_set_send_codecs(true);
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_RECEIVEDACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_CONTENT, session1_.error());
   }
 
@@ -1581,7 +1581,7 @@
     session1_.set_local_description(sdesc);
 
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_SENTINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_SENTINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasSendStream(1));
 
@@ -1589,7 +1589,7 @@
     sdesc = CreateSessionDescriptionWithStream(2);
     session1_.set_local_description(sdesc);
 
-    session1_.SetState(cricket::Session::STATE_SENTINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_SENTINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_FALSE(media_channel1_->HasSendStream(1));
     EXPECT_TRUE(media_channel1_->HasSendStream(2));
@@ -1603,13 +1603,13 @@
     session1_.set_remote_description(sdesc);
 
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasRecvStream(1));
 
     sdesc = CreateSessionDescriptionWithStream(2);
     session1_.set_remote_description(sdesc);
-    session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_FALSE(media_channel1_->HasRecvStream(1));
     EXPECT_TRUE(media_channel1_->HasRecvStream(2));
@@ -1623,7 +1623,7 @@
     session1_.set_remote_description(sdesc);
 
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_RECEIVEDINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasRecvStream(1));
 
@@ -1631,7 +1631,7 @@
     sdesc = CreateSessionDescriptionWithStream(2);
     session1_.set_local_description(sdesc);
 
-    session1_.SetState(cricket::Session::STATE_SENTPRACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_SENTPRACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasRecvStream(1));
     EXPECT_TRUE(media_channel1_->HasSendStream(2));
@@ -1640,7 +1640,7 @@
     sdesc = CreateSessionDescriptionWithStream(3);
     session1_.set_local_description(sdesc);
 
-    session1_.SetState(cricket::Session::STATE_SENTACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_SENTACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasRecvStream(1));
     EXPECT_FALSE(media_channel1_->HasSendStream(2));
@@ -1655,7 +1655,7 @@
     session1_.set_local_description(sdesc);
 
     session1_.SetError(cricket::BaseSession::ERROR_NONE, "");
-    session1_.SetState(cricket::Session::STATE_SENTINITIATE);
+    session1_.SetState(cricket::BaseSession::STATE_SENTINITIATE);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasSendStream(1));
 
@@ -1663,7 +1663,7 @@
     sdesc = CreateSessionDescriptionWithStream(2);
     session1_.set_remote_description(sdesc);
 
-    session1_.SetState(cricket::Session::STATE_RECEIVEDPRACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDPRACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasSendStream(1));
     EXPECT_TRUE(media_channel1_->HasRecvStream(2));
@@ -1672,7 +1672,7 @@
     sdesc = CreateSessionDescriptionWithStream(3);
     session1_.set_remote_description(sdesc);
 
-    session1_.SetState(cricket::Session::STATE_RECEIVEDACCEPT);
+    session1_.SetState(cricket::BaseSession::STATE_RECEIVEDACCEPT);
     EXPECT_EQ(cricket::BaseSession::ERROR_NONE, session1_.error());
     EXPECT_TRUE(media_channel1_->HasSendStream(1));
     EXPECT_FALSE(media_channel1_->HasRecvStream(2));
diff --git a/talk/session/media/currentspeakermonitor.h b/talk/session/media/currentspeakermonitor.h
index 0397a6d..64beb98 100644
--- a/talk/session/media/currentspeakermonitor.h
+++ b/talk/session/media/currentspeakermonitor.h
@@ -39,7 +39,6 @@
 namespace cricket {
 
 class BaseSession;
-class Session;
 struct AudioInfo;
 struct MediaStreams;
 
diff --git a/talk/session/tunnel/pseudotcpchannel.h b/talk/session/tunnel/pseudotcpchannel.h
index ad6d907..e216f35 100644
--- a/talk/session/tunnel/pseudotcpchannel.h
+++ b/talk/session/tunnel/pseudotcpchannel.h
@@ -29,10 +29,10 @@
 #define TALK_SESSION_TUNNEL_PSEUDOTCPCHANNEL_H_
 
 #include "webrtc/p2p/base/pseudotcp.h"
-#include "webrtc/p2p/base/session.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/messagequeue.h"
 #include "webrtc/base/stream.h"
+#include "webrtc/libjingle/session/session.h"
 
 namespace rtc {
 class Thread;
diff --git a/webrtc/libjingle/session/session.cc b/webrtc/libjingle/session/session.cc
new file mode 100644
index 0000000..cf07c1f
--- /dev/null
+++ b/webrtc/libjingle/session/session.cc
@@ -0,0 +1,859 @@
+/*
+ *  Copyright 2004 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/session.h"
+
+#include "webrtc/libjingle/xmpp/constants.h"
+#include "webrtc/libjingle/xmpp/jid.h"
+#include "webrtc/p2p/base/p2ptransport.h"
+
+namespace cricket {
+
+bool BadMessage(const buzz::QName type,
+                const std::string& text,
+                MessageError* err) {
+  err->SetType(type);
+  err->SetText(text);
+  return false;
+}
+
+Session::Session(SessionManager* session_manager,
+                 const std::string& local_name,
+                 const std::string& initiator_name,
+                 const std::string& sid,
+                 const std::string& content_type,
+                 SessionClient* client)
+    : BaseSession(session_manager->signaling_thread(),
+                  session_manager->worker_thread(),
+                  session_manager->port_allocator(),
+                  sid, content_type, initiator_name == local_name) {
+  ASSERT(client != NULL);
+  session_manager_ = session_manager;
+  local_name_ = local_name;
+  initiator_name_ = initiator_name;
+  transport_parser_ = new P2PTransportParser();
+  client_ = client;
+  initiate_acked_ = false;
+  current_protocol_ = PROTOCOL_HYBRID;
+}
+
+Session::~Session() {
+  delete transport_parser_;
+}
+
+bool Session::Initiate(const std::string& to,
+                       const SessionDescription* sdesc) {
+  ASSERT(signaling_thread()->IsCurrent());
+  SessionError error;
+
+  // Only from STATE_INIT
+  if (state() != STATE_INIT)
+    return false;
+
+  // Setup for signaling.
+  set_remote_name(to);
+  set_local_description(sdesc);
+  if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()),
+                              &error)) {
+    LOG(LS_ERROR) << "Could not create transports: " << error.text;
+    return false;
+  }
+
+  if (!SendInitiateMessage(sdesc, &error)) {
+    LOG(LS_ERROR) << "Could not send initiate message: " << error.text;
+    return false;
+  }
+
+  // We need to connect transport proxy and impl here so that we can process
+  // the TransportDescriptions.
+  SpeculativelyConnectAllTransportChannels();
+
+  PushdownTransportDescription(CS_LOCAL, CA_OFFER, NULL);
+  SetState(Session::STATE_SENTINITIATE);
+  return true;
+}
+
+bool Session::Accept(const SessionDescription* sdesc) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  // Only if just received initiate
+  if (state() != STATE_RECEIVEDINITIATE)
+    return false;
+
+  // Setup for signaling.
+  set_local_description(sdesc);
+
+  SessionError error;
+  if (!SendAcceptMessage(sdesc, &error)) {
+    LOG(LS_ERROR) << "Could not send accept message: " << error.text;
+    return false;
+  }
+  // TODO(juberti): Add BUNDLE support to transport-info messages.
+  PushdownTransportDescription(CS_LOCAL, CA_ANSWER, NULL);
+  MaybeEnableMuxingSupport();  // Enable transport channel mux if supported.
+  SetState(Session::STATE_SENTACCEPT);
+  return true;
+}
+
+bool Session::Reject(const std::string& reason) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  // Reject is sent in response to an initiate or modify, to reject the
+  // request
+  if (state() != STATE_RECEIVEDINITIATE && state() != STATE_RECEIVEDMODIFY)
+    return false;
+
+  SessionError error;
+  if (!SendRejectMessage(reason, &error)) {
+    LOG(LS_ERROR) << "Could not send reject message: " << error.text;
+    return false;
+  }
+
+  SetState(STATE_SENTREJECT);
+  return true;
+}
+
+bool Session::TerminateWithReason(const std::string& reason) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  // Either side can terminate, at any time.
+  switch (state()) {
+    case STATE_SENTTERMINATE:
+    case STATE_RECEIVEDTERMINATE:
+      return false;
+
+    case STATE_SENTREJECT:
+    case STATE_RECEIVEDREJECT:
+      // We don't need to send terminate if we sent or received a reject...
+      // it's implicit.
+      break;
+
+    default:
+      SessionError error;
+      if (!SendTerminateMessage(reason, &error)) {
+        LOG(LS_ERROR) << "Could not send terminate message: " << error.text;
+        return false;
+      }
+      break;
+  }
+
+  SetState(STATE_SENTTERMINATE);
+  return true;
+}
+
+bool Session::SendInfoMessage(const XmlElements& elems,
+                              const std::string& remote_name) {
+  ASSERT(signaling_thread()->IsCurrent());
+  SessionError error;
+  if (!SendMessage(ACTION_SESSION_INFO, elems, remote_name, &error)) {
+    LOG(LS_ERROR) << "Could not send info message " << error.text;
+    return false;
+  }
+  return true;
+}
+
+bool Session::SendDescriptionInfoMessage(const ContentInfos& contents) {
+  XmlElements elems;
+  WriteError write_error;
+  if (!WriteDescriptionInfo(current_protocol_,
+                            contents,
+                            GetContentParsers(),
+                            &elems, &write_error)) {
+    LOG(LS_ERROR) << "Could not write description info message: "
+                  << write_error.text;
+    return false;
+  }
+  SessionError error;
+  if (!SendMessage(ACTION_DESCRIPTION_INFO, elems, &error)) {
+    LOG(LS_ERROR) << "Could not send description info message: "
+                  << error.text;
+    return false;
+  }
+  return true;
+}
+
+TransportInfos Session::GetEmptyTransportInfos(
+    const ContentInfos& contents) const {
+  TransportInfos tinfos;
+  for (ContentInfos::const_iterator content = contents.begin();
+       content != contents.end(); ++content) {
+    tinfos.push_back(TransportInfo(content->name,
+                                   TransportDescription(transport_type(),
+                                                        std::string(),
+                                                        std::string())));
+  }
+  return tinfos;
+}
+
+bool Session::OnRemoteCandidates(
+    const TransportInfos& tinfos, ParseError* error) {
+  for (TransportInfos::const_iterator tinfo = tinfos.begin();
+       tinfo != tinfos.end(); ++tinfo) {
+    std::string str_error;
+    if (!BaseSession::OnRemoteCandidates(
+        tinfo->content_name, tinfo->description.candidates, &str_error)) {
+      return BadParse(str_error, error);
+    }
+  }
+  return true;
+}
+
+bool Session::CreateTransportProxies(const TransportInfos& tinfos,
+                                     SessionError* error) {
+  for (TransportInfos::const_iterator tinfo = tinfos.begin();
+       tinfo != tinfos.end(); ++tinfo) {
+    if (tinfo->description.transport_type != transport_type()) {
+      error->SetText("No supported transport in offer.");
+      return false;
+    }
+
+    GetOrCreateTransportProxy(tinfo->content_name);
+  }
+  return true;
+}
+
+TransportParserMap Session::GetTransportParsers() {
+  TransportParserMap parsers;
+  parsers[transport_type()] = transport_parser_;
+  return parsers;
+}
+
+CandidateTranslatorMap Session::GetCandidateTranslators() {
+  CandidateTranslatorMap translators;
+  // NOTE: This technique makes it impossible to parse G-ICE
+  // candidates in session-initiate messages because the channels
+  // aren't yet created at that point.  Since we don't use candidates
+  // in session-initiate messages, we should be OK.  Once we switch to
+  // ICE, this translation shouldn't be necessary.
+  for (TransportMap::const_iterator iter = transport_proxies().begin();
+       iter != transport_proxies().end(); ++iter) {
+    translators[iter->first] = iter->second;
+  }
+  return translators;
+}
+
+ContentParserMap Session::GetContentParsers() {
+  ContentParserMap parsers;
+  parsers[content_type()] = client_;
+  // We need to be able parse both RTP-based and SCTP-based Jingle
+  // with the same client.
+  if (content_type() == NS_JINGLE_RTP) {
+    parsers[NS_JINGLE_DRAFT_SCTP] = client_;
+  }
+  return parsers;
+}
+
+void Session::OnTransportRequestSignaling(Transport* transport) {
+  ASSERT(signaling_thread()->IsCurrent());
+  TransportProxy* transproxy = GetTransportProxy(transport);
+  ASSERT(transproxy != NULL);
+  if (transproxy) {
+    // Reset candidate allocation status for the transport proxy.
+    transproxy->set_candidates_allocated(false);
+  }
+  SignalRequestSignaling(this);
+}
+
+void Session::OnTransportConnecting(Transport* transport) {
+  // This is an indication that we should begin watching the writability
+  // state of the transport.
+  OnTransportWritable(transport);
+}
+
+void Session::OnTransportWritable(Transport* transport) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  // If the transport is not writable, start a timer to make sure that it
+  // becomes writable within a reasonable amount of time.  If it does not, we
+  // terminate since we can't actually send data.  If the transport is writable,
+  // cancel the timer.  Note that writability transitions may occur repeatedly
+  // during the lifetime of the session.
+  signaling_thread()->Clear(this, MSG_TIMEOUT);
+  if (transport->HasChannels() && !transport->writable()) {
+    signaling_thread()->PostDelayed(
+        session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT);
+  }
+}
+
+void Session::OnTransportProxyCandidatesReady(TransportProxy* transproxy,
+                                              const Candidates& candidates) {
+  ASSERT(signaling_thread()->IsCurrent());
+  if (transproxy != NULL) {
+    if (initiator() && !initiate_acked_) {
+      // TODO: This is to work around server re-ordering
+      // messages.  We send the candidates once the session-initiate
+      // is acked.  Once we have fixed the server to guarantee message
+      // order, we can remove this case.
+      transproxy->AddUnsentCandidates(candidates);
+    } else {
+      if (!transproxy->negotiated()) {
+        transproxy->AddSentCandidates(candidates);
+      }
+      SessionError error;
+      if (!SendTransportInfoMessage(transproxy, candidates, &error)) {
+        LOG(LS_ERROR) << "Could not send transport info message: "
+                      << error.text;
+        return;
+      }
+    }
+  }
+}
+
+void Session::OnIncomingMessage(const SessionMessage& msg) {
+  ASSERT(signaling_thread()->IsCurrent());
+  ASSERT(state() == STATE_INIT || msg.from == remote_name());
+
+  if (current_protocol_== PROTOCOL_HYBRID) {
+    if (msg.protocol == PROTOCOL_GINGLE) {
+      current_protocol_ = PROTOCOL_GINGLE;
+    } else {
+      current_protocol_ = PROTOCOL_JINGLE;
+    }
+  }
+
+  bool valid = false;
+  MessageError error;
+  switch (msg.type) {
+    case ACTION_SESSION_INITIATE:
+      valid = OnInitiateMessage(msg, &error);
+      break;
+    case ACTION_SESSION_INFO:
+      valid = OnInfoMessage(msg);
+      break;
+    case ACTION_SESSION_ACCEPT:
+      valid = OnAcceptMessage(msg, &error);
+      break;
+    case ACTION_SESSION_REJECT:
+      valid = OnRejectMessage(msg, &error);
+      break;
+    case ACTION_SESSION_TERMINATE:
+      valid = OnTerminateMessage(msg, &error);
+      break;
+    case ACTION_TRANSPORT_INFO:
+      valid = OnTransportInfoMessage(msg, &error);
+      break;
+    case ACTION_TRANSPORT_ACCEPT:
+      valid = OnTransportAcceptMessage(msg, &error);
+      break;
+    case ACTION_DESCRIPTION_INFO:
+      valid = OnDescriptionInfoMessage(msg, &error);
+      break;
+    default:
+      valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST,
+                         "unknown session message type",
+                         &error);
+  }
+
+  if (valid) {
+    SendAcknowledgementMessage(msg.stanza);
+  } else {
+    SignalErrorMessage(this, msg.stanza, error.type,
+                       "modify", error.text, NULL);
+  }
+}
+
+void Session::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
+                                 const buzz::XmlElement* response_stanza,
+                                 const SessionMessage& msg) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  if (msg.type == ACTION_SESSION_INITIATE) {
+    OnInitiateAcked();
+  }
+}
+
+void Session::OnInitiateAcked() {
+  // TODO: This is to work around server re-ordering
+  // messages.  We send the candidates once the session-initiate
+  // is acked.  Once we have fixed the server to guarantee message
+  // order, we can remove this case.
+  if (!initiate_acked_) {
+    initiate_acked_ = true;
+    SessionError error;
+    SendAllUnsentTransportInfoMessages(&error);
+  }
+}
+
+void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
+                           const buzz::XmlElement* error_stanza) {
+  ASSERT(signaling_thread()->IsCurrent());
+
+  SessionMessage msg;
+  ParseError parse_error;
+  if (!ParseSessionMessage(orig_stanza, &msg, &parse_error)) {
+    LOG(LS_ERROR) << "Error parsing failed send: " << parse_error.text
+                  << ":" << orig_stanza;
+    return;
+  }
+
+  // If the error is a session redirect, call OnRedirectError, which will
+  // continue the session with a new remote JID.
+  SessionRedirect redirect;
+  if (FindSessionRedirect(error_stanza, &redirect)) {
+    SessionError error;
+    if (!OnRedirectError(redirect, &error)) {
+      // TODO: Should we send a message back?  The standard
+      // says nothing about it.
+      std::ostringstream desc;
+      desc << "Failed to redirect: " << error.text;
+      LOG(LS_ERROR) << desc.str();
+      SetError(ERROR_RESPONSE, desc.str());
+    }
+    return;
+  }
+
+  std::string error_type = "cancel";
+
+  const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
+  if (error) {
+    error_type = error->Attr(buzz::QN_TYPE);
+
+    LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n"
+                  << "in response to:\n" << orig_stanza->Str();
+  } else {
+    // don't crash if <error> is missing
+    LOG(LS_ERROR) << "Session error without <error/> element, ignoring";
+    return;
+  }
+
+  if (msg.type == ACTION_TRANSPORT_INFO) {
+    // Transport messages frequently generate errors because they are sent right
+    // when we detect a network failure.  For that reason, we ignore such
+    // errors, because if we do not establish writability again, we will
+    // terminate anyway.  The exceptions are transport-specific error tags,
+    // which we pass on to the respective transport.
+  } else if ((error_type != "continue") && (error_type != "wait")) {
+    // We do not set an error if the other side said it is okay to continue
+    // (possibly after waiting).  These errors can be ignored.
+    SetError(ERROR_RESPONSE, "");
+  }
+}
+
+bool Session::OnInitiateMessage(const SessionMessage& msg,
+                                MessageError* error) {
+  if (!CheckState(STATE_INIT, error))
+    return false;
+
+  SessionInitiate init;
+  if (!ParseSessionInitiate(msg.protocol, msg.action_elem,
+                            GetContentParsers(), GetTransportParsers(),
+                            GetCandidateTranslators(),
+                            &init, error))
+    return false;
+
+  SessionError session_error;
+  if (!CreateTransportProxies(init.transports, &session_error)) {
+    return BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE,
+                      session_error.text, error);
+  }
+
+  set_remote_name(msg.from);
+  set_initiator_name(msg.initiator);
+  set_remote_description(new SessionDescription(init.ClearContents(),
+                                                init.transports,
+                                                init.groups));
+  // Updating transport with TransportDescription.
+  PushdownTransportDescription(CS_REMOTE, CA_OFFER, NULL);
+  SetState(STATE_RECEIVEDINITIATE);
+
+  // Users of Session may listen to state change and call Reject().
+  if (state() != STATE_SENTREJECT) {
+    if (!OnRemoteCandidates(init.transports, error))
+      return false;
+
+    // TODO(juberti): Auto-generate and push down the local transport answer.
+    // This is necessary for trickling to work with RFC 5245 ICE.
+  }
+  return true;
+}
+
+bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
+  if (!CheckState(STATE_SENTINITIATE, error))
+    return false;
+
+  SessionAccept accept;
+  if (!ParseSessionAccept(msg.protocol, msg.action_elem,
+                          GetContentParsers(), GetTransportParsers(),
+                          GetCandidateTranslators(),
+                          &accept, error)) {
+    return false;
+  }
+
+  // If we get an accept, we can assume the initiate has been
+  // received, even if we haven't gotten an IQ response.
+  OnInitiateAcked();
+
+  set_remote_description(new SessionDescription(accept.ClearContents(),
+                                                accept.transports,
+                                                accept.groups));
+  // Updating transport with TransportDescription.
+  PushdownTransportDescription(CS_REMOTE, CA_ANSWER, NULL);
+  MaybeEnableMuxingSupport();  // Enable transport channel mux if supported.
+  SetState(STATE_RECEIVEDACCEPT);
+
+  if (!OnRemoteCandidates(accept.transports, error))
+    return false;
+
+  return true;
+}
+
+bool Session::OnRejectMessage(const SessionMessage& msg, MessageError* error) {
+  if (!CheckState(STATE_SENTINITIATE, error))
+    return false;
+
+  SetState(STATE_RECEIVEDREJECT);
+  return true;
+}
+
+bool Session::OnInfoMessage(const SessionMessage& msg) {
+  SignalInfoMessage(this, msg.action_elem);
+  return true;
+}
+
+bool Session::OnTerminateMessage(const SessionMessage& msg,
+                                 MessageError* error) {
+  SessionTerminate term;
+  if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error))
+    return false;
+
+  SignalReceivedTerminateReason(this, term.reason);
+  if (term.debug_reason != buzz::STR_EMPTY) {
+    LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason;
+  }
+
+  SetState(STATE_RECEIVEDTERMINATE);
+  return true;
+}
+
+bool Session::OnTransportInfoMessage(const SessionMessage& msg,
+                                     MessageError* error) {
+  TransportInfos tinfos;
+  if (!ParseTransportInfos(msg.protocol, msg.action_elem,
+                           initiator_description()->contents(),
+                           GetTransportParsers(), GetCandidateTranslators(),
+                           &tinfos, error))
+    return false;
+
+  if (!OnRemoteCandidates(tinfos, error))
+    return false;
+
+  return true;
+}
+
+bool Session::OnTransportAcceptMessage(const SessionMessage& msg,
+                                       MessageError* error) {
+  // TODO: Currently here only for compatibility with
+  // Gingle 1.1 clients (notably, Google Voice).
+  return true;
+}
+
+bool Session::OnDescriptionInfoMessage(const SessionMessage& msg,
+                              MessageError* error) {
+  if (!CheckState(STATE_INPROGRESS, error))
+    return false;
+
+  DescriptionInfo description_info;
+  if (!ParseDescriptionInfo(msg.protocol, msg.action_elem,
+                            GetContentParsers(), GetTransportParsers(),
+                            GetCandidateTranslators(),
+                            &description_info, error)) {
+    return false;
+  }
+
+  ContentInfos& updated_contents = description_info.contents;
+
+  // TODO: Currently, reflector sends back
+  // video stream updates even for an audio-only call, which causes
+  // this to fail.  Put this back once reflector is fixed.
+  //
+  // ContentInfos::iterator it;
+  // First, ensure all updates are valid before modifying remote_description_.
+  // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
+  //   if (remote_description()->GetContentByName(it->name) == NULL) {
+  //     return false;
+  //   }
+  // }
+
+  // TODO: We used to replace contents from an update, but
+  // that no longer works with partial updates.  We need to figure out
+  // a way to merge patial updates into contents.  For now, users of
+  // Session should listen to SignalRemoteDescriptionUpdate and handle
+  // updates.  They should not expect remote_description to be the
+  // latest value.
+  //
+  // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
+  //     remote_description()->RemoveContentByName(it->name);
+  //     remote_description()->AddContent(it->name, it->type, it->description);
+  //   }
+  // }
+
+  SignalRemoteDescriptionUpdate(this, updated_contents);
+  return true;
+}
+
+bool BareJidsEqual(const std::string& name1,
+                   const std::string& name2) {
+  buzz::Jid jid1(name1);
+  buzz::Jid jid2(name2);
+
+  return jid1.IsValid() && jid2.IsValid() && jid1.BareEquals(jid2);
+}
+
+bool Session::OnRedirectError(const SessionRedirect& redirect,
+                              SessionError* error) {
+  MessageError message_error;
+  if (!CheckState(STATE_SENTINITIATE, &message_error)) {
+    return BadWrite(message_error.text, error);
+  }
+
+  if (!BareJidsEqual(remote_name(), redirect.target))
+    return BadWrite("Redirection not allowed: must be the same bare jid.",
+                    error);
+
+  // When we receive a redirect, we point the session at the new JID
+  // and resend the candidates.
+  set_remote_name(redirect.target);
+  return (SendInitiateMessage(local_description(), error) &&
+          ResendAllTransportInfoMessages(error));
+}
+
+bool Session::CheckState(State expected, MessageError* error) {
+  if (state() != expected) {
+    // The server can deliver messages out of order/repeated for various
+    // reasons. For example, if the server does not recive our iq response,
+    // it could assume that the iq it sent was lost, and will then send
+    // it again. Ideally, we should implement reliable messaging with
+    // duplicate elimination.
+    return BadMessage(buzz::QN_STANZA_NOT_ALLOWED,
+                      "message not allowed in current state",
+                      error);
+  }
+  return true;
+}
+
+void Session::SetError(Error error, const std::string& error_desc) {
+  BaseSession::SetError(error, error_desc);
+  if (error != ERROR_NONE)
+    signaling_thread()->Post(this, MSG_ERROR);
+}
+
+void Session::OnMessage(rtc::Message* pmsg) {
+  // preserve this because BaseSession::OnMessage may modify it
+  State orig_state = state();
+
+  BaseSession::OnMessage(pmsg);
+
+  switch (pmsg->message_id) {
+  case MSG_ERROR:
+    TerminateWithReason(STR_TERMINATE_ERROR);
+    break;
+
+  case MSG_STATE:
+    switch (orig_state) {
+    case STATE_SENTREJECT:
+    case STATE_RECEIVEDREJECT:
+      // Assume clean termination.
+      Terminate();
+      break;
+
+    case STATE_SENTTERMINATE:
+    case STATE_RECEIVEDTERMINATE:
+      session_manager_->DestroySession(this);
+      break;
+
+    default:
+      // Explicitly ignoring some states here.
+      break;
+    }
+    break;
+  }
+}
+
+bool Session::SendInitiateMessage(const SessionDescription* sdesc,
+                                  SessionError* error) {
+  SessionInitiate init;
+  init.contents = sdesc->contents();
+  init.transports = GetEmptyTransportInfos(init.contents);
+  init.groups = sdesc->groups();
+  return SendMessage(ACTION_SESSION_INITIATE, init, error);
+}
+
+bool Session::WriteSessionAction(
+    SignalingProtocol protocol, const SessionInitiate& init,
+    XmlElements* elems, WriteError* error) {
+  return WriteSessionInitiate(protocol, init.contents, init.transports,
+                              GetContentParsers(), GetTransportParsers(),
+                              GetCandidateTranslators(), init.groups,
+                              elems, error);
+}
+
+bool Session::SendAcceptMessage(const SessionDescription* sdesc,
+                                SessionError* error) {
+  XmlElements elems;
+  if (!WriteSessionAccept(current_protocol_,
+                          sdesc->contents(),
+                          GetEmptyTransportInfos(sdesc->contents()),
+                          GetContentParsers(), GetTransportParsers(),
+                          GetCandidateTranslators(), sdesc->groups(),
+                          &elems, error)) {
+    return false;
+  }
+  return SendMessage(ACTION_SESSION_ACCEPT, elems, error);
+}
+
+bool Session::SendRejectMessage(const std::string& reason,
+                                SessionError* error) {
+  SessionTerminate term(reason);
+  return SendMessage(ACTION_SESSION_REJECT, term, error);
+}
+
+bool Session::SendTerminateMessage(const std::string& reason,
+                                   SessionError* error) {
+  SessionTerminate term(reason);
+  return SendMessage(ACTION_SESSION_TERMINATE, term, error);
+}
+
+bool Session::WriteSessionAction(SignalingProtocol protocol,
+                                 const SessionTerminate& term,
+                                 XmlElements* elems, WriteError* error) {
+  WriteSessionTerminate(protocol, term, elems);
+  return true;
+}
+
+bool Session::SendTransportInfoMessage(const TransportInfo& tinfo,
+                                       SessionError* error) {
+  return SendMessage(ACTION_TRANSPORT_INFO, tinfo, error);
+}
+
+bool Session::SendTransportInfoMessage(const TransportProxy* transproxy,
+                                       const Candidates& candidates,
+                                       SessionError* error) {
+  return SendTransportInfoMessage(TransportInfo(transproxy->content_name(),
+      TransportDescription(transproxy->type(), std::vector<std::string>(),
+                           std::string(), std::string(), ICEMODE_FULL,
+                           CONNECTIONROLE_NONE, NULL, candidates)), error);
+}
+
+bool Session::WriteSessionAction(SignalingProtocol protocol,
+                                 const TransportInfo& tinfo,
+                                 XmlElements* elems, WriteError* error) {
+  TransportInfos tinfos;
+  tinfos.push_back(tinfo);
+  return WriteTransportInfos(protocol, tinfos,
+                             GetTransportParsers(), GetCandidateTranslators(),
+                             elems, error);
+}
+
+bool Session::ResendAllTransportInfoMessages(SessionError* error) {
+  for (TransportMap::const_iterator iter = transport_proxies().begin();
+       iter != transport_proxies().end(); ++iter) {
+    TransportProxy* transproxy = iter->second;
+    if (transproxy->sent_candidates().size() > 0) {
+      if (!SendTransportInfoMessage(
+              transproxy, transproxy->sent_candidates(), error)) {
+        LOG(LS_ERROR) << "Could not resend transport info messages: "
+                      << error->text;
+        return false;
+      }
+      transproxy->ClearSentCandidates();
+    }
+  }
+  return true;
+}
+
+bool Session::SendAllUnsentTransportInfoMessages(SessionError* error) {
+  for (TransportMap::const_iterator iter = transport_proxies().begin();
+       iter != transport_proxies().end(); ++iter) {
+    TransportProxy* transproxy = iter->second;
+    if (transproxy->unsent_candidates().size() > 0) {
+      if (!SendTransportInfoMessage(
+              transproxy, transproxy->unsent_candidates(), error)) {
+        LOG(LS_ERROR) << "Could not send unsent transport info messages: "
+                      << error->text;
+        return false;
+      }
+      transproxy->ClearUnsentCandidates();
+    }
+  }
+  return true;
+}
+
+bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
+                          SessionError* error) {
+    return SendMessage(type, action_elems, remote_name(), error);
+}
+
+bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
+                          const std::string& remote_name, SessionError* error) {
+  rtc::scoped_ptr<buzz::XmlElement> stanza(
+      new buzz::XmlElement(buzz::QN_IQ));
+
+  SessionMessage msg(current_protocol_, type, id(), initiator_name());
+  msg.to = remote_name;
+  WriteSessionMessage(msg, action_elems, stanza.get());
+
+  SignalOutgoingMessage(this, stanza.get());
+  return true;
+}
+
+template <typename Action>
+bool Session::SendMessage(ActionType type, const Action& action,
+                          SessionError* error) {
+  rtc::scoped_ptr<buzz::XmlElement> stanza(
+      new buzz::XmlElement(buzz::QN_IQ));
+  if (!WriteActionMessage(type, action, stanza.get(), error))
+    return false;
+
+  SignalOutgoingMessage(this, stanza.get());
+  return true;
+}
+
+template <typename Action>
+bool Session::WriteActionMessage(ActionType type, const Action& action,
+                                 buzz::XmlElement* stanza,
+                                 WriteError* error) {
+  if (current_protocol_ == PROTOCOL_HYBRID) {
+    if (!WriteActionMessage(PROTOCOL_JINGLE, type, action, stanza, error))
+      return false;
+    if (!WriteActionMessage(PROTOCOL_GINGLE, type, action, stanza, error))
+      return false;
+  } else {
+    if (!WriteActionMessage(current_protocol_, type, action, stanza, error))
+      return false;
+  }
+  return true;
+}
+
+template <typename Action>
+bool Session::WriteActionMessage(SignalingProtocol protocol,
+                                 ActionType type, const Action& action,
+                                 buzz::XmlElement* stanza, WriteError* error) {
+  XmlElements action_elems;
+  if (!WriteSessionAction(protocol, action, &action_elems, error))
+    return false;
+
+  SessionMessage msg(protocol, type, id(), initiator_name());
+  msg.to = remote_name();
+
+  WriteSessionMessage(msg, action_elems, stanza);
+  return true;
+}
+
+void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) {
+  rtc::scoped_ptr<buzz::XmlElement> ack(
+      new buzz::XmlElement(buzz::QN_IQ));
+  ack->SetAttr(buzz::QN_TO, remote_name());
+  ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
+  ack->SetAttr(buzz::QN_TYPE, "result");
+
+  SignalOutgoingMessage(this, ack.get());
+}
+
+}  // namespace cricket
diff --git a/webrtc/libjingle/session/session.h b/webrtc/libjingle/session/session.h
new file mode 100644
index 0000000..4f185f1
--- /dev/null
+++ b/webrtc/libjingle/session/session.h
@@ -0,0 +1,265 @@
+/*
+ *  Copyright 2004 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.
+ */
+
+#ifndef WEBRTC_LIBJINGLE_SESSION_SESSION_H_
+#define WEBRTC_LIBJINGLE_SESSION_SESSION_H_
+
+#include <string>
+
+#include "webrtc/libjingle/xmllite/xmlelement.h"
+#include "webrtc/libjingle/xmpp/constants.h"
+#include "webrtc/p2p/base/parsing.h"
+#include "webrtc/p2p/base/session.h"
+#include "webrtc/p2p/base/sessionclient.h"
+#include "webrtc/p2p/base/sessionmanager.h"
+#include "webrtc/p2p/base/sessionmessages.h"
+
+
+namespace cricket {
+
+// Used for errors that will send back a specific error message to the
+// remote peer.  We add "type" to the errors because it's needed for
+// SignalErrorMessage.
+struct MessageError : ParseError {
+  buzz::QName type;
+
+  // if unset, assume type is a parse error
+  MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
+
+  void SetType(const buzz::QName type) {
+    this->type = type;
+  }
+};
+
+// Used for errors that may be returned by public session methods that
+// can fail.
+// TODO: Use this error in Session::Initiate and
+// Session::Accept.
+struct SessionError : WriteError {
+};
+
+// A specific Session created by the SessionManager, using XMPP for protocol.
+class Session : public BaseSession {
+ public:
+  // Returns the manager that created and owns this session.
+  SessionManager* session_manager() const { return session_manager_; }
+
+  // Returns the client that is handling the application data of this session.
+  SessionClient* client() const { return client_; }
+
+    // Returns the JID of this client.
+  const std::string& local_name() const { return local_name_; }
+
+  // Returns the JID of the other peer in this session.
+  const std::string& remote_name() const { return remote_name_; }
+
+  // Set the JID of the other peer in this session.
+  // Typically the remote_name_ is set when the session is initiated.
+  // However, sometimes (e.g when a proxy is used) the peer name is
+  // known after the BaseSession has been initiated and it must be updated
+  // explicitly.
+  void set_remote_name(const std::string& name) { remote_name_ = name; }
+
+  // Set the JID of the initiator of this session. Allows for the overriding
+  // of the initiator to be a third-party, eg. the MUC JID when creating p2p
+  // sessions.
+  void set_initiator_name(const std::string& name) { initiator_name_ = name; }
+
+  // Indicates the JID of the entity who initiated this session.
+  // In special cases, may be different than both local_name and remote_name.
+  const std::string& initiator_name() const { return initiator_name_; }
+
+  SignalingProtocol current_protocol() const { return current_protocol_; }
+
+  void set_current_protocol(SignalingProtocol protocol) {
+    current_protocol_ = protocol;
+  }
+
+  // Updates the error state, signaling if necessary.
+  virtual void SetError(Error error, const std::string& error_desc);
+
+  // When the session needs to send signaling messages, it beings by requesting
+  // signaling.  The client should handle this by calling OnSignalingReady once
+  // it is ready to send the messages.
+  // (These are called only by SessionManager.)
+  sigslot::signal1<Session*> SignalRequestSignaling;
+  void OnSignalingReady() { BaseSession::OnSignalingReady(); }
+
+  // Takes ownership of session description.
+  // TODO: Add an error argument to pass back to the caller.
+  bool Initiate(const std::string& to,
+                const SessionDescription* sdesc);
+
+  // When we receive an initiate, we create a session in the
+  // RECEIVEDINITIATE state and respond by accepting or rejecting.
+  // Takes ownership of session description.
+  // TODO: Add an error argument to pass back to the caller.
+  bool Accept(const SessionDescription* sdesc);
+  bool Reject(const std::string& reason);
+  bool Terminate() {
+    return TerminateWithReason(STR_TERMINATE_SUCCESS);
+  }
+  bool TerminateWithReason(const std::string& reason);
+  // Fired whenever we receive a terminate message along with a reason
+  sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
+
+  // The two clients in the session may also send one another
+  // arbitrary XML messages, which are called "info" messages. Sending
+  // takes ownership of the given elements.  The signal does not; the
+  // parent element will be deleted after the signal.
+  bool SendInfoMessage(const XmlElements& elems,
+                       const std::string& remote_name);
+  bool SendDescriptionInfoMessage(const ContentInfos& contents);
+  sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage;
+
+ private:
+  // Creates or destroys a session.  (These are called only SessionManager.)
+  Session(SessionManager *session_manager,
+          const std::string& local_name, const std::string& initiator_name,
+          const std::string& sid, const std::string& content_type,
+          SessionClient* client);
+  ~Session();
+  // For each transport info, create a transport proxy.  Can fail for
+  // incompatible transport types.
+  bool CreateTransportProxies(const TransportInfos& tinfos,
+                              SessionError* error);
+  bool OnRemoteCandidates(const TransportInfos& tinfos,
+                          ParseError* error);
+  // Returns a TransportInfo without candidates for each content name.
+  // Uses the transport_type_ of the session.
+  TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
+
+    // Maps passed to serialization functions.
+  TransportParserMap GetTransportParsers();
+  ContentParserMap GetContentParsers();
+  CandidateTranslatorMap GetCandidateTranslators();
+
+  virtual void OnTransportRequestSignaling(Transport* transport);
+  virtual void OnTransportConnecting(Transport* transport);
+  virtual void OnTransportWritable(Transport* transport);
+  virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy,
+                                               const Candidates& candidates);
+  virtual void OnMessage(rtc::Message *pmsg);
+
+  // Send various kinds of session messages.
+  bool SendInitiateMessage(const SessionDescription* sdesc,
+                           SessionError* error);
+  bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
+  bool SendRejectMessage(const std::string& reason, SessionError* error);
+  bool SendTerminateMessage(const std::string& reason, SessionError* error);
+  bool SendTransportInfoMessage(const TransportInfo& tinfo,
+                                SessionError* error);
+  bool SendTransportInfoMessage(const TransportProxy* transproxy,
+                                const Candidates& candidates,
+                                SessionError* error);
+
+  bool ResendAllTransportInfoMessages(SessionError* error);
+  bool SendAllUnsentTransportInfoMessages(SessionError* error);
+
+  // All versions of SendMessage send a message of the given type to
+  // the other client.  Can pass either a set of elements or an
+  // "action", which must have a WriteSessionAction method to go along
+  // with it.  Sending with an action supports sending a "hybrid"
+  // message.  Sending with elements must be sent as Jingle or Gingle.
+
+  // When passing elems, must be either Jingle or Gingle protocol.
+  // Takes ownership of action_elems.
+  bool SendMessage(ActionType type, const XmlElements& action_elems,
+                   SessionError* error);
+  // Sends a messge, but overrides the remote name.
+  bool SendMessage(ActionType type, const XmlElements& action_elems,
+                   const std::string& remote_name,
+                   SessionError* error);
+  // When passing an action, may be Hybrid protocol.
+  template <typename Action>
+  bool SendMessage(ActionType type, const Action& action,
+                   SessionError* error);
+
+  // Helper methods to write the session message stanza.
+  template <typename Action>
+  bool WriteActionMessage(ActionType type, const Action& action,
+                          buzz::XmlElement* stanza, WriteError* error);
+  template <typename Action>
+  bool WriteActionMessage(SignalingProtocol protocol,
+                          ActionType type, const Action& action,
+                          buzz::XmlElement* stanza, WriteError* error);
+
+  // Sending messages in hybrid form requires being able to write them
+  // on a per-protocol basis with a common method signature, which all
+  // of these have.
+  bool WriteSessionAction(SignalingProtocol protocol,
+                          const SessionInitiate& init,
+                          XmlElements* elems, WriteError* error);
+  bool WriteSessionAction(SignalingProtocol protocol,
+                          const TransportInfo& tinfo,
+                          XmlElements* elems, WriteError* error);
+  bool WriteSessionAction(SignalingProtocol protocol,
+                          const SessionTerminate& term,
+                          XmlElements* elems, WriteError* error);
+
+  // Sends a message back to the other client indicating that we have received
+  // and accepted their message.
+  void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
+
+  // Once signaling is ready, the session will use this signal to request the
+  // sending of each message.  When messages are received by the other client,
+  // they should be handed to OnIncomingMessage.
+  // (These are called only by SessionManager.)
+  sigslot::signal2<Session* , const buzz::XmlElement*> SignalOutgoingMessage;
+  void OnIncomingMessage(const SessionMessage& msg);
+
+  void OnIncomingResponse(const buzz::XmlElement* orig_stanza,
+                          const buzz::XmlElement* response_stanza,
+                          const SessionMessage& msg);
+  void OnInitiateAcked();
+  void OnFailedSend(const buzz::XmlElement* orig_stanza,
+                    const buzz::XmlElement* error_stanza);
+
+  // Invoked when an error is found in an incoming message.  This is translated
+  // into the appropriate XMPP response by SessionManager.
+  sigslot::signal6<BaseSession*,
+                   const buzz::XmlElement*,
+                   const buzz::QName&,
+                   const std::string&,
+                   const std::string&,
+                   const buzz::XmlElement*> SignalErrorMessage;
+
+  // Handlers for the various types of messages.  These functions may take
+  // pointers to the whole stanza or to just the session element.
+  bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
+  bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
+  bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
+  bool OnInfoMessage(const SessionMessage& msg);
+  bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
+  bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
+  bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
+  bool OnDescriptionInfoMessage(const SessionMessage& msg, MessageError* error);
+  bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
+
+  // Verifies that we are in the appropriate state to receive this message.
+  bool CheckState(State state, MessageError* error);
+
+  SessionManager* session_manager_;
+  bool initiate_acked_;
+  std::string local_name_;
+  std::string initiator_name_;
+  std::string remote_name_;
+  SessionClient* client_;
+  TransportParser* transport_parser_;
+  // Keeps track of what protocol we are speaking.
+  SignalingProtocol current_protocol_;
+
+  friend class SessionManager;  // For access to constructor, destructor,
+                                // and signaling related methods.
+};
+
+}  // namespace cricket
+
+#endif  // WEBRTC_LIBJINGLE_SESSION_SESSION_H_
diff --git a/webrtc/p2p/base/candidate.h b/webrtc/p2p/base/candidate.h
index 44b9b98..43809fa 100644
--- a/webrtc/p2p/base/candidate.h
+++ b/webrtc/p2p/base/candidate.h
@@ -230,6 +230,18 @@
   std::string tcptype_;
 };
 
+// Used during parsing and writing to map component to channel name
+// and back.  This is primarily for converting old G-ICE candidate
+// signalling to new ICE candidate classes.
+class CandidateTranslator {
+ public:
+  virtual ~CandidateTranslator() {}
+  virtual bool GetChannelNameFromComponent(
+      int component, std::string* channel_name) const = 0;
+  virtual bool GetComponentFromChannelName(
+      const std::string& channel_name, int* component) const = 0;
+};
+
 }  // namespace cricket
 
 #endif  // WEBRTC_P2P_BASE_CANDIDATE_H_
diff --git a/webrtc/p2p/base/session.cc b/webrtc/p2p/base/session.cc
index 30a9f2b..8baab1a 100644
--- a/webrtc/p2p/base/session.cc
+++ b/webrtc/p2p/base/session.cc
@@ -12,17 +12,15 @@
 
 #include "webrtc/p2p/base/dtlstransport.h"
 #include "webrtc/p2p/base/p2ptransport.h"
-#include "webrtc/p2p/base/sessionclient.h"
 #include "webrtc/p2p/base/transport.h"
 #include "webrtc/p2p/base/transportchannelproxy.h"
 #include "webrtc/p2p/base/transportinfo.h"
-#include "webrtc/libjingle/xmpp/constants.h"
-#include "webrtc/libjingle/xmpp/jid.h"
 #include "webrtc/base/bind.h"
 #include "webrtc/base/common.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/scoped_ptr.h"
+#include "webrtc/base/stringencode.h"
 #include "webrtc/base/sslstreamadapter.h"
 
 #include "webrtc/p2p/base/constants.h"
@@ -31,14 +29,6 @@
 
 using rtc::Bind;
 
-bool BadMessage(const buzz::QName type,
-                const std::string& text,
-                MessageError* err) {
-  err->SetType(type);
-  err->SetText(text);
-  return false;
-}
-
 TransportProxy::~TransportProxy() {
   for (ChannelMap::iterator iter = channels_.begin();
        iter != channels_.end(); ++iter) {
@@ -325,37 +315,37 @@
 
 std::string BaseSession::StateToString(State state) {
   switch (state) {
-    case Session::STATE_INIT:
+    case BaseSession::STATE_INIT:
       return "STATE_INIT";
-    case Session::STATE_SENTINITIATE:
+    case BaseSession::STATE_SENTINITIATE:
       return "STATE_SENTINITIATE";
-    case Session::STATE_RECEIVEDINITIATE:
+    case BaseSession::STATE_RECEIVEDINITIATE:
       return "STATE_RECEIVEDINITIATE";
-    case Session::STATE_SENTPRACCEPT:
+    case BaseSession::STATE_SENTPRACCEPT:
       return "STATE_SENTPRACCEPT";
-    case Session::STATE_SENTACCEPT:
+    case BaseSession::STATE_SENTACCEPT:
       return "STATE_SENTACCEPT";
-    case Session::STATE_RECEIVEDPRACCEPT:
+    case BaseSession::STATE_RECEIVEDPRACCEPT:
       return "STATE_RECEIVEDPRACCEPT";
-    case Session::STATE_RECEIVEDACCEPT:
+    case BaseSession::STATE_RECEIVEDACCEPT:
       return "STATE_RECEIVEDACCEPT";
-    case Session::STATE_SENTMODIFY:
+    case BaseSession::STATE_SENTMODIFY:
       return "STATE_SENTMODIFY";
-    case Session::STATE_RECEIVEDMODIFY:
+    case BaseSession::STATE_RECEIVEDMODIFY:
       return "STATE_RECEIVEDMODIFY";
-    case Session::STATE_SENTREJECT:
+    case BaseSession::STATE_SENTREJECT:
       return "STATE_SENTREJECT";
-    case Session::STATE_RECEIVEDREJECT:
+    case BaseSession::STATE_RECEIVEDREJECT:
       return "STATE_RECEIVEDREJECT";
-    case Session::STATE_SENTREDIRECT:
+    case BaseSession::STATE_SENTREDIRECT:
       return "STATE_SENTREDIRECT";
-    case Session::STATE_SENTTERMINATE:
+    case BaseSession::STATE_SENTTERMINATE:
       return "STATE_SENTTERMINATE";
-    case Session::STATE_RECEIVEDTERMINATE:
+    case BaseSession::STATE_RECEIVEDTERMINATE:
       return "STATE_RECEIVEDTERMINATE";
-    case Session::STATE_INPROGRESS:
+    case BaseSession::STATE_INPROGRESS:
       return "STATE_INPROGRESS";
-    case Session::STATE_DEINIT:
+    case BaseSession::STATE_DEINIT:
       return "STATE_DEINIT";
     default:
       break;
@@ -547,8 +537,6 @@
       this, &BaseSession::OnTransportWritable);
   transport->SignalRequestSignaling.connect(
       this, &BaseSession::OnTransportRequestSignaling);
-  transport->SignalTransportError.connect(
-      this, &BaseSession::OnTransportSendError);
   transport->SignalRouteChange.connect(
       this, &BaseSession::OnTransportRouteChange);
   transport->SignalCandidatesAllocationDone.connect(
@@ -920,846 +908,4 @@
   }
 }
 
-Session::Session(SessionManager* session_manager,
-                 const std::string& local_name,
-                 const std::string& initiator_name,
-                 const std::string& sid,
-                 const std::string& content_type,
-                 SessionClient* client)
-    : BaseSession(session_manager->signaling_thread(),
-                  session_manager->worker_thread(),
-                  session_manager->port_allocator(),
-                  sid, content_type, initiator_name == local_name) {
-  ASSERT(client != NULL);
-  session_manager_ = session_manager;
-  local_name_ = local_name;
-  initiator_name_ = initiator_name;
-  transport_parser_ = new P2PTransportParser();
-  client_ = client;
-  initiate_acked_ = false;
-  current_protocol_ = PROTOCOL_HYBRID;
-}
-
-Session::~Session() {
-  delete transport_parser_;
-}
-
-bool Session::Initiate(const std::string& to,
-                       const SessionDescription* sdesc) {
-  ASSERT(signaling_thread()->IsCurrent());
-  SessionError error;
-
-  // Only from STATE_INIT
-  if (state() != STATE_INIT)
-    return false;
-
-  // Setup for signaling.
-  set_remote_name(to);
-  set_local_description(sdesc);
-  if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()),
-                              &error)) {
-    LOG(LS_ERROR) << "Could not create transports: " << error.text;
-    return false;
-  }
-
-  if (!SendInitiateMessage(sdesc, &error)) {
-    LOG(LS_ERROR) << "Could not send initiate message: " << error.text;
-    return false;
-  }
-
-  // We need to connect transport proxy and impl here so that we can process
-  // the TransportDescriptions.
-  SpeculativelyConnectAllTransportChannels();
-
-  PushdownTransportDescription(CS_LOCAL, CA_OFFER, NULL);
-  SetState(Session::STATE_SENTINITIATE);
-  return true;
-}
-
-bool Session::Accept(const SessionDescription* sdesc) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  // Only if just received initiate
-  if (state() != STATE_RECEIVEDINITIATE)
-    return false;
-
-  // Setup for signaling.
-  set_local_description(sdesc);
-
-  SessionError error;
-  if (!SendAcceptMessage(sdesc, &error)) {
-    LOG(LS_ERROR) << "Could not send accept message: " << error.text;
-    return false;
-  }
-  // TODO(juberti): Add BUNDLE support to transport-info messages.
-  PushdownTransportDescription(CS_LOCAL, CA_ANSWER, NULL);
-  MaybeEnableMuxingSupport();  // Enable transport channel mux if supported.
-  SetState(Session::STATE_SENTACCEPT);
-  return true;
-}
-
-bool Session::Reject(const std::string& reason) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  // Reject is sent in response to an initiate or modify, to reject the
-  // request
-  if (state() != STATE_RECEIVEDINITIATE && state() != STATE_RECEIVEDMODIFY)
-    return false;
-
-  SessionError error;
-  if (!SendRejectMessage(reason, &error)) {
-    LOG(LS_ERROR) << "Could not send reject message: " << error.text;
-    return false;
-  }
-
-  SetState(STATE_SENTREJECT);
-  return true;
-}
-
-bool Session::TerminateWithReason(const std::string& reason) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  // Either side can terminate, at any time.
-  switch (state()) {
-    case STATE_SENTTERMINATE:
-    case STATE_RECEIVEDTERMINATE:
-      return false;
-
-    case STATE_SENTREJECT:
-    case STATE_RECEIVEDREJECT:
-      // We don't need to send terminate if we sent or received a reject...
-      // it's implicit.
-      break;
-
-    default:
-      SessionError error;
-      if (!SendTerminateMessage(reason, &error)) {
-        LOG(LS_ERROR) << "Could not send terminate message: " << error.text;
-        return false;
-      }
-      break;
-  }
-
-  SetState(STATE_SENTTERMINATE);
-  return true;
-}
-
-bool Session::SendInfoMessage(const XmlElements& elems,
-                              const std::string& remote_name) {
-  ASSERT(signaling_thread()->IsCurrent());
-  SessionError error;
-  if (!SendMessage(ACTION_SESSION_INFO, elems, remote_name, &error)) {
-    LOG(LS_ERROR) << "Could not send info message " << error.text;
-    return false;
-  }
-  return true;
-}
-
-bool Session::SendDescriptionInfoMessage(const ContentInfos& contents) {
-  XmlElements elems;
-  WriteError write_error;
-  if (!WriteDescriptionInfo(current_protocol_,
-                            contents,
-                            GetContentParsers(),
-                            &elems, &write_error)) {
-    LOG(LS_ERROR) << "Could not write description info message: "
-                  << write_error.text;
-    return false;
-  }
-  SessionError error;
-  if (!SendMessage(ACTION_DESCRIPTION_INFO, elems, &error)) {
-    LOG(LS_ERROR) << "Could not send description info message: "
-                  << error.text;
-    return false;
-  }
-  return true;
-}
-
-TransportInfos Session::GetEmptyTransportInfos(
-    const ContentInfos& contents) const {
-  TransportInfos tinfos;
-  for (ContentInfos::const_iterator content = contents.begin();
-       content != contents.end(); ++content) {
-    tinfos.push_back(TransportInfo(content->name,
-                                   TransportDescription(transport_type(),
-                                                        std::string(),
-                                                        std::string())));
-  }
-  return tinfos;
-}
-
-bool Session::OnRemoteCandidates(
-    const TransportInfos& tinfos, ParseError* error) {
-  for (TransportInfos::const_iterator tinfo = tinfos.begin();
-       tinfo != tinfos.end(); ++tinfo) {
-    std::string str_error;
-    if (!BaseSession::OnRemoteCandidates(
-        tinfo->content_name, tinfo->description.candidates, &str_error)) {
-      return BadParse(str_error, error);
-    }
-  }
-  return true;
-}
-
-bool Session::CreateTransportProxies(const TransportInfos& tinfos,
-                                     SessionError* error) {
-  for (TransportInfos::const_iterator tinfo = tinfos.begin();
-       tinfo != tinfos.end(); ++tinfo) {
-    if (tinfo->description.transport_type != transport_type()) {
-      error->SetText("No supported transport in offer.");
-      return false;
-    }
-
-    GetOrCreateTransportProxy(tinfo->content_name);
-  }
-  return true;
-}
-
-TransportParserMap Session::GetTransportParsers() {
-  TransportParserMap parsers;
-  parsers[transport_type()] = transport_parser_;
-  return parsers;
-}
-
-CandidateTranslatorMap Session::GetCandidateTranslators() {
-  CandidateTranslatorMap translators;
-  // NOTE: This technique makes it impossible to parse G-ICE
-  // candidates in session-initiate messages because the channels
-  // aren't yet created at that point.  Since we don't use candidates
-  // in session-initiate messages, we should be OK.  Once we switch to
-  // ICE, this translation shouldn't be necessary.
-  for (TransportMap::const_iterator iter = transport_proxies().begin();
-       iter != transport_proxies().end(); ++iter) {
-    translators[iter->first] = iter->second;
-  }
-  return translators;
-}
-
-ContentParserMap Session::GetContentParsers() {
-  ContentParserMap parsers;
-  parsers[content_type()] = client_;
-  // We need to be able parse both RTP-based and SCTP-based Jingle
-  // with the same client.
-  if (content_type() == NS_JINGLE_RTP) {
-    parsers[NS_JINGLE_DRAFT_SCTP] = client_;
-  }
-  return parsers;
-}
-
-void Session::OnTransportRequestSignaling(Transport* transport) {
-  ASSERT(signaling_thread()->IsCurrent());
-  TransportProxy* transproxy = GetTransportProxy(transport);
-  ASSERT(transproxy != NULL);
-  if (transproxy) {
-    // Reset candidate allocation status for the transport proxy.
-    transproxy->set_candidates_allocated(false);
-  }
-  SignalRequestSignaling(this);
-}
-
-void Session::OnTransportConnecting(Transport* transport) {
-  // This is an indication that we should begin watching the writability
-  // state of the transport.
-  OnTransportWritable(transport);
-}
-
-void Session::OnTransportWritable(Transport* transport) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  // If the transport is not writable, start a timer to make sure that it
-  // becomes writable within a reasonable amount of time.  If it does not, we
-  // terminate since we can't actually send data.  If the transport is writable,
-  // cancel the timer.  Note that writability transitions may occur repeatedly
-  // during the lifetime of the session.
-  signaling_thread()->Clear(this, MSG_TIMEOUT);
-  if (transport->HasChannels() && !transport->writable()) {
-    signaling_thread()->PostDelayed(
-        session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT);
-  }
-}
-
-void Session::OnTransportProxyCandidatesReady(TransportProxy* transproxy,
-                                              const Candidates& candidates) {
-  ASSERT(signaling_thread()->IsCurrent());
-  if (transproxy != NULL) {
-    if (initiator() && !initiate_acked_) {
-      // TODO: This is to work around server re-ordering
-      // messages.  We send the candidates once the session-initiate
-      // is acked.  Once we have fixed the server to guarantee message
-      // order, we can remove this case.
-      transproxy->AddUnsentCandidates(candidates);
-    } else {
-      if (!transproxy->negotiated()) {
-        transproxy->AddSentCandidates(candidates);
-      }
-      SessionError error;
-      if (!SendTransportInfoMessage(transproxy, candidates, &error)) {
-        LOG(LS_ERROR) << "Could not send transport info message: "
-                      << error.text;
-        return;
-      }
-    }
-  }
-}
-
-void Session::OnTransportSendError(Transport* transport,
-                                   const buzz::XmlElement* stanza,
-                                   const buzz::QName& name,
-                                   const std::string& type,
-                                   const std::string& text,
-                                   const buzz::XmlElement* extra_info) {
-  ASSERT(signaling_thread()->IsCurrent());
-  SignalErrorMessage(this, stanza, name, type, text, extra_info);
-}
-
-void Session::OnIncomingMessage(const SessionMessage& msg) {
-  ASSERT(signaling_thread()->IsCurrent());
-  ASSERT(state() == STATE_INIT || msg.from == remote_name());
-
-  if (current_protocol_== PROTOCOL_HYBRID) {
-    if (msg.protocol == PROTOCOL_GINGLE) {
-      current_protocol_ = PROTOCOL_GINGLE;
-    } else {
-      current_protocol_ = PROTOCOL_JINGLE;
-    }
-  }
-
-  bool valid = false;
-  MessageError error;
-  switch (msg.type) {
-    case ACTION_SESSION_INITIATE:
-      valid = OnInitiateMessage(msg, &error);
-      break;
-    case ACTION_SESSION_INFO:
-      valid = OnInfoMessage(msg);
-      break;
-    case ACTION_SESSION_ACCEPT:
-      valid = OnAcceptMessage(msg, &error);
-      break;
-    case ACTION_SESSION_REJECT:
-      valid = OnRejectMessage(msg, &error);
-      break;
-    case ACTION_SESSION_TERMINATE:
-      valid = OnTerminateMessage(msg, &error);
-      break;
-    case ACTION_TRANSPORT_INFO:
-      valid = OnTransportInfoMessage(msg, &error);
-      break;
-    case ACTION_TRANSPORT_ACCEPT:
-      valid = OnTransportAcceptMessage(msg, &error);
-      break;
-    case ACTION_DESCRIPTION_INFO:
-      valid = OnDescriptionInfoMessage(msg, &error);
-      break;
-    default:
-      valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST,
-                         "unknown session message type",
-                         &error);
-  }
-
-  if (valid) {
-    SendAcknowledgementMessage(msg.stanza);
-  } else {
-    SignalErrorMessage(this, msg.stanza, error.type,
-                       "modify", error.text, NULL);
-  }
-}
-
-void Session::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
-                                 const buzz::XmlElement* response_stanza,
-                                 const SessionMessage& msg) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  if (msg.type == ACTION_SESSION_INITIATE) {
-    OnInitiateAcked();
-  }
-}
-
-void Session::OnInitiateAcked() {
-  // TODO: This is to work around server re-ordering
-  // messages.  We send the candidates once the session-initiate
-  // is acked.  Once we have fixed the server to guarantee message
-  // order, we can remove this case.
-  if (!initiate_acked_) {
-    initiate_acked_ = true;
-    SessionError error;
-    SendAllUnsentTransportInfoMessages(&error);
-  }
-}
-
-void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
-                           const buzz::XmlElement* error_stanza) {
-  ASSERT(signaling_thread()->IsCurrent());
-
-  SessionMessage msg;
-  ParseError parse_error;
-  if (!ParseSessionMessage(orig_stanza, &msg, &parse_error)) {
-    LOG(LS_ERROR) << "Error parsing failed send: " << parse_error.text
-                  << ":" << orig_stanza;
-    return;
-  }
-
-  // If the error is a session redirect, call OnRedirectError, which will
-  // continue the session with a new remote JID.
-  SessionRedirect redirect;
-  if (FindSessionRedirect(error_stanza, &redirect)) {
-    SessionError error;
-    if (!OnRedirectError(redirect, &error)) {
-      // TODO: Should we send a message back?  The standard
-      // says nothing about it.
-      std::ostringstream desc;
-      desc << "Failed to redirect: " << error.text;
-      LOG(LS_ERROR) << desc.str();
-      SetError(ERROR_RESPONSE, desc.str());
-    }
-    return;
-  }
-
-  std::string error_type = "cancel";
-
-  const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
-  if (error) {
-    error_type = error->Attr(buzz::QN_TYPE);
-
-    LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n"
-                  << "in response to:\n" << orig_stanza->Str();
-  } else {
-    // don't crash if <error> is missing
-    LOG(LS_ERROR) << "Session error without <error/> element, ignoring";
-    return;
-  }
-
-  if (msg.type == ACTION_TRANSPORT_INFO) {
-    // Transport messages frequently generate errors because they are sent right
-    // when we detect a network failure.  For that reason, we ignore such
-    // errors, because if we do not establish writability again, we will
-    // terminate anyway.  The exceptions are transport-specific error tags,
-    // which we pass on to the respective transport.
-  } else if ((error_type != "continue") && (error_type != "wait")) {
-    // We do not set an error if the other side said it is okay to continue
-    // (possibly after waiting).  These errors can be ignored.
-    SetError(ERROR_RESPONSE, "");
-  }
-}
-
-bool Session::OnInitiateMessage(const SessionMessage& msg,
-                                MessageError* error) {
-  if (!CheckState(STATE_INIT, error))
-    return false;
-
-  SessionInitiate init;
-  if (!ParseSessionInitiate(msg.protocol, msg.action_elem,
-                            GetContentParsers(), GetTransportParsers(),
-                            GetCandidateTranslators(),
-                            &init, error))
-    return false;
-
-  SessionError session_error;
-  if (!CreateTransportProxies(init.transports, &session_error)) {
-    return BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE,
-                      session_error.text, error);
-  }
-
-  set_remote_name(msg.from);
-  set_initiator_name(msg.initiator);
-  set_remote_description(new SessionDescription(init.ClearContents(),
-                                                init.transports,
-                                                init.groups));
-  // Updating transport with TransportDescription.
-  PushdownTransportDescription(CS_REMOTE, CA_OFFER, NULL);
-  SetState(STATE_RECEIVEDINITIATE);
-
-  // Users of Session may listen to state change and call Reject().
-  if (state() != STATE_SENTREJECT) {
-    if (!OnRemoteCandidates(init.transports, error))
-      return false;
-
-    // TODO(juberti): Auto-generate and push down the local transport answer.
-    // This is necessary for trickling to work with RFC 5245 ICE.
-  }
-  return true;
-}
-
-bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
-  if (!CheckState(STATE_SENTINITIATE, error))
-    return false;
-
-  SessionAccept accept;
-  if (!ParseSessionAccept(msg.protocol, msg.action_elem,
-                          GetContentParsers(), GetTransportParsers(),
-                          GetCandidateTranslators(),
-                          &accept, error)) {
-    return false;
-  }
-
-  // If we get an accept, we can assume the initiate has been
-  // received, even if we haven't gotten an IQ response.
-  OnInitiateAcked();
-
-  set_remote_description(new SessionDescription(accept.ClearContents(),
-                                                accept.transports,
-                                                accept.groups));
-  // Updating transport with TransportDescription.
-  PushdownTransportDescription(CS_REMOTE, CA_ANSWER, NULL);
-  MaybeEnableMuxingSupport();  // Enable transport channel mux if supported.
-  SetState(STATE_RECEIVEDACCEPT);
-
-  if (!OnRemoteCandidates(accept.transports, error))
-    return false;
-
-  return true;
-}
-
-bool Session::OnRejectMessage(const SessionMessage& msg, MessageError* error) {
-  if (!CheckState(STATE_SENTINITIATE, error))
-    return false;
-
-  SetState(STATE_RECEIVEDREJECT);
-  return true;
-}
-
-bool Session::OnInfoMessage(const SessionMessage& msg) {
-  SignalInfoMessage(this, msg.action_elem);
-  return true;
-}
-
-bool Session::OnTerminateMessage(const SessionMessage& msg,
-                                 MessageError* error) {
-  SessionTerminate term;
-  if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error))
-    return false;
-
-  SignalReceivedTerminateReason(this, term.reason);
-  if (term.debug_reason != buzz::STR_EMPTY) {
-    LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason;
-  }
-
-  SetState(STATE_RECEIVEDTERMINATE);
-  return true;
-}
-
-bool Session::OnTransportInfoMessage(const SessionMessage& msg,
-                                     MessageError* error) {
-  TransportInfos tinfos;
-  if (!ParseTransportInfos(msg.protocol, msg.action_elem,
-                           initiator_description()->contents(),
-                           GetTransportParsers(), GetCandidateTranslators(),
-                           &tinfos, error))
-    return false;
-
-  if (!OnRemoteCandidates(tinfos, error))
-    return false;
-
-  return true;
-}
-
-bool Session::OnTransportAcceptMessage(const SessionMessage& msg,
-                                       MessageError* error) {
-  // TODO: Currently here only for compatibility with
-  // Gingle 1.1 clients (notably, Google Voice).
-  return true;
-}
-
-bool Session::OnDescriptionInfoMessage(const SessionMessage& msg,
-                              MessageError* error) {
-  if (!CheckState(STATE_INPROGRESS, error))
-    return false;
-
-  DescriptionInfo description_info;
-  if (!ParseDescriptionInfo(msg.protocol, msg.action_elem,
-                            GetContentParsers(), GetTransportParsers(),
-                            GetCandidateTranslators(),
-                            &description_info, error)) {
-    return false;
-  }
-
-  ContentInfos& updated_contents = description_info.contents;
-
-  // TODO: Currently, reflector sends back
-  // video stream updates even for an audio-only call, which causes
-  // this to fail.  Put this back once reflector is fixed.
-  //
-  // ContentInfos::iterator it;
-  // First, ensure all updates are valid before modifying remote_description_.
-  // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
-  //   if (remote_description()->GetContentByName(it->name) == NULL) {
-  //     return false;
-  //   }
-  // }
-
-  // TODO: We used to replace contents from an update, but
-  // that no longer works with partial updates.  We need to figure out
-  // a way to merge patial updates into contents.  For now, users of
-  // Session should listen to SignalRemoteDescriptionUpdate and handle
-  // updates.  They should not expect remote_description to be the
-  // latest value.
-  //
-  // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
-  //     remote_description()->RemoveContentByName(it->name);
-  //     remote_description()->AddContent(it->name, it->type, it->description);
-  //   }
-  // }
-
-  SignalRemoteDescriptionUpdate(this, updated_contents);
-  return true;
-}
-
-bool BareJidsEqual(const std::string& name1,
-                   const std::string& name2) {
-  buzz::Jid jid1(name1);
-  buzz::Jid jid2(name2);
-
-  return jid1.IsValid() && jid2.IsValid() && jid1.BareEquals(jid2);
-}
-
-bool Session::OnRedirectError(const SessionRedirect& redirect,
-                              SessionError* error) {
-  MessageError message_error;
-  if (!CheckState(STATE_SENTINITIATE, &message_error)) {
-    return BadWrite(message_error.text, error);
-  }
-
-  if (!BareJidsEqual(remote_name(), redirect.target))
-    return BadWrite("Redirection not allowed: must be the same bare jid.",
-                    error);
-
-  // When we receive a redirect, we point the session at the new JID
-  // and resend the candidates.
-  set_remote_name(redirect.target);
-  return (SendInitiateMessage(local_description(), error) &&
-          ResendAllTransportInfoMessages(error));
-}
-
-bool Session::CheckState(State expected, MessageError* error) {
-  if (state() != expected) {
-    // The server can deliver messages out of order/repeated for various
-    // reasons. For example, if the server does not recive our iq response,
-    // it could assume that the iq it sent was lost, and will then send
-    // it again. Ideally, we should implement reliable messaging with
-    // duplicate elimination.
-    return BadMessage(buzz::QN_STANZA_NOT_ALLOWED,
-                      "message not allowed in current state",
-                      error);
-  }
-  return true;
-}
-
-void Session::SetError(Error error, const std::string& error_desc) {
-  BaseSession::SetError(error, error_desc);
-  if (error != ERROR_NONE)
-    signaling_thread()->Post(this, MSG_ERROR);
-}
-
-void Session::OnMessage(rtc::Message* pmsg) {
-  // preserve this because BaseSession::OnMessage may modify it
-  State orig_state = state();
-
-  BaseSession::OnMessage(pmsg);
-
-  switch (pmsg->message_id) {
-  case MSG_ERROR:
-    TerminateWithReason(STR_TERMINATE_ERROR);
-    break;
-
-  case MSG_STATE:
-    switch (orig_state) {
-    case STATE_SENTREJECT:
-    case STATE_RECEIVEDREJECT:
-      // Assume clean termination.
-      Terminate();
-      break;
-
-    case STATE_SENTTERMINATE:
-    case STATE_RECEIVEDTERMINATE:
-      session_manager_->DestroySession(this);
-      break;
-
-    default:
-      // Explicitly ignoring some states here.
-      break;
-    }
-    break;
-  }
-}
-
-bool Session::SendInitiateMessage(const SessionDescription* sdesc,
-                                  SessionError* error) {
-  SessionInitiate init;
-  init.contents = sdesc->contents();
-  init.transports = GetEmptyTransportInfos(init.contents);
-  init.groups = sdesc->groups();
-  return SendMessage(ACTION_SESSION_INITIATE, init, error);
-}
-
-bool Session::WriteSessionAction(
-    SignalingProtocol protocol, const SessionInitiate& init,
-    XmlElements* elems, WriteError* error) {
-  return WriteSessionInitiate(protocol, init.contents, init.transports,
-                              GetContentParsers(), GetTransportParsers(),
-                              GetCandidateTranslators(), init.groups,
-                              elems, error);
-}
-
-bool Session::SendAcceptMessage(const SessionDescription* sdesc,
-                                SessionError* error) {
-  XmlElements elems;
-  if (!WriteSessionAccept(current_protocol_,
-                          sdesc->contents(),
-                          GetEmptyTransportInfos(sdesc->contents()),
-                          GetContentParsers(), GetTransportParsers(),
-                          GetCandidateTranslators(), sdesc->groups(),
-                          &elems, error)) {
-    return false;
-  }
-  return SendMessage(ACTION_SESSION_ACCEPT, elems, error);
-}
-
-bool Session::SendRejectMessage(const std::string& reason,
-                                SessionError* error) {
-  SessionTerminate term(reason);
-  return SendMessage(ACTION_SESSION_REJECT, term, error);
-}
-
-bool Session::SendTerminateMessage(const std::string& reason,
-                                   SessionError* error) {
-  SessionTerminate term(reason);
-  return SendMessage(ACTION_SESSION_TERMINATE, term, error);
-}
-
-bool Session::WriteSessionAction(SignalingProtocol protocol,
-                                 const SessionTerminate& term,
-                                 XmlElements* elems, WriteError* error) {
-  WriteSessionTerminate(protocol, term, elems);
-  return true;
-}
-
-bool Session::SendTransportInfoMessage(const TransportInfo& tinfo,
-                                       SessionError* error) {
-  return SendMessage(ACTION_TRANSPORT_INFO, tinfo, error);
-}
-
-bool Session::SendTransportInfoMessage(const TransportProxy* transproxy,
-                                       const Candidates& candidates,
-                                       SessionError* error) {
-  return SendTransportInfoMessage(TransportInfo(transproxy->content_name(),
-      TransportDescription(transproxy->type(), std::vector<std::string>(),
-                           std::string(), std::string(), ICEMODE_FULL,
-                           CONNECTIONROLE_NONE, NULL, candidates)), error);
-}
-
-bool Session::WriteSessionAction(SignalingProtocol protocol,
-                                 const TransportInfo& tinfo,
-                                 XmlElements* elems, WriteError* error) {
-  TransportInfos tinfos;
-  tinfos.push_back(tinfo);
-  return WriteTransportInfos(protocol, tinfos,
-                             GetTransportParsers(), GetCandidateTranslators(),
-                             elems, error);
-}
-
-bool Session::ResendAllTransportInfoMessages(SessionError* error) {
-  for (TransportMap::const_iterator iter = transport_proxies().begin();
-       iter != transport_proxies().end(); ++iter) {
-    TransportProxy* transproxy = iter->second;
-    if (transproxy->sent_candidates().size() > 0) {
-      if (!SendTransportInfoMessage(
-              transproxy, transproxy->sent_candidates(), error)) {
-        LOG(LS_ERROR) << "Could not resend transport info messages: "
-                      << error->text;
-        return false;
-      }
-      transproxy->ClearSentCandidates();
-    }
-  }
-  return true;
-}
-
-bool Session::SendAllUnsentTransportInfoMessages(SessionError* error) {
-  for (TransportMap::const_iterator iter = transport_proxies().begin();
-       iter != transport_proxies().end(); ++iter) {
-    TransportProxy* transproxy = iter->second;
-    if (transproxy->unsent_candidates().size() > 0) {
-      if (!SendTransportInfoMessage(
-              transproxy, transproxy->unsent_candidates(), error)) {
-        LOG(LS_ERROR) << "Could not send unsent transport info messages: "
-                      << error->text;
-        return false;
-      }
-      transproxy->ClearUnsentCandidates();
-    }
-  }
-  return true;
-}
-
-bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
-                          SessionError* error) {
-    return SendMessage(type, action_elems, remote_name(), error);
-}
-
-bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
-                          const std::string& remote_name, SessionError* error) {
-  rtc::scoped_ptr<buzz::XmlElement> stanza(
-      new buzz::XmlElement(buzz::QN_IQ));
-
-  SessionMessage msg(current_protocol_, type, id(), initiator_name());
-  msg.to = remote_name;
-  WriteSessionMessage(msg, action_elems, stanza.get());
-
-  SignalOutgoingMessage(this, stanza.get());
-  return true;
-}
-
-template <typename Action>
-bool Session::SendMessage(ActionType type, const Action& action,
-                          SessionError* error) {
-  rtc::scoped_ptr<buzz::XmlElement> stanza(
-      new buzz::XmlElement(buzz::QN_IQ));
-  if (!WriteActionMessage(type, action, stanza.get(), error))
-    return false;
-
-  SignalOutgoingMessage(this, stanza.get());
-  return true;
-}
-
-template <typename Action>
-bool Session::WriteActionMessage(ActionType type, const Action& action,
-                                 buzz::XmlElement* stanza,
-                                 WriteError* error) {
-  if (current_protocol_ == PROTOCOL_HYBRID) {
-    if (!WriteActionMessage(PROTOCOL_JINGLE, type, action, stanza, error))
-      return false;
-    if (!WriteActionMessage(PROTOCOL_GINGLE, type, action, stanza, error))
-      return false;
-  } else {
-    if (!WriteActionMessage(current_protocol_, type, action, stanza, error))
-      return false;
-  }
-  return true;
-}
-
-template <typename Action>
-bool Session::WriteActionMessage(SignalingProtocol protocol,
-                                 ActionType type, const Action& action,
-                                 buzz::XmlElement* stanza, WriteError* error) {
-  XmlElements action_elems;
-  if (!WriteSessionAction(protocol, action, &action_elems, error))
-    return false;
-
-  SessionMessage msg(protocol, type, id(), initiator_name());
-  msg.to = remote_name();
-
-  WriteSessionMessage(msg, action_elems, stanza);
-  return true;
-}
-
-void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) {
-  rtc::scoped_ptr<buzz::XmlElement> ack(
-      new buzz::XmlElement(buzz::QN_IQ));
-  ack->SetAttr(buzz::QN_TO, remote_name());
-  ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
-  ack->SetAttr(buzz::QN_TYPE, "result");
-
-  SignalOutgoingMessage(this, ack.get());
-}
-
 }  // namespace cricket
diff --git a/webrtc/p2p/base/session.h b/webrtc/p2p/base/session.h
index f5eaf41..fc09810 100644
--- a/webrtc/p2p/base/session.h
+++ b/webrtc/p2p/base/session.h
@@ -16,14 +16,9 @@
 #include <string>
 #include <vector>
 
-#include "webrtc/p2p/base/parsing.h"
+#include "webrtc/p2p/base/candidate.h"
 #include "webrtc/p2p/base/port.h"
-#include "webrtc/p2p/base/sessionclient.h"
-#include "webrtc/p2p/base/sessionmanager.h"
-#include "webrtc/p2p/base/sessionmessages.h"
 #include "webrtc/p2p/base/transport.h"
-#include "webrtc/libjingle/xmllite/xmlelement.h"
-#include "webrtc/libjingle/xmpp/constants.h"
 #include "webrtc/base/refcount.h"
 #include "webrtc/base/scoped_ptr.h"
 #include "webrtc/base/scoped_ref_ptr.h"
@@ -41,27 +36,6 @@
 typedef rtc::RefCountedObject<rtc::scoped_ptr<Transport> >
 TransportWrapper;
 
-// Used for errors that will send back a specific error message to the
-// remote peer.  We add "type" to the errors because it's needed for
-// SignalErrorMessage.
-struct MessageError : ParseError {
-  buzz::QName type;
-
-  // if unset, assume type is a parse error
-  MessageError() : ParseError(), type(buzz::QN_STANZA_BAD_REQUEST) {}
-
-  void SetType(const buzz::QName type) {
-    this->type = type;
-  }
-};
-
-// Used for errors that may be returned by public session methods that
-// can fail.
-// TODO: Use this error in Session::Initiate and
-// Session::Accept.
-struct SessionError : WriteError {
-};
-
 // Bundles a Transport and ChannelMap together. ChannelMap is used to
 // create transport channels before receiving or sending a session
 // initiate, and for speculatively connecting channels.  Previously, a
@@ -418,16 +392,6 @@
                                                const Candidates& candidates) {
   }
 
-  // Called when a transport signals that it found an error in an incoming
-  // message.
-  virtual void OnTransportSendError(Transport* transport,
-                                    const buzz::XmlElement* stanza,
-                                    const buzz::QName& name,
-                                    const std::string& type,
-                                    const std::string& text,
-                                    const buzz::XmlElement* extra_info) {
-  }
-
   virtual void OnTransportRouteChange(
       Transport* transport,
       int component,
@@ -504,227 +468,6 @@
   TransportMap transports_;
 };
 
-// A specific Session created by the SessionManager, using XMPP for protocol.
-class Session : public BaseSession {
- public:
-  // Returns the manager that created and owns this session.
-  SessionManager* session_manager() const { return session_manager_; }
-
-  // Returns the client that is handling the application data of this session.
-  SessionClient* client() const { return client_; }
-
-    // Returns the JID of this client.
-  const std::string& local_name() const { return local_name_; }
-
-  // Returns the JID of the other peer in this session.
-  const std::string& remote_name() const { return remote_name_; }
-
-  // Set the JID of the other peer in this session.
-  // Typically the remote_name_ is set when the session is initiated.
-  // However, sometimes (e.g when a proxy is used) the peer name is
-  // known after the BaseSession has been initiated and it must be updated
-  // explicitly.
-  void set_remote_name(const std::string& name) { remote_name_ = name; }
-
-  // Set the JID of the initiator of this session. Allows for the overriding
-  // of the initiator to be a third-party, eg. the MUC JID when creating p2p
-  // sessions.
-  void set_initiator_name(const std::string& name) { initiator_name_ = name; }
-
-  // Indicates the JID of the entity who initiated this session.
-  // In special cases, may be different than both local_name and remote_name.
-  const std::string& initiator_name() const { return initiator_name_; }
-
-  SignalingProtocol current_protocol() const { return current_protocol_; }
-
-  void set_current_protocol(SignalingProtocol protocol) {
-    current_protocol_ = protocol;
-  }
-
-  // Updates the error state, signaling if necessary.
-  virtual void SetError(Error error, const std::string& error_desc);
-
-  // When the session needs to send signaling messages, it beings by requesting
-  // signaling.  The client should handle this by calling OnSignalingReady once
-  // it is ready to send the messages.
-  // (These are called only by SessionManager.)
-  sigslot::signal1<Session*> SignalRequestSignaling;
-  void OnSignalingReady() { BaseSession::OnSignalingReady(); }
-
-  // Takes ownership of session description.
-  // TODO: Add an error argument to pass back to the caller.
-  bool Initiate(const std::string& to,
-                const SessionDescription* sdesc);
-
-  // When we receive an initiate, we create a session in the
-  // RECEIVEDINITIATE state and respond by accepting or rejecting.
-  // Takes ownership of session description.
-  // TODO: Add an error argument to pass back to the caller.
-  bool Accept(const SessionDescription* sdesc);
-  bool Reject(const std::string& reason);
-  bool Terminate() {
-    return TerminateWithReason(STR_TERMINATE_SUCCESS);
-  }
-  bool TerminateWithReason(const std::string& reason);
-  // Fired whenever we receive a terminate message along with a reason
-  sigslot::signal2<Session*, const std::string&> SignalReceivedTerminateReason;
-
-  // The two clients in the session may also send one another
-  // arbitrary XML messages, which are called "info" messages. Sending
-  // takes ownership of the given elements.  The signal does not; the
-  // parent element will be deleted after the signal.
-  bool SendInfoMessage(const XmlElements& elems,
-                       const std::string& remote_name);
-  bool SendDescriptionInfoMessage(const ContentInfos& contents);
-  sigslot::signal2<Session*, const buzz::XmlElement*> SignalInfoMessage;
-
- private:
-  // Creates or destroys a session.  (These are called only SessionManager.)
-  Session(SessionManager *session_manager,
-          const std::string& local_name, const std::string& initiator_name,
-          const std::string& sid, const std::string& content_type,
-          SessionClient* client);
-  ~Session();
-  // For each transport info, create a transport proxy.  Can fail for
-  // incompatible transport types.
-  bool CreateTransportProxies(const TransportInfos& tinfos,
-                              SessionError* error);
-  bool OnRemoteCandidates(const TransportInfos& tinfos,
-                          ParseError* error);
-  // Returns a TransportInfo without candidates for each content name.
-  // Uses the transport_type_ of the session.
-  TransportInfos GetEmptyTransportInfos(const ContentInfos& contents) const;
-
-    // Maps passed to serialization functions.
-  TransportParserMap GetTransportParsers();
-  ContentParserMap GetContentParsers();
-  CandidateTranslatorMap GetCandidateTranslators();
-
-  virtual void OnTransportRequestSignaling(Transport* transport);
-  virtual void OnTransportConnecting(Transport* transport);
-  virtual void OnTransportWritable(Transport* transport);
-  virtual void OnTransportProxyCandidatesReady(TransportProxy* proxy,
-                                               const Candidates& candidates);
-  virtual void OnTransportSendError(Transport* transport,
-                                    const buzz::XmlElement* stanza,
-                                    const buzz::QName& name,
-                                    const std::string& type,
-                                    const std::string& text,
-                                    const buzz::XmlElement* extra_info);
-  virtual void OnMessage(rtc::Message *pmsg);
-
-  // Send various kinds of session messages.
-  bool SendInitiateMessage(const SessionDescription* sdesc,
-                           SessionError* error);
-  bool SendAcceptMessage(const SessionDescription* sdesc, SessionError* error);
-  bool SendRejectMessage(const std::string& reason, SessionError* error);
-  bool SendTerminateMessage(const std::string& reason, SessionError* error);
-  bool SendTransportInfoMessage(const TransportInfo& tinfo,
-                                SessionError* error);
-  bool SendTransportInfoMessage(const TransportProxy* transproxy,
-                                const Candidates& candidates,
-                                SessionError* error);
-
-  bool ResendAllTransportInfoMessages(SessionError* error);
-  bool SendAllUnsentTransportInfoMessages(SessionError* error);
-
-  // All versions of SendMessage send a message of the given type to
-  // the other client.  Can pass either a set of elements or an
-  // "action", which must have a WriteSessionAction method to go along
-  // with it.  Sending with an action supports sending a "hybrid"
-  // message.  Sending with elements must be sent as Jingle or Gingle.
-
-  // When passing elems, must be either Jingle or Gingle protocol.
-  // Takes ownership of action_elems.
-  bool SendMessage(ActionType type, const XmlElements& action_elems,
-                   SessionError* error);
-  // Sends a messge, but overrides the remote name.
-  bool SendMessage(ActionType type, const XmlElements& action_elems,
-                   const std::string& remote_name,
-                   SessionError* error);
-  // When passing an action, may be Hybrid protocol.
-  template <typename Action>
-  bool SendMessage(ActionType type, const Action& action,
-                   SessionError* error);
-
-  // Helper methods to write the session message stanza.
-  template <typename Action>
-  bool WriteActionMessage(ActionType type, const Action& action,
-                          buzz::XmlElement* stanza, WriteError* error);
-  template <typename Action>
-  bool WriteActionMessage(SignalingProtocol protocol,
-                          ActionType type, const Action& action,
-                          buzz::XmlElement* stanza, WriteError* error);
-
-  // Sending messages in hybrid form requires being able to write them
-  // on a per-protocol basis with a common method signature, which all
-  // of these have.
-  bool WriteSessionAction(SignalingProtocol protocol,
-                          const SessionInitiate& init,
-                          XmlElements* elems, WriteError* error);
-  bool WriteSessionAction(SignalingProtocol protocol,
-                          const TransportInfo& tinfo,
-                          XmlElements* elems, WriteError* error);
-  bool WriteSessionAction(SignalingProtocol protocol,
-                          const SessionTerminate& term,
-                          XmlElements* elems, WriteError* error);
-
-  // Sends a message back to the other client indicating that we have received
-  // and accepted their message.
-  void SendAcknowledgementMessage(const buzz::XmlElement* stanza);
-
-  // Once signaling is ready, the session will use this signal to request the
-  // sending of each message.  When messages are received by the other client,
-  // they should be handed to OnIncomingMessage.
-  // (These are called only by SessionManager.)
-  sigslot::signal2<Session* , const buzz::XmlElement*> SignalOutgoingMessage;
-  void OnIncomingMessage(const SessionMessage& msg);
-
-  void OnIncomingResponse(const buzz::XmlElement* orig_stanza,
-                          const buzz::XmlElement* response_stanza,
-                          const SessionMessage& msg);
-  void OnInitiateAcked();
-  void OnFailedSend(const buzz::XmlElement* orig_stanza,
-                    const buzz::XmlElement* error_stanza);
-
-  // Invoked when an error is found in an incoming message.  This is translated
-  // into the appropriate XMPP response by SessionManager.
-  sigslot::signal6<BaseSession*,
-                   const buzz::XmlElement*,
-                   const buzz::QName&,
-                   const std::string&,
-                   const std::string&,
-                   const buzz::XmlElement*> SignalErrorMessage;
-
-  // Handlers for the various types of messages.  These functions may take
-  // pointers to the whole stanza or to just the session element.
-  bool OnInitiateMessage(const SessionMessage& msg, MessageError* error);
-  bool OnAcceptMessage(const SessionMessage& msg, MessageError* error);
-  bool OnRejectMessage(const SessionMessage& msg, MessageError* error);
-  bool OnInfoMessage(const SessionMessage& msg);
-  bool OnTerminateMessage(const SessionMessage& msg, MessageError* error);
-  bool OnTransportInfoMessage(const SessionMessage& msg, MessageError* error);
-  bool OnTransportAcceptMessage(const SessionMessage& msg, MessageError* error);
-  bool OnDescriptionInfoMessage(const SessionMessage& msg, MessageError* error);
-  bool OnRedirectError(const SessionRedirect& redirect, SessionError* error);
-
-  // Verifies that we are in the appropriate state to receive this message.
-  bool CheckState(State state, MessageError* error);
-
-  SessionManager* session_manager_;
-  bool initiate_acked_;
-  std::string local_name_;
-  std::string initiator_name_;
-  std::string remote_name_;
-  SessionClient* client_;
-  TransportParser* transport_parser_;
-  // Keeps track of what protocol we are speaking.
-  SignalingProtocol current_protocol_;
-
-  friend class SessionManager;  // For access to constructor, destructor,
-                                // and signaling related methods.
-};
-
 }  // namespace cricket
 
 #endif  // WEBRTC_P2P_BASE_SESSION_H_
diff --git a/webrtc/p2p/base/session_unittest.cc b/webrtc/p2p/base/session_unittest.cc
index d6f94b2..fdd0bdc 100644
--- a/webrtc/p2p/base/session_unittest.cc
+++ b/webrtc/p2p/base/session_unittest.cc
@@ -14,22 +14,6 @@
 #include <map>
 #include <sstream>
 
-#include "webrtc/p2p/base/basicpacketsocketfactory.h"
-#include "webrtc/p2p/base/constants.h"
-#include "webrtc/p2p/base/p2ptransport.h"
-#include "webrtc/p2p/base/parsing.h"
-#include "webrtc/p2p/base/portallocator.h"
-#include "webrtc/p2p/base/relayport.h"
-#include "webrtc/p2p/base/relayserver.h"
-#include "webrtc/p2p/base/session.h"
-#include "webrtc/p2p/base/sessionclient.h"
-#include "webrtc/p2p/base/sessionmanager.h"
-#include "webrtc/p2p/base/stunport.h"
-#include "webrtc/p2p/base/stunserver.h"
-#include "webrtc/p2p/base/transportchannel.h"
-#include "webrtc/p2p/base/transportchannelproxy.h"
-#include "webrtc/p2p/base/udpport.h"
-#include "webrtc/libjingle/xmpp/constants.h"
 #include "webrtc/base/base64.h"
 #include "webrtc/base/common.h"
 #include "webrtc/base/gunit.h"
@@ -38,6 +22,22 @@
 #include "webrtc/base/natserver.h"
 #include "webrtc/base/natsocketfactory.h"
 #include "webrtc/base/stringencode.h"
+#include "webrtc/p2p/base/basicpacketsocketfactory.h"
+#include "webrtc/p2p/base/constants.h"
+#include "webrtc/p2p/base/p2ptransport.h"
+#include "webrtc/p2p/base/parsing.h"
+#include "webrtc/p2p/base/portallocator.h"
+#include "webrtc/p2p/base/relayport.h"
+#include "webrtc/p2p/base/relayserver.h"
+#include "webrtc/p2p/base/sessionclient.h"
+#include "webrtc/p2p/base/sessionmanager.h"
+#include "webrtc/p2p/base/stunport.h"
+#include "webrtc/p2p/base/stunserver.h"
+#include "webrtc/p2p/base/transportchannel.h"
+#include "webrtc/p2p/base/transportchannelproxy.h"
+#include "webrtc/p2p/base/udpport.h"
+#include "webrtc/libjingle/session/session.h"
+#include "webrtc/libjingle/xmpp/constants.h"
 
 using cricket::SignalingProtocol;
 using cricket::PROTOCOL_HYBRID;
diff --git a/webrtc/p2p/base/sessionmanager.cc b/webrtc/p2p/base/sessionmanager.cc
index f375dea..816c613 100644
--- a/webrtc/p2p/base/sessionmanager.cc
+++ b/webrtc/p2p/base/sessionmanager.cc
@@ -11,8 +11,8 @@
 #include "webrtc/p2p/base/sessionmanager.h"
 
 #include "webrtc/p2p/base/constants.h"
-#include "webrtc/p2p/base/session.h"
 #include "webrtc/p2p/base/sessionmessages.h"
+#include "webrtc/libjingle/session/session.h"
 #include "webrtc/libjingle/xmpp/constants.h"
 #include "webrtc/libjingle/xmpp/jid.h"
 #include "webrtc/base/common.h"
diff --git a/webrtc/p2p/base/sessionmessages.h b/webrtc/p2p/base/sessionmessages.h
index 7b156d4..3437a9a 100644
--- a/webrtc/p2p/base/sessionmessages.h
+++ b/webrtc/p2p/base/sessionmessages.h
@@ -15,9 +15,11 @@
 #include <string>
 #include <vector>
 
+#include "webrtc/p2p/base/candidate.h"
 #include "webrtc/p2p/base/constants.h"
 #include "webrtc/p2p/base/parsing.h"
 #include "webrtc/p2p/base/sessiondescription.h"  // Needed to delete contents.
+#include "webrtc/p2p/base/transport.h"
 #include "webrtc/p2p/base/transportinfo.h"
 #include "webrtc/libjingle/xmllite/xmlelement.h"
 #include "webrtc/base/basictypes.h"
@@ -125,17 +127,6 @@
   std::string target;
 };
 
-// Used during parsing and writing to map component to channel name
-// and back.  This is primarily for converting old G-ICE candidate
-// signalling to new ICE candidate classes.
-class CandidateTranslator {
- public:
-  virtual bool GetChannelNameFromComponent(
-      int component, std::string* channel_name) const = 0;
-  virtual bool GetComponentFromChannelName(
-      const std::string& channel_name, int* component) const = 0;
-};
-
 // Content name => translator
 typedef std::map<std::string, CandidateTranslator*> CandidateTranslatorMap;
 
diff --git a/webrtc/p2p/base/transport.h b/webrtc/p2p/base/transport.h
index 1091cb0..5fe445c 100644
--- a/webrtc/p2p/base/transport.h
+++ b/webrtc/p2p/base/transport.h
@@ -56,8 +56,6 @@
 struct WriteError;
 class CandidateTranslator;
 class PortAllocator;
-class SessionManager;
-class Session;
 class TransportChannel;
 class TransportChannelImpl;
 
diff --git a/webrtc/p2p/p2p.gyp b/webrtc/p2p/p2p.gyp
index 102e75b..ae02d65 100644
--- a/webrtc/p2p/p2p.gyp
+++ b/webrtc/p2p/p2p.gyp
@@ -108,6 +108,8 @@
         'client/sessionsendtask.h',
         'client/socketmonitor.cc',
         'client/socketmonitor.h',
+        '<(webrtc_root)/libjingle/session/session.cc',
+        '<(webrtc_root)/libjingle/session/session.h',
       ],
       'direct_dependent_settings': {
         'cflags_cc!': [