summaryrefslogtreecommitdiffstats
path: root/remoting/protocol
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-15 18:10:55 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-15 18:10:55 +0000
commitf09abf28fd801c956267db53c5f3b069501bd428 (patch)
tree2317fbfa46169fa82330067b39175ff2e9aa412f /remoting/protocol
parentb7ca15e0d73295f77d0877b766d3283b51eced20 (diff)
downloadchromium_src-f09abf28fd801c956267db53c5f3b069501bd428.zip
chromium_src-f09abf28fd801c956267db53c5f3b069501bd428.tar.gz
chromium_src-f09abf28fd801c956267db53c5f3b069501bd428.tar.bz2
Move channel initialization logic to JingleChannel class.
Added new CreateChannel() method in Session interface. The new method can be used to create arbitrary channels. BUG=None TEST=Unittests Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=92641 Review URL: http://codereview.chromium.org/7326024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92712 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/protocol')
-rw-r--r--remoting/protocol/fake_session.cc12
-rw-r--r--remoting/protocol/fake_session.h5
-rw-r--r--remoting/protocol/jingle_channel_connector.h44
-rw-r--r--remoting/protocol/jingle_datagram_connector.cc49
-rw-r--r--remoting/protocol/jingle_datagram_connector.h52
-rw-r--r--remoting/protocol/jingle_session.cc398
-rw-r--r--remoting/protocol/jingle_session.h144
-rw-r--r--remoting/protocol/jingle_stream_connector.cc188
-rw-r--r--remoting/protocol/jingle_stream_connector.h85
-rw-r--r--remoting/protocol/protocol_mock_objects.h4
-rw-r--r--remoting/protocol/session.h30
11 files changed, 667 insertions, 344 deletions
diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc
index c11fa34..2403a20 100644
--- a/remoting/protocol/fake_session.cc
+++ b/remoting/protocol/fake_session.cc
@@ -140,6 +140,18 @@ void FakeSession::SetStateChangeCallback(
callback_.reset(callback);
}
+void FakeSession::CreateStreamChannel(
+ const std::string& name, const StreamChannelCallback& callback) {
+ NOTIMPLEMENTED();
+ callback.Run(name, NULL);
+}
+
+void FakeSession::CreateDatagramChannel(
+ const std::string& name, const DatagramChannelCallback& callback) {
+ NOTIMPLEMENTED();
+ callback.Run(name, NULL);
+}
+
FakeSocket* FakeSession::control_channel() {
return &control_channel_;
}
diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h
index 1427bf3..d892ede 100644
--- a/remoting/protocol/fake_session.h
+++ b/remoting/protocol/fake_session.h
@@ -105,6 +105,11 @@ class FakeSession : public Session {
virtual void SetStateChangeCallback(StateChangeCallback* callback);
+ virtual void CreateStreamChannel(
+ const std::string& name, const StreamChannelCallback& callback);
+ virtual void CreateDatagramChannel(
+ const std::string& name, const DatagramChannelCallback& callback);
+
virtual FakeSocket* control_channel();
virtual FakeSocket* event_channel();
virtual FakeSocket* video_channel();
diff --git a/remoting/protocol/jingle_channel_connector.h b/remoting/protocol/jingle_channel_connector.h
new file mode 100644
index 0000000..6037ee4
--- /dev/null
+++ b/remoting/protocol/jingle_channel_connector.h
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 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.
+
+#ifndef REMOTING_PROTOCOL_JINGLE_CHANNEL_CONNECTOR_H_
+#define REMOTING_PROTOCOL_JINGLE_CHANNEL_CONNECTOR_H_
+
+#include "base/basictypes.h"
+#include "base/threading/non_thread_safe.h"
+
+namespace cricket {
+class TransportChannel;
+} // namespace cricket
+
+namespace crypto {
+class RSAPrivateKey;
+} // namespace crypto
+
+namespace net {
+class X509Certificate;
+} // namespace net
+
+namespace remoting {
+namespace protocol {
+
+class JingleChannelConnector : public base::NonThreadSafe {
+ public:
+ JingleChannelConnector() { }
+ virtual ~JingleChannelConnector() { }
+
+ virtual void Connect(bool initiator,
+ net::X509Certificate* local_cert,
+ net::X509Certificate* remote_cert,
+ crypto::RSAPrivateKey* local_private_key,
+ cricket::TransportChannel* raw_channel) = 0;
+
+ protected:
+ DISALLOW_COPY_AND_ASSIGN(JingleChannelConnector);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_JINGLE_CHANNEL_CONNECTOR_H_
diff --git a/remoting/protocol/jingle_datagram_connector.cc b/remoting/protocol/jingle_datagram_connector.cc
new file mode 100644
index 0000000..ff717a0
--- /dev/null
+++ b/remoting/protocol/jingle_datagram_connector.cc
@@ -0,0 +1,49 @@
+// Copyright (c) 2011 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_datagram_connector.h"
+
+#include "jingle/glue/channel_socket_adapter.h"
+#include "remoting/protocol/jingle_session.h"
+#include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
+
+namespace remoting {
+namespace protocol {
+
+JingleDatagramConnector::JingleDatagramConnector(
+ JingleSession* session,
+ const std::string& name,
+ const Session::DatagramChannelCallback& callback)
+ : session_(session),
+ name_(name),
+ callback_(callback) {
+}
+
+JingleDatagramConnector::~JingleDatagramConnector() {
+}
+
+void JingleDatagramConnector::Connect(
+ bool initiator,
+ net::X509Certificate* local_cert,
+ net::X509Certificate* remote_cert,
+ crypto::RSAPrivateKey* local_private_key,
+ cricket::TransportChannel* raw_channel) {
+ DCHECK(CalledOnValidThread());
+
+ if (!initiator) {
+ // Don't make outgoing connections from the host to client.
+ raw_channel->GetP2PChannel()->set_incoming_only(true);
+ }
+
+ net::Socket* socket =
+ new jingle_glue::TransportChannelSocketAdapter(raw_channel);
+
+ // TODO(sergeyu): Implement encryption for datagram channels.
+
+ callback_.Run(name_, socket);
+ session_->OnChannelConnectorFinished(name_, this);
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/jingle_datagram_connector.h b/remoting/protocol/jingle_datagram_connector.h
new file mode 100644
index 0000000..f6b79d7
--- /dev/null
+++ b/remoting/protocol/jingle_datagram_connector.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2011 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.
+
+#ifndef REMOTING_PROTOCOL_JINGLE_DATAGRAM_CONNECTOR_H_
+#define REMOTING_PROTOCOL_JINGLE_DATAGRAM_CONNECTOR_H_
+
+#include "net/base/completion_callback.h"
+#include "remoting/protocol/jingle_channel_connector.h"
+#include "remoting/protocol/session.h"
+
+namespace cricket {
+class TransportChannel;
+} // namespace cricket
+
+namespace jingle_glue {
+class TransportChannelSocketAdapter;
+} // namespace jingle_glue
+
+namespace remoting {
+namespace protocol {
+
+class JingleSession;
+
+class JingleDatagramConnector : public JingleChannelConnector {
+ public:
+ JingleDatagramConnector(JingleSession* session,
+ const std::string& name,
+ const Session::DatagramChannelCallback& callback);
+ virtual ~JingleDatagramConnector();
+
+ // Starts connection process for the channel. |local_private_key| is
+ // owned by the caller, and must exist until this object is
+ // destroyed.
+ virtual void Connect(bool initiator,
+ net::X509Certificate* local_cert,
+ net::X509Certificate* remote_cert,
+ crypto::RSAPrivateKey* local_private_key,
+ cricket::TransportChannel* raw_channel) OVERRIDE;
+
+ private:
+ JingleSession* session_;
+ std::string name_;
+ Session::DatagramChannelCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(JingleDatagramConnector);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_JINGLE_DATAGRAM_CONNECTOR_H_
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index ad417ef..f7d61f1 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -4,26 +4,21 @@
#include "remoting/protocol/jingle_session.h"
+#include "base/bind.h"
#include "base/message_loop.h"
#include "base/rand_util.h"
+#include "base/stl_util-inl.h"
#include "crypto/hmac.h"
#include "crypto/rsa_private_key.h"
-#include "jingle/glue/channel_socket_adapter.h"
-#include "jingle/glue/pseudotcp_adapter.h"
-#include "net/base/cert_status_flags.h"
-#include "net/base/cert_verifier.h"
-#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
-#include "net/base/ssl_config_service.h"
-#include "net/base/x509_certificate.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/ssl_server_socket.h"
+#include "net/socket/stream_socket.h"
#include "remoting/base/constants.h"
+#include "remoting/protocol/jingle_datagram_connector.h"
#include "remoting/protocol/jingle_session_manager.h"
+#include "remoting/protocol/jingle_stream_connector.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/p2p/base/p2ptransportchannel.h"
+#include "third_party/libjingle/source/talk/p2p/base/transport.h"
using cricket::BaseSession;
@@ -44,34 +39,6 @@ const char kVideoRtcpChannelName[] = "videortcp";
const int kMasterKeyLength = 16;
const int kChannelKeyLength = 16;
-// Value is choosen to balance the extra latency against the reduced
-// load due to ACK traffic.
-const int kTcpAckDelayMilliseconds = 10;
-
-// Helper method to create a SSL client socket.
-net::SSLClientSocket* CreateSSLClientSocket(
- net::StreamSocket* socket, scoped_refptr<net::X509Certificate> cert,
- net::CertVerifier* cert_verifier) {
- net::SSLConfig ssl_config;
- ssl_config.cached_info_enabled = false;
- ssl_config.false_start_enabled = false;
- ssl_config.ssl3_enabled = true;
- ssl_config.tls1_enabled = true;
-
- // Certificate provided by the host doesn't need authority.
- net::SSLConfig::CertAndStatus cert_and_status;
- cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
- cert_and_status.cert = cert;
- ssl_config.allowed_bad_certs.push_back(cert_and_status);
-
- // SSLClientSocket takes ownership of the adapter.
- net::HostPortPair host_and_pair(JingleSession::kChromotingContentName, 0);
- net::SSLClientSocket* ssl_socket =
- net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
- socket, host_and_pair, ssl_config, NULL, cert_verifier);
- return ssl_socket;
-}
-
std::string GenerateRandomMasterKey() {
std::string result;
result.resize(kMasterKeyLength);
@@ -142,10 +109,6 @@ JingleSession::JingleSession(
closed_(false),
closing_(false),
cricket_session_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(connect_callback_(
- this, &JingleSession::OnConnect)),
- ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_(
- this, &JingleSession::OnSSLConnect)),
ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) {
// TODO(hclam): Need a better way to clone a key.
if (local_private_key) {
@@ -169,7 +132,6 @@ void JingleSession::Init(cricket::Session* cricket_session) {
cricket_session_ = cricket_session;
jid_ = cricket_session_->remote_name();
- cert_verifier_.reset(new net::CertVerifier());
cricket_session_->SignalState.connect(
this, &JingleSession::OnSessionState);
cricket_session_->SignalError.connect(
@@ -194,18 +156,13 @@ void JingleSession::CloseInternal(int result, bool failed) {
else
SetState(CLOSED);
- // Now tear down the remoting channel resources.
- control_channel_.reset();
- control_socket_.reset();
- control_ssl_socket_.reset();
- event_channel_.reset();
- event_socket_.reset();
- event_ssl_socket_.reset();
- video_channel_.reset();
- video_socket_.reset();
- video_ssl_socket_.reset();
- video_rtp_channel_.reset();
- video_rtcp_channel_.reset();
+ control_channel_socket_.reset();
+ event_channel_socket_.reset();
+ video_channel_socket_.reset();
+ video_rtp_channel_socket_.reset();
+ video_rtcp_channel_socket_.reset();
+ STLDeleteContainerPairSecondPointers(channel_connectors_.begin(),
+ channel_connectors_.end());
// Tear down the cricket session, including the cricket transport channels.
if (cricket_session_) {
@@ -215,7 +172,6 @@ void JingleSession::CloseInternal(int result, bool failed) {
closed_ = true;
}
- cert_verifier_.reset();
}
bool JingleSession::HasSession(cricket::Session* cricket_session) {
@@ -242,30 +198,45 @@ void JingleSession::SetStateChangeCallback(StateChangeCallback* callback) {
state_change_callback_.reset(callback);
}
+void JingleSession::CreateStreamChannel(
+ const std::string& name, const StreamChannelCallback& callback) {
+ DCHECK(CalledOnValidThread());
+
+ AddChannelConnector(
+ name, new JingleStreamConnector(this, name, callback));
+}
+
+void JingleSession::CreateDatagramChannel(
+ const std::string& name, const DatagramChannelCallback& callback) {
+ DCHECK(CalledOnValidThread());
+
+ AddChannelConnector(
+ name, new JingleDatagramConnector(this, name, callback));
+}
+
net::Socket* JingleSession::control_channel() {
DCHECK(CalledOnValidThread());
- return control_ssl_socket_.get();
+ return control_channel_socket_.get();
}
net::Socket* JingleSession::event_channel() {
DCHECK(CalledOnValidThread());
- return event_ssl_socket_.get();
+ return event_channel_socket_.get();
}
-// TODO(sergeyu): Remove this method after we switch to RTP.
net::Socket* JingleSession::video_channel() {
DCHECK(CalledOnValidThread());
- return video_ssl_socket_.get();
+ return video_channel_socket_.get();
}
net::Socket* JingleSession::video_rtp_channel() {
DCHECK(CalledOnValidThread());
- return video_rtp_channel_.get();
+ return video_rtp_channel_socket_.get();
}
net::Socket* JingleSession::video_rtcp_channel() {
DCHECK(CalledOnValidThread());
- return video_rtcp_channel_.get();
+ return video_rtcp_channel_socket_.get();
}
const std::string& JingleSession::jid() {
@@ -390,22 +361,12 @@ void JingleSession::OnInitiate() {
DCHECK(CalledOnValidThread());
jid_ = cricket_session_->remote_name();
- const cricket::SessionDescription* session_description;
- // If we initiate the session, we get to specify the content name. When
- // accepting one, the remote end specifies it.
- if (cricket_session_->initiator()) {
- session_description = cricket_session_->local_description();
- } else {
- session_description = cricket_session_->remote_description();
- }
- const cricket::ContentInfo* content =
- session_description->FirstContentByType(kChromotingXmlNamespace);
- CHECK(content);
- const ContentDescription* content_description =
- static_cast<const ContentDescription*>(content->description);
- std::string content_name = content->name;
-
if (!cricket_session_->initiator()) {
+ const protocol::ContentDescription* content_description =
+ static_cast<const protocol::ContentDescription*>(
+ GetContentInfo()->description);
+ CHECK(content_description);
+
if (!DecryptMasterKey(local_private_key_.get(),
content_description->master_key(), &master_key_)) {
LOG(ERROR) << "Failed to decrypt master-key";
@@ -414,103 +375,23 @@ void JingleSession::OnInitiate() {
}
}
- // Create video RTP channels.
- raw_video_rtp_channel_ =
- cricket_session_->CreateChannel(content_name, kVideoRtpChannelName);
- video_rtp_channel_.reset(
- new jingle_glue::TransportChannelSocketAdapter(raw_video_rtp_channel_));
- raw_video_rtcp_channel_ =
- cricket_session_->CreateChannel(content_name, kVideoRtcpChannelName);
- video_rtcp_channel_.reset(
- new jingle_glue::TransportChannelSocketAdapter(raw_video_rtcp_channel_));
-
- // Create control channel.
- raw_control_channel_ =
- cricket_session_->CreateChannel(content_name, kControlChannelName);
- control_channel_.reset(
- new jingle_glue::TransportChannelSocketAdapter(raw_control_channel_));
-
- // Create event channel.
- raw_event_channel_ =
- cricket_session_->CreateChannel(content_name, kEventChannelName);
- event_channel_.reset(
- new jingle_glue::TransportChannelSocketAdapter(raw_event_channel_));
-
- // Create video channel.
- // TODO(wez): When we have RTP video support, we'll need to negotiate the
- // type of video channel to allocate, for legacy compatibility.
- raw_video_channel_ =
- cricket_session_->CreateChannel(content_name, kVideoChannelName);
- video_channel_.reset(
- new jingle_glue::TransportChannelSocketAdapter(raw_video_channel_));
-
- if (!cricket_session_->initiator()) {
- if (!jingle_session_manager_->AcceptConnection(this, cricket_session_)) {
- Close();
- // Release session so that
- // JingleSessionManager::SessionDestroyed() doesn't try to call
- // cricket::SessionManager::DestroySession() for it.
- ReleaseSession();
- delete this;
- return;
- }
- }
-
- // Set state to CONNECTING if the session is being accepted.
- SetState(CONNECTING);
-}
-
-bool JingleSession::EstablishPseudoTcp(
- net::Socket* channel,
- scoped_ptr<net::StreamSocket>* stream) {
- jingle_glue::PseudoTcpAdapter* adapter =
- new jingle_glue::PseudoTcpAdapter(channel);
- adapter->SetAckDelay(kTcpAckDelayMilliseconds);
- adapter->SetNoDelay(true);
-
- stream->reset(adapter);
- int result = (*stream)->Connect(&connect_callback_);
- return (result == net::OK) || (result == net::ERR_IO_PENDING);
-}
-
-bool JingleSession::EstablishSSLConnection(
- net::StreamSocket* socket,
- scoped_ptr<net::StreamSocket>* ssl_socket) {
- DCHECK(socket);
- DCHECK(socket->IsConnected());
if (cricket_session_->initiator()) {
- // Create client SSL socket.
- net::SSLClientSocket* ssl_client_socket = CreateSSLClientSocket(
- socket, remote_cert_, cert_verifier_.get());
- ssl_socket->reset(ssl_client_socket);
-
- int ret = ssl_client_socket->Connect(&ssl_connect_callback_);
- if (ret == net::ERR_IO_PENDING) {
- return true;
- } else if (ret != net::OK) {
- LOG(ERROR) << "Failed to establish SSL connection";
- cricket_session_->Terminate();
- return false;
- }
+ // Set state to CONNECTING if this is an outgoing message. We need
+ // to post this task because channel creation works only after we
+ // return from this method. This is because
+ // JingleChannelConnector::Connect() needs to call
+ // set_incoming_only() on P2PTransportChannel, but
+ // P2PTransportChannel is created only after we return from this
+ // method.
+ // TODO(sergeyu): Add set_incoming_only() in TransportChannelProxy.
+ MessageLoop::current()->PostTask(
+ FROM_HERE, task_factory_.NewRunnableMethod(
+ &JingleSession::SetState, CONNECTING));
} else {
- // Create server SSL socket.
- net::SSLConfig ssl_config;
- net::SSLServerSocket* ssl_server_socket = net::CreateSSLServerSocket(
- socket, local_cert_, local_private_key_.get(), ssl_config);
- ssl_socket->reset(ssl_server_socket);
-
- int ret = ssl_server_socket->Handshake(&ssl_connect_callback_);
- if (ret == net::ERR_IO_PENDING) {
- return true;
- } else if (ret != net::OK) {
- LOG(ERROR) << "Failed to establish SSL connection";
- cricket_session_->Terminate();
- return false;
- }
+ MessageLoop::current()->PostTask(
+ FROM_HERE, task_factory_.NewRunnableMethod(
+ &JingleSession::AcceptConnection));
}
- // Reach here if net::OK is received.
- ssl_connect_callback_.Run(net::OK);
- return true;
}
bool JingleSession::InitializeConfigFromDescription(
@@ -518,14 +399,13 @@ bool JingleSession::InitializeConfigFromDescription(
// We should only be called after ParseContent has succeeded, in which
// case there will always be a Chromoting session configuration.
const cricket::ContentInfo* content =
- description->FirstContentByType(kChromotingXmlNamespace);
+ description->FirstContentByType(kChromotingXmlNamespace);
CHECK(content);
const protocol::ContentDescription* content_description =
- static_cast<const protocol::ContentDescription*>(content->description);
+ static_cast<const protocol::ContentDescription*>(content->description);
CHECK(content_description);
- remote_cert_ = content_description->certificate();
- if (!remote_cert_) {
+ remote_cert_ = content_description->certificate(); if (!remote_cert_) {
LOG(ERROR) << "Connection response does not specify certificate";
return false;
}
@@ -545,29 +425,6 @@ bool JingleSession::InitializeConfigFromDescription(
return true;
}
-void JingleSession::InitializeChannels() {
- // Disable incoming connections on the host so that we don't traverse
- // the firewall.
- if (!cricket_session_->initiator()) {
- raw_control_channel_->GetP2PChannel()->set_incoming_only(true);
- raw_event_channel_->GetP2PChannel()->set_incoming_only(true);
- raw_video_channel_->GetP2PChannel()->set_incoming_only(true);
- raw_video_rtp_channel_->GetP2PChannel()->set_incoming_only(true);
- raw_video_rtcp_channel_->GetP2PChannel()->set_incoming_only(true);
- }
-
- // Create the Control, Event and Video connections on the channels.
- if (!EstablishPseudoTcp(control_channel_.release(),
- &control_socket_) ||
- !EstablishPseudoTcp(event_channel_.release(),
- &event_socket_) ||
- !EstablishPseudoTcp(video_channel_.release(),
- &video_socket_)) {
- CloseInternal(net::ERR_CONNECTION_FAILED, true);
- return;
- }
-}
-
void JingleSession::OnAccept() {
DCHECK(CalledOnValidThread());
@@ -575,21 +432,13 @@ void JingleSession::OnAccept() {
// host responded with, to refer to later.
if (cricket_session_->initiator()) {
if (!InitializeConfigFromDescription(
- cricket_session_->remote_description())) {
+ cricket_session_->remote_description())) {
CloseInternal(net::ERR_CONNECTION_FAILED, true);
return;
}
}
- // TODO(sergeyu): This is a hack: Currently set_incoming_only()
- // needs to be called on each channel before the channel starts
- // creating candidates but after session is accepted (after
- // TransportChannelProxy::GetP2PChannel() starts returning actual
- // P2P channel). By posting a task here we can call it at the right
- // moment. This problem will go away when we switch to Pepper P2P
- // API.
- MessageLoop::current()->PostTask(FROM_HERE, task_factory_.NewRunnableMethod(
- &JingleSession::InitializeChannels));
+ CreateChannels();
}
void JingleSession::OnTerminate() {
@@ -597,58 +446,113 @@ void JingleSession::OnTerminate() {
CloseInternal(net::ERR_CONNECTION_ABORTED, false);
}
-void JingleSession::OnConnect(int result) {
- DCHECK(CalledOnValidThread());
-
- if (result != net::OK) {
- LOG(ERROR) << "PseudoTCP connection failed: " << result;
- CloseInternal(result, true);
+void JingleSession::AcceptConnection() {
+ if (!jingle_session_manager_->AcceptConnection(this, cricket_session_)) {
+ Close();
+ // Release session so that JingleSessionManager::SessionDestroyed()
+ // doesn't try to call cricket::SessionManager::DestroySession() for it.
+ ReleaseSession();
+ delete this;
return;
}
- if (control_socket_.get() && control_socket_->IsConnected()) {
- if (!EstablishSSLConnection(control_socket_.release(),
- &control_ssl_socket_)) {
- LOG(ERROR) << "Establish control channel failed";
- CloseInternal(net::ERR_CONNECTION_FAILED, true);
- return;
- }
- }
- if (event_socket_.get() && event_socket_->IsConnected()) {
- if (!EstablishSSLConnection(event_socket_.release(),
- &event_ssl_socket_)) {
- LOG(ERROR) << "Establish control event failed";
- CloseInternal(net::ERR_CONNECTION_FAILED, true);
- return;
- }
- }
- if (video_socket_.get() && video_socket_->IsConnected()) {
- if (!EstablishSSLConnection(video_socket_.release(),
- &video_ssl_socket_)) {
- LOG(ERROR) << "Establish control video failed";
- CloseInternal(net::ERR_CONNECTION_FAILED, true);
- return;
- }
- }
+ // Set state to CONNECTING if the session is being accepted.
+ SetState(CONNECTING);
+}
+
+void JingleSession::AddChannelConnector(
+ const std::string& name, JingleChannelConnector* connector) {
+ DCHECK(channel_connectors_.find(name) == channel_connectors_.end());
+
+ const std::string& content_name = GetContentInfo()->name;
+ cricket::TransportChannel* raw_channel =
+ cricket_session_->CreateChannel(content_name, name);
+
+ channel_connectors_[name] = connector;
+ connector->Connect(cricket_session_->initiator(), local_cert_,
+ remote_cert_, local_private_key_.get(), raw_channel);
+
+ // Workaround bug in libjingle - it doesn't connect channels if they
+ // are created after the session is accepted. See crbug.com/89384.
+ // TODO(sergeyu): Fix the bug and remove this line.
+ cricket_session_->GetTransport(content_name)->ConnectChannels();
}
-void JingleSession::OnSSLConnect(int result) {
+void JingleSession::OnChannelConnectorFinished(
+ const std::string& name, JingleChannelConnector* connector) {
DCHECK(CalledOnValidThread());
+ DCHECK_EQ(channel_connectors_[name], connector);
+ channel_connectors_[name] = NULL;
+ delete connector;
+}
+
+void JingleSession::CreateChannels() {
+ StreamChannelCallback stream_callback(
+ base::Bind(&JingleSession::OnStreamChannelConnected,
+ base::Unretained(this)));
+ CreateStreamChannel(kControlChannelName, stream_callback);
+ CreateStreamChannel(kEventChannelName, stream_callback);
+ CreateStreamChannel(kVideoChannelName, stream_callback);
+
+ DatagramChannelCallback datagram_callback(
+ base::Bind(&JingleSession::OnChannelConnected,
+ base::Unretained(this)));
+ CreateDatagramChannel(kVideoRtpChannelName, datagram_callback);
+ CreateDatagramChannel(kVideoRtcpChannelName, datagram_callback);
+}
+
+void JingleSession::OnStreamChannelConnected(const std::string& name,
+ net::StreamSocket* socket) {
+ OnChannelConnected(name, socket);
+}
- DCHECK(!closed_);
- if (result != net::OK) {
- LOG(ERROR) << "Error during SSL connection: " << result;
- CloseInternal(result, true);
+void JingleSession::OnChannelConnected(const std::string& name,
+ net::Socket* socket) {
+ if (!socket) {
+ LOG(ERROR) << "Failed to connect channel " << name
+ << ". Terminating connection";
+ CloseInternal(net::ERR_CONNECTION_CLOSED, true);
return;
}
- if (event_ssl_socket_.get() && event_ssl_socket_->IsConnected() &&
- control_ssl_socket_.get() && control_ssl_socket_->IsConnected() &&
- video_ssl_socket_.get() && video_ssl_socket_->IsConnected()) {
+ if (name == kControlChannelName) {
+ control_channel_socket_.reset(socket);
+ } else if (name == kEventChannelName) {
+ event_channel_socket_.reset(socket);
+ } else if (name == kVideoChannelName) {
+ video_channel_socket_.reset(socket);
+ } else if (name == kVideoRtpChannelName) {
+ video_rtp_channel_socket_.reset(socket);
+ } else if (name == kVideoRtcpChannelName) {
+ video_rtcp_channel_socket_.reset(socket);
+ } else {
+ NOTREACHED();
+ }
+
+ if (control_channel_socket_.get() && event_channel_socket_.get() &&
+ video_channel_socket_.get() && video_rtp_channel_socket_.get() &&
+ video_rtcp_channel_socket_.get()) {
+ // TODO(sergeyu): State should be set to CONNECTED in OnAccept
+ // independent of the channels state.
SetState(CONNECTED);
}
}
+const cricket::ContentInfo* JingleSession::GetContentInfo() const {
+ const cricket::SessionDescription* session_description;
+ // If we initiate the session, we get to specify the content name. When
+ // accepting one, the remote end specifies it.
+ if (cricket_session_->initiator()) {
+ session_description = cricket_session_->local_description();
+ } else {
+ session_description = cricket_session_->remote_description();
+ }
+ const cricket::ContentInfo* content =
+ session_description->FirstContentByType(kChromotingXmlNamespace);
+ CHECK(content);
+ return content;
+}
+
void JingleSession::SetState(State new_state) {
DCHECK(CalledOnValidThread());
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index c011e88..13a29bc 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -13,17 +13,7 @@
#include "third_party/libjingle/source/talk/base/sigslot.h"
#include "third_party/libjingle/source/talk/p2p/base/session.h"
-namespace jingle_glue {
-class PseudoTcpAdapter;
-class StreamSocketAdapter;
-class TransportChannelSocketAdapter;
-} // namespace jingle_glue
-
namespace net {
-class CertVerifier;
-class ClientSocketFactory;
-class Socket;
-class StreamSocket;
class X509Certificate;
} // namespace net
@@ -31,6 +21,7 @@ namespace remoting {
namespace protocol {
+class JingleChannelConnector;
class JingleSessionManager;
// Implements protocol::Session that work over libjingle session (the
@@ -41,32 +32,33 @@ class JingleSession : public protocol::Session,
public:
static const char kChromotingContentName[];
- // Chromotocol Session interface.
- virtual void SetStateChangeCallback(StateChangeCallback* callback);
-
- virtual net::Socket* control_channel();
- virtual net::Socket* event_channel();
- virtual net::Socket* video_channel();
-
- virtual net::Socket* video_rtp_channel();
- virtual net::Socket* video_rtcp_channel();
-
- virtual const std::string& jid();
-
- virtual const CandidateSessionConfig* candidate_config();
-
- virtual const SessionConfig* config();
- virtual void set_config(const SessionConfig* config);
-
- virtual const std::string& initiator_token();
- virtual void set_initiator_token(const std::string& initiator_token);
- virtual const std::string& receiver_token();
- virtual void set_receiver_token(const std::string& receiver_token);
-
- virtual void Close();
+ // Session interface.
+ virtual void SetStateChangeCallback(StateChangeCallback* callback) OVERRIDE;
+ virtual void CreateStreamChannel(
+ const std::string& name,
+ const StreamChannelCallback& callback) OVERRIDE;
+ virtual void CreateDatagramChannel(
+ const std::string& name,
+ const DatagramChannelCallback& callback) OVERRIDE;
+ virtual net::Socket* control_channel() OVERRIDE;
+ virtual net::Socket* event_channel() OVERRIDE;
+ virtual net::Socket* video_channel() OVERRIDE;
+ virtual net::Socket* video_rtp_channel() OVERRIDE;
+ virtual net::Socket* video_rtcp_channel() OVERRIDE;
+ virtual const std::string& jid() OVERRIDE;
+ virtual const CandidateSessionConfig* candidate_config() OVERRIDE;
+ virtual const SessionConfig* config() OVERRIDE;
+ virtual void set_config(const SessionConfig* config) OVERRIDE;
+ virtual const std::string& initiator_token() OVERRIDE;
+ virtual void set_initiator_token(const std::string& initiator_token) OVERRIDE;
+ virtual const std::string& receiver_token() OVERRIDE;
+ virtual void set_receiver_token(const std::string& receiver_token) OVERRIDE;
+ virtual void Close() OVERRIDE;
private:
+ friend class JingleDatagramConnector;
friend class JingleSessionManager;
+ friend class JingleStreamConnector;
// Create a JingleSession used in client mode. A server certificate is
// required.
@@ -104,20 +96,7 @@ class JingleSession : public protocol::Session,
// Initialize the session configuration from a received connection response
// stanza.
bool InitializeConfigFromDescription(
- const cricket::SessionDescription* description);
-
- // Configures channels and calls InitializeSSL().
- void InitializeChannels();
-
- // Helper method to initialize PseudoTcp over the datagram-oriented |channel|.
- // If things don't immediately fail then a new StreamSocket is placed in
- // |pseudo_tcp|.
- bool EstablishPseudoTcp(net::Socket* channel,
- scoped_ptr<net::StreamSocket>* pseudo_tcp);
-
- // Helper method to initialize SSL over a StreamSocket.
- bool EstablishSSLConnection(net::StreamSocket* socket,
- scoped_ptr<net::StreamSocket>* ssl_socket);
+ const cricket::SessionDescription* description);
// Used for Session.SignalState sigslot.
void OnSessionState(cricket::BaseSession* session,
@@ -130,10 +109,30 @@ class JingleSession : public protocol::Session,
void OnAccept();
void OnTerminate();
- void OnConnect(int result);
+ // Notifies upper layer about incoming connection and
+ // accepts/rejects connection.
+ void AcceptConnection();
+
+ void AddChannelConnector(const std::string& name,
+ JingleChannelConnector* connector);
- // Called by SSL socket to notify connect event.
- void OnSSLConnect(int result);
+ // Called by JingleChannelConnector when it has finished connecting
+ // the channel and needs to be destroyed.
+ void OnChannelConnectorFinished(const std::string& name,
+ JingleChannelConnector* connector);
+
+ // Creates channels after session has been accepted.
+ // TODO(sergeyu): Don't create channels in JingleSession.
+ void CreateChannels();
+
+ // Callbacks for the channels created in JingleSession.
+ // TODO(sergeyu): Remove this method once *_channel() methods are
+ // removed from Session interface.
+ void OnStreamChannelConnected(
+ const std::string& name, net::StreamSocket* socket);
+ void OnChannelConnected(const std::string& name, net::Socket* socket);
+
+ const cricket::ContentInfo* GetContentInfo() const;
void SetState(State new_state);
@@ -178,43 +177,14 @@ class JingleSession : public protocol::Session,
// These data members are only set on the receiving side.
scoped_ptr<const CandidateSessionConfig> candidate_config_;
- // |raw_foo_channel_| is a reference to the Cricket transport channel foo,
- // which is owned by the Cricket session.
- // |foo_channel_| owns the Socket adapter for that channel.
- // |foo_socket_| takes ownership of the Socket from |foo_channel_| and wraps
- // it with PseudoTcp. |foo_ssl_socket_| takes ownership from |foo_socket_|
- // and runs the SSL protocol over it. Finally |foo_socket_wrapper_| takes
- // ownership of |foo_ssl_socket_|, wrapping it with a SocketWrapper to work
- // around issues with callers of the resulting Sockets continuing to access
- // them after CloseInternal() has completed.
- // TODO(wez): Fix the tear-down issue and remove SocketWrapper.
-
- cricket::TransportChannel* raw_control_channel_;
- scoped_ptr<jingle_glue::TransportChannelSocketAdapter> control_channel_;
- scoped_ptr<net::StreamSocket> control_socket_;
- scoped_ptr<net::StreamSocket> control_ssl_socket_;
-
- cricket::TransportChannel* raw_event_channel_;
- scoped_ptr<jingle_glue::TransportChannelSocketAdapter> event_channel_;
- scoped_ptr<net::StreamSocket> event_socket_;
- scoped_ptr<net::StreamSocket> event_ssl_socket_;
-
- cricket::TransportChannel* raw_video_channel_;
- scoped_ptr<jingle_glue::TransportChannelSocketAdapter> video_channel_;
- scoped_ptr<net::StreamSocket> video_socket_;
- scoped_ptr<net::StreamSocket> video_ssl_socket_;
-
- // Used to verify the certificate received in SSLClientSocket.
- scoped_ptr<net::CertVerifier> cert_verifier_;
-
- cricket::TransportChannel* raw_video_rtp_channel_;
- scoped_ptr<jingle_glue::TransportChannelSocketAdapter> video_rtp_channel_;
- cricket::TransportChannel* raw_video_rtcp_channel_;
- scoped_ptr<jingle_glue::TransportChannelSocketAdapter> video_rtcp_channel_;
-
- // Callback called by the SSL layer.
- net::CompletionCallbackImpl<JingleSession> connect_callback_;
- net::CompletionCallbackImpl<JingleSession> ssl_connect_callback_;
+ // Channels that are currently being connected.
+ std::map<std::string, JingleChannelConnector*> channel_connectors_;
+
+ scoped_ptr<net::Socket> control_channel_socket_;
+ scoped_ptr<net::Socket> event_channel_socket_;
+ scoped_ptr<net::Socket> video_channel_socket_;
+ scoped_ptr<net::Socket> video_rtp_channel_socket_;
+ scoped_ptr<net::Socket> video_rtcp_channel_socket_;
ScopedRunnableMethodFactory<JingleSession> task_factory_;
diff --git a/remoting/protocol/jingle_stream_connector.cc b/remoting/protocol/jingle_stream_connector.cc
new file mode 100644
index 0000000..ea541b0
--- /dev/null
+++ b/remoting/protocol/jingle_stream_connector.cc
@@ -0,0 +1,188 @@
+// Copyright (c) 2011 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_stream_connector.h"
+
+#include "jingle/glue/channel_socket_adapter.h"
+#include "jingle/glue/pseudotcp_adapter.h"
+#include "net/base/cert_status_flags.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ssl_config_service.h"
+#include "net/base/x509_certificate.h"
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_server_socket.h"
+#include "net/socket/client_socket_factory.h"
+#include "remoting/protocol/jingle_session.h"
+#include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
+
+namespace remoting {
+namespace protocol {
+
+namespace {
+
+// Value is choosen to balance the extra latency against the reduced
+// load due to ACK traffic.
+const int kTcpAckDelayMilliseconds = 10;
+
+// Helper method to create a SSL client socket.
+net::SSLClientSocket* CreateSSLClientSocket(
+ net::StreamSocket* socket, scoped_refptr<net::X509Certificate> cert,
+ net::CertVerifier* cert_verifier) {
+ net::SSLConfig ssl_config;
+
+ // Certificate provided by the host doesn't need authority.
+ net::SSLConfig::CertAndStatus cert_and_status;
+ cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID;
+ cert_and_status.cert = cert;
+ ssl_config.allowed_bad_certs.push_back(cert_and_status);
+
+ // SSLClientSocket takes ownership of the adapter.
+ net::HostPortPair host_and_pair(JingleSession::kChromotingContentName, 0);
+ net::SSLClientSocket* ssl_socket =
+ net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
+ socket, host_and_pair, ssl_config, NULL, cert_verifier);
+ return ssl_socket;
+}
+
+} // namespace
+
+JingleStreamConnector::JingleStreamConnector(
+ JingleSession* session,
+ const std::string& name,
+ const Session::StreamChannelCallback& callback)
+ : session_(session),
+ name_(name),
+ callback_(callback),
+ initiator_(false),
+ local_private_key_(NULL),
+ raw_channel_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(tcp_connect_callback_(
+ this, &JingleStreamConnector::OnTCPConnect)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_(
+ this, &JingleStreamConnector::OnSSLConnect)) {
+}
+
+JingleStreamConnector::~JingleStreamConnector() {
+}
+
+void JingleStreamConnector::Connect(bool initiator,
+ net::X509Certificate* local_cert,
+ net::X509Certificate* remote_cert,
+ crypto::RSAPrivateKey* local_private_key,
+ cricket::TransportChannel* raw_channel) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!raw_channel_);
+
+ initiator_ = initiator;
+ local_cert_ = local_cert;
+ remote_cert_ = remote_cert;
+ local_private_key_ = local_private_key;
+ raw_channel_ = raw_channel;
+
+ if (!initiator_) {
+ // Don't make outgoing connections from the host to client.
+ raw_channel_->GetP2PChannel()->set_incoming_only(true);
+ }
+
+ net::Socket* socket =
+ new jingle_glue::TransportChannelSocketAdapter(raw_channel_);
+
+ if (!EstablishTCPConnection(socket))
+ NotifyError();
+}
+
+bool JingleStreamConnector::EstablishTCPConnection(net::Socket* socket) {
+ jingle_glue::PseudoTcpAdapter* adapter =
+ new jingle_glue::PseudoTcpAdapter(socket);
+ adapter->SetAckDelay(kTcpAckDelayMilliseconds);
+ adapter->SetNoDelay(true);
+
+ socket_.reset(adapter);
+ int result = socket_->Connect(&tcp_connect_callback_);
+ if (result == net::ERR_IO_PENDING) {
+ return true;
+ } else if (result == net::OK) {
+ tcp_connect_callback_.Run(result);
+ return true;
+ }
+
+ return false;
+}
+
+bool JingleStreamConnector::EstablishSSLConnection() {
+ DCHECK(socket_->IsConnected());
+
+ int result;
+ if (initiator_) {
+ cert_verifier_.reset(new net::CertVerifier());
+
+ // Create client SSL socket.
+ net::SSLClientSocket* ssl_client_socket = CreateSSLClientSocket(
+ socket_.release(), remote_cert_, cert_verifier_.get());
+ socket_.reset(ssl_client_socket);
+
+ result = ssl_client_socket->Connect(&ssl_connect_callback_);
+ } else {
+ // Create server SSL socket.
+ net::SSLConfig ssl_config;
+ net::SSLServerSocket* ssl_server_socket =
+ net::CreateSSLServerSocket(socket_.release(), local_cert_,
+ local_private_key_, ssl_config);
+ socket_.reset(ssl_server_socket);
+
+ result = ssl_server_socket->Handshake(&ssl_connect_callback_);
+ }
+
+ if (result == net::ERR_IO_PENDING) {
+ return true;
+ } else if (result != net::OK) {
+ LOG(ERROR) << "Failed to establish SSL connection";
+ return false;
+ }
+
+ // Reach here if net::OK is received.
+ ssl_connect_callback_.Run(net::OK);
+ return true;
+}
+
+void JingleStreamConnector::OnTCPConnect(int result) {
+ DCHECK(CalledOnValidThread());
+
+ if (result != net::OK) {
+ LOG(ERROR) << "PseudoTCP connection failed: " << result;
+ NotifyError();
+ return;
+ }
+
+ if (!EstablishSSLConnection())
+ NotifyError();
+}
+
+void JingleStreamConnector::OnSSLConnect(int result) {
+ DCHECK(CalledOnValidThread());
+
+ if (result != net::OK) {
+ LOG(ERROR) << "Error during SSL connection: " << result;
+ NotifyError();
+ return;
+ }
+
+ DCHECK(socket_->IsConnected());
+ NotifyDone(socket_.release());
+}
+
+void JingleStreamConnector::NotifyDone(net::StreamSocket* socket) {
+ callback_.Run(name_, socket);
+ session_->OnChannelConnectorFinished(name_, this);
+}
+
+void JingleStreamConnector::NotifyError() {
+ socket_.reset();
+ callback_.Run(name_, NULL);
+ session_->OnChannelConnectorFinished(name_, this);
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/jingle_stream_connector.h b/remoting/protocol/jingle_stream_connector.h
new file mode 100644
index 0000000..ab7968b
--- /dev/null
+++ b/remoting/protocol/jingle_stream_connector.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2011 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.
+
+#ifndef REMOTING_PROTOCOL_JINGLE_STREAM_CONNECTOR_H_
+#define REMOTING_PROTOCOL_JINGLE_STREAM_CONNECTOR_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "remoting/protocol/jingle_channel_connector.h"
+#include "remoting/protocol/session.h"
+
+namespace cricket {
+class TransportChannel;
+} // namespace cricket
+
+namespace jingle_glue {
+class TransportChannelSocketAdapter;
+} // namespace jingle_glue
+
+namespace net {
+class CertVerifier;
+class StreamSocket;
+} // namespace net
+
+namespace remoting {
+namespace protocol {
+
+class JingleSession;
+
+class JingleStreamConnector : public JingleChannelConnector {
+ public:
+ JingleStreamConnector(JingleSession* session,
+ const std::string& name,
+ const Session::StreamChannelCallback& callback);
+ virtual ~JingleStreamConnector();
+
+ // Starts connection process for the channel. |local_private_key| is
+ // owned by the caller, and must exist until this object is
+ // destroyed.
+ virtual void Connect(bool initiator,
+ net::X509Certificate* local_cert,
+ net::X509Certificate* remote_cert,
+ crypto::RSAPrivateKey* local_private_key,
+ cricket::TransportChannel* raw_channel) OVERRIDE;
+
+ private:
+ bool EstablishTCPConnection(net::Socket* socket);
+ void OnTCPConnect(int result);
+
+ bool EstablishSSLConnection();
+ void OnSSLConnect(int result);
+
+ void NotifyDone(net::StreamSocket* socket);
+ void NotifyError();
+
+ JingleSession* session_;
+
+ std::string name_;
+
+ Session::StreamChannelCallback callback_;
+
+ bool initiator_;
+ scoped_refptr<net::X509Certificate> local_cert_;
+ scoped_refptr<net::X509Certificate> remote_cert_;
+ crypto::RSAPrivateKey* local_private_key_;
+
+ cricket::TransportChannel* raw_channel_;
+ scoped_ptr<net::StreamSocket> socket_;
+
+ // Used to verify the certificate received in SSLClientSocket.
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+
+ // Callback called by the TCP and SSL layers.
+ net::CompletionCallbackImpl<JingleStreamConnector> tcp_connect_callback_;
+ net::CompletionCallbackImpl<JingleStreamConnector> ssl_connect_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(JingleStreamConnector);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_JINGLE_STREAM_CONNECTOR_H_
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index 274b304..9b34b8e 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -112,6 +112,10 @@ class MockSession : public Session {
virtual ~MockSession();
MOCK_METHOD1(SetStateChangeCallback, void(StateChangeCallback* callback));
+ MOCK_METHOD2(CreateStreamChannel, void(
+ const std::string& name, const StreamChannelCallback& callback));
+ MOCK_METHOD2(CreateDatagramChannel, void(
+ const std::string& name, const DatagramChannelCallback& callback));
MOCK_METHOD0(control_channel, net::Socket*());
MOCK_METHOD0(event_channel, net::Socket*());
MOCK_METHOD0(video_channel, net::Socket*());
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h
index 754b223..059a21f 100644
--- a/remoting/protocol/session.h
+++ b/remoting/protocol/session.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
@@ -16,6 +16,7 @@ class Task;
namespace net {
class Socket;
+class StreamSocket;
} // namespace net
namespace remoting {
@@ -24,7 +25,6 @@ namespace protocol {
// Generic interface for Chromotocol connection used by both client and host.
// Provides access to the connection channels, but doesn't depend on the
// protocol used for each channel.
-// TODO(sergeyu): Remove refcounting?
class Session : public base::NonThreadSafe {
public:
enum State {
@@ -36,6 +36,10 @@ class Session : public base::NonThreadSafe {
};
typedef Callback1<State>::Type StateChangeCallback;
+ typedef base::Callback<void(const std::string&, net::StreamSocket*)>
+ StreamChannelCallback;
+ typedef base::Callback<void(const std::string&, net::Socket*)>
+ DatagramChannelCallback;
Session() { }
virtual ~Session() { }
@@ -44,20 +48,26 @@ class Session : public base::NonThreadSafe {
// Must be called on the jingle thread only.
virtual void SetStateChangeCallback(StateChangeCallback* callback) = 0;
- // Reliable PseudoTCP channels for this connection.
+ // Creates new channels for this connection. The specified callback
+ // is called when then new channel is created and connected. The
+ // callback is called with NULL if connection failed for any reason.
+ // Ownership of the channel socket is given to the caller when the
+ // callback is called. All channels must be destroyed before the
+ // session is destroyed. Can be called only when in CONNECTING or
+ // CONNECTED state.
+ virtual void CreateStreamChannel(
+ const std::string& name, const StreamChannelCallback& callback) = 0;
+ virtual void CreateDatagramChannel(
+ const std::string& name, const DatagramChannelCallback& callback) = 0;
+
+ // TODO(sergeyu): Remove these methods, and use CreateChannel()
+ // instead.
virtual net::Socket* control_channel() = 0;
virtual net::Socket* event_channel() = 0;
-
- // TODO(sergeyu): Remove VideoChannel, and use RTP channels instead.
virtual net::Socket* video_channel() = 0;
-
- // Unreliable channels for this connection.
virtual net::Socket* video_rtp_channel() = 0;
virtual net::Socket* video_rtcp_channel() = 0;
- // TODO(sergeyu): Make it possible to create/destroy additional channels
- // on-fly?
-
// JID of the other side.
virtual const std::string& jid() = 0;