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!': [