summaryrefslogtreecommitdiffstats
path: root/remoting/protocol/jingle_session.cc
diff options
context:
space:
mode:
authorgarykac@chromium.org <garykac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 21:56:42 +0000
committergarykac@chromium.org <garykac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-03 21:56:42 +0000
commit230d2fd2e1cafaab5cd5e4d2a9f64b4ae272550a (patch)
tree8aa02e4a85f0d314a4419a434037e163a41981c8 /remoting/protocol/jingle_session.cc
parent3296839602c5c54cae0b0fb0a9d6623a5ba65895 (diff)
downloadchromium_src-230d2fd2e1cafaab5cd5e4d2a9f64b4ae272550a.zip
chromium_src-230d2fd2e1cafaab5cd5e4d2a9f64b4ae272550a.tar.gz
chromium_src-230d2fd2e1cafaab5cd5e4d2a9f64b4ae272550a.tar.bz2
Rename classes for Chromoting:
ChromotocolServer -> protocol::SessionManager ChromotocolConnection -> protocol::Session BUG=none TEST=compiles + make chromoting connection Review URL: http://codereview.chromium.org/4313001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64971 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/protocol/jingle_session.cc')
-rw-r--r--remoting/protocol/jingle_session.cc343
1 files changed, 343 insertions, 0 deletions
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
new file mode 100644
index 0000000..4ed6b4f
--- /dev/null
+++ b/remoting/protocol/jingle_session.cc
@@ -0,0 +1,343 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/protocol/jingle_session.h"
+
+#include "base/message_loop.h"
+#include "net/base/net_errors.h"
+#include "remoting/base/constants.h"
+#include "remoting/jingle_glue/channel_socket_adapter.h"
+#include "remoting/jingle_glue/jingle_thread.h"
+#include "remoting/jingle_glue/stream_socket_adapter.h"
+#include "remoting/protocol/jingle_session_manager.h"
+#include "third_party/libjingle/source/talk/base/thread.h"
+#include "third_party/libjingle/source/talk/p2p/base/session.h"
+#include "third_party/libjingle/source/talk/session/tunnel/pseudotcpchannel.h"
+
+using cricket::BaseSession;
+using cricket::PseudoTcpChannel;
+
+namespace remoting {
+
+namespace protocol {
+
+namespace {
+const char kControlChannelName[] = "control";
+const char kEventChannelName[] = "event";
+const char kVideoChannelName[] = "video";
+const char kVideoRtpChannelName[] = "videortp";
+const char kVideoRtcpChannelName[] = "videortcp";
+} // namespace
+
+const char JingleSession::kChromotingContentName[] = "chromoting";
+
+JingleSession::JingleSession(
+ JingleSessionManager* jingle_session_manager)
+ : jingle_session_manager_(jingle_session_manager),
+ state_(INITIALIZING),
+ closed_(false),
+ cricket_session_(NULL),
+ event_channel_(NULL),
+ video_channel_(NULL) {
+}
+
+JingleSession::~JingleSession() {
+ DCHECK(closed_);
+}
+
+void JingleSession::Init(cricket::Session* cricket_session) {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+
+ cricket_session_ = cricket_session;
+ jid_ = cricket_session_->remote_name();
+ cricket_session_->SignalState.connect(
+ this, &JingleSession::OnSessionState);
+}
+
+bool JingleSession::HasSession(cricket::Session* cricket_session) {
+ return cricket_session_ == cricket_session;
+}
+
+cricket::Session* JingleSession::ReleaseSession() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+
+ SetState(CLOSED);
+ cricket::Session* session = cricket_session_;
+ if (cricket_session_)
+ cricket_session_->SignalState.disconnect(this);
+ cricket_session_ = NULL;
+ closed_ = true;
+ return session;
+}
+
+void JingleSession::SetStateChangeCallback(
+ StateChangeCallback* callback) {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ DCHECK(callback);
+ state_change_callback_.reset(callback);
+}
+
+net::Socket* JingleSession::control_channel() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ return control_channel_adapter_.get();
+}
+
+net::Socket* JingleSession::event_channel() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ return event_channel_adapter_.get();
+}
+
+// TODO(sergeyu): Remove this method after we switch to RTP.
+net::Socket* JingleSession::video_channel() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ return video_channel_adapter_.get();
+}
+
+net::Socket* JingleSession::video_rtp_channel() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ return video_rtp_channel_.get();
+}
+
+net::Socket* JingleSession::video_rtcp_channel() {
+ DCHECK_EQ(jingle_session_manager_->message_loop(), MessageLoop::current());
+ return video_rtcp_channel_.get();
+}
+
+const std::string& JingleSession::jid() {
+ // No synchronization is needed because jid_ is not changed
+ // after new connection is passed to JingleChromotocolServer callback.
+ return jid_;
+}
+
+MessageLoop* JingleSession::message_loop() {
+ return jingle_session_manager_->message_loop();
+}
+
+const CandidateChromotocolConfig*
+JingleSession::candidate_config() {
+ DCHECK(candidate_config_.get());
+ return candidate_config_.get();
+}
+
+void JingleSession::set_candidate_config(
+ const CandidateChromotocolConfig* candidate_config) {
+ DCHECK(!candidate_config_.get());
+ DCHECK(candidate_config);
+ candidate_config_.reset(candidate_config);
+}
+
+const ChromotocolConfig* JingleSession::config() {
+ DCHECK(config_.get());
+ return config_.get();
+}
+
+void JingleSession::set_config(const ChromotocolConfig* config) {
+ DCHECK(!config_.get());
+ DCHECK(config);
+ config_.reset(config);
+}
+
+void JingleSession::Close(Task* closed_task) {
+ if (MessageLoop::current() != jingle_session_manager_->message_loop()) {
+ jingle_session_manager_->message_loop()->PostTask(
+ FROM_HERE, NewRunnableMethod(this, &JingleSession::Close,
+ closed_task));
+ return;
+ }
+
+ if (!closed_) {
+ if (control_channel_adapter_.get())
+ control_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
+
+ if (control_channel_) {
+ control_channel_->OnSessionTerminate(cricket_session_);
+ control_channel_ = NULL;
+ }
+
+ if (event_channel_adapter_.get())
+ event_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
+
+ if (event_channel_) {
+ event_channel_->OnSessionTerminate(cricket_session_);
+ event_channel_ = NULL;
+ }
+
+ if (video_channel_adapter_.get())
+ video_channel_adapter_->Close(net::ERR_CONNECTION_CLOSED);
+
+ if (video_channel_) {
+ video_channel_->OnSessionTerminate(cricket_session_);
+ video_channel_ = NULL;
+ }
+
+ if (video_rtp_channel_.get())
+ video_rtp_channel_->Close(net::ERR_CONNECTION_CLOSED);
+ if (video_rtcp_channel_.get())
+ video_rtcp_channel_->Close(net::ERR_CONNECTION_CLOSED);
+
+ if (cricket_session_)
+ cricket_session_->Terminate();
+
+ SetState(CLOSED);
+
+ closed_ = true;
+ }
+
+ closed_task->Run();
+ delete closed_task;
+}
+
+void JingleSession::OnSessionState(
+ BaseSession* session, BaseSession::State state) {
+ DCHECK_EQ(cricket_session_, session);
+
+ switch (state) {
+ case cricket::Session::STATE_SENTINITIATE:
+ case cricket::Session::STATE_RECEIVEDINITIATE:
+ OnInitiate();
+ break;
+
+ case cricket::Session::STATE_SENTACCEPT:
+ case cricket::Session::STATE_RECEIVEDACCEPT:
+ OnAccept();
+ break;
+
+ case cricket::Session::STATE_SENTTERMINATE:
+ case cricket::Session::STATE_RECEIVEDTERMINATE:
+ case cricket::Session::STATE_SENTREJECT:
+ case cricket::Session::STATE_RECEIVEDREJECT:
+ OnTerminate();
+ break;
+
+ case cricket::Session::STATE_DEINIT:
+ // Close() must have been called before this.
+ NOTREACHED();
+ break;
+
+ default:
+ // We don't care about other steates.
+ break;
+ }
+}
+
+void JingleSession::OnInitiate() {
+ jid_ = cricket_session_->remote_name();
+
+ std::string content_name;
+ // If we initiate the session, we get to specify the content name. When
+ // accepting one, the remote end specifies it.
+ if (cricket_session_->initiator()) {
+ content_name = kChromotingContentName;
+ } else {
+ const cricket::ContentInfo* content;
+ content = cricket_session_->remote_description()->FirstContentByType(
+ kChromotingXmlNamespace);
+ CHECK(content);
+ content_name = content->name;
+ }
+
+ // Create video RTP channels.
+ video_rtp_channel_.reset(new TransportChannelSocketAdapter(
+ cricket_session_->CreateChannel(content_name, kVideoRtpChannelName)));
+ video_rtcp_channel_.reset(new TransportChannelSocketAdapter(
+ cricket_session_->CreateChannel(content_name, kVideoRtcpChannelName)));
+
+ // Create control channel.
+ control_channel_ = new PseudoTcpChannel(
+ jingle_session_manager_->jingle_thread(), cricket_session_);
+ control_channel_->Connect(content_name, kControlChannelName);
+ control_channel_adapter_.reset(new StreamSocketAdapter(
+ control_channel_->GetStream()));
+
+ // Create event channel.
+ event_channel_ = new PseudoTcpChannel(
+ jingle_session_manager_->jingle_thread(), cricket_session_);
+ event_channel_->Connect(content_name, kEventChannelName);
+ event_channel_adapter_.reset(new StreamSocketAdapter(
+ event_channel_->GetStream()));
+
+ // Create video channel.
+ // TODO(sergeyu): Remove video channel when we are ready to switch to RTP.
+ video_channel_ = new PseudoTcpChannel(
+ jingle_session_manager_->jingle_thread(), cricket_session_);
+ video_channel_->Connect(content_name, kVideoChannelName);
+ video_channel_adapter_.reset(new StreamSocketAdapter(
+ video_channel_->GetStream()));
+
+ if (!cricket_session_->initiator())
+ jingle_session_manager_->AcceptConnection(this, cricket_session_);
+
+ SetState(CONNECTING);
+}
+
+void JingleSession::OnAccept() {
+ // Set the config if we are the one who initiated the session.
+ if (cricket_session_->initiator()) {
+ const cricket::ContentInfo* content =
+ cricket_session_->remote_description()->FirstContentByType(
+ kChromotingXmlNamespace);
+ CHECK(content);
+
+ const protocol::ContentDescription* content_description =
+ static_cast<const protocol::ContentDescription*>(content->description);
+ ChromotocolConfig* config = content_description->config()->GetFinalConfig();
+
+ // Terminate the session if the config we received is invalid.
+ if (!config || !candidate_config()->IsSupported(config)) {
+ // TODO(sergeyu): Inform the user that the host is misbehaving?
+ LOG(ERROR) << "Terminating outgoing session after an "
+ "invalid session description has been received.";
+ cricket_session_->Terminate();
+ return;
+ }
+
+ set_config(config);
+ }
+
+ SetState(CONNECTED);
+}
+
+void JingleSession::OnTerminate() {
+ if (control_channel_adapter_.get())
+ control_channel_adapter_->Close(net::ERR_CONNECTION_ABORTED);
+ if (control_channel_) {
+ control_channel_->OnSessionTerminate(cricket_session_);
+ control_channel_ = NULL;
+ }
+
+ if (event_channel_adapter_.get())
+ event_channel_adapter_->Close(net::ERR_CONNECTION_ABORTED);
+ if (event_channel_) {
+ event_channel_->OnSessionTerminate(cricket_session_);
+ event_channel_ = NULL;
+ }
+
+ if (video_channel_adapter_.get())
+ video_channel_adapter_->Close(net::ERR_CONNECTION_ABORTED);
+ if (video_channel_) {
+ video_channel_->OnSessionTerminate(cricket_session_);
+ video_channel_ = NULL;
+ }
+
+ if (video_rtp_channel_.get())
+ video_rtp_channel_->Close(net::ERR_CONNECTION_ABORTED);
+ if (video_rtcp_channel_.get())
+ video_rtcp_channel_->Close(net::ERR_CONNECTION_ABORTED);
+
+ SetState(CLOSED);
+
+ closed_ = true;
+}
+
+void JingleSession::SetState(State new_state) {
+ if (new_state != state_) {
+ state_ = new_state;
+ if (!closed_ && state_change_callback_.get())
+ state_change_callback_->Run(new_state);
+ }
+}
+
+} // namespace protocol
+
+} // namespace remoting