summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-12 23:47:51 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-12 23:47:51 +0000
commit22aae95df95ac05d0fe4bf5a206e5631ea9c3242 (patch)
treee443dd13f566b2adb6be3191b7b66d98e2918ff6 /remoting
parent82ca9b9f30b2c497b9f224086de0089a6cb7a419 (diff)
downloadchromium_src-22aae95df95ac05d0fe4bf5a206e5631ea9c3242.zip
chromium_src-22aae95df95ac05d0fe4bf5a206e5631ea9c3242.tar.gz
chromium_src-22aae95df95ac05d0fe4bf5a206e5631ea9c3242.tar.bz2
Chromoting protocol implementation based on P2P Transport API.
Then new code is not enabled yet, there are still some issues that need to be resolved before this code is used by default. I plan to make the switch in M16, as there isn't enough time left in M15. TEST=Manual BUG=51198 Review URL: http://codereview.chromium.org/7778022 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100805 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r--remoting/base/constants.cc2
-rw-r--r--remoting/base/constants.h2
-rw-r--r--remoting/protocol/jingle_session.cc7
-rw-r--r--remoting/protocol/pepper_channel.h50
-rw-r--r--remoting/protocol/pepper_session.cc396
-rw-r--r--remoting/protocol/pepper_session.h168
-rw-r--r--remoting/protocol/pepper_session_manager.cc146
-rw-r--r--remoting/protocol/pepper_session_manager.h105
-rw-r--r--remoting/protocol/pepper_stream_channel.cc264
-rw-r--r--remoting/protocol/pepper_stream_channel.h92
-rw-r--r--remoting/protocol/pepper_transport_socket_adapter.cc14
-rw-r--r--remoting/protocol/pepper_transport_socket_adapter.h2
-rw-r--r--remoting/protocol/transport_config.cc18
-rw-r--r--remoting/protocol/transport_config.h26
-rw-r--r--remoting/remoting.gyp9
15 files changed, 1288 insertions, 13 deletions
diff --git a/remoting/base/constants.cc b/remoting/base/constants.cc
index 90ea755..178ec91 100644
--- a/remoting/base/constants.cc
+++ b/remoting/base/constants.cc
@@ -12,6 +12,8 @@ const char kChromotingTokenDefaultServiceName[] = "chromiumsync";
const char kChromotingXmlNamespace[] = "google:remoting";
+const char kControlChannelName[] = "control";
+const char kEventChannelName[] = "event";
const char kVideoChannelName[] = "video";
const char kVideoRtpChannelName[] = "videortp";
const char kVideoRtcpChannelName[] = "videortpc";
diff --git a/remoting/base/constants.h b/remoting/base/constants.h
index 6efa408..ed95ccc 100644
--- a/remoting/base/constants.h
+++ b/remoting/base/constants.h
@@ -18,6 +18,8 @@ extern const char kChromotingTokenDefaultServiceName[];
extern const char kChromotingXmlNamespace[];
// Channel names.
+extern const char kControlChannelName[];
+extern const char kEventChannelName[];
extern const char kVideoChannelName[];
extern const char kVideoRtpChannelName[];
extern const char kVideoRtcpChannelName[];
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
index b80239c..6d78f55 100644
--- a/remoting/protocol/jingle_session.cc
+++ b/remoting/protocol/jingle_session.cc
@@ -26,13 +26,6 @@ using cricket::BaseSession;
namespace remoting {
namespace protocol {
-namespace {
-
-const char kControlChannelName[] = "control";
-const char kEventChannelName[] = "event";
-
-} // namespace
-
// static
JingleSession* JingleSession::CreateClientSession(
JingleSessionManager* manager, const std::string& host_public_key) {
diff --git a/remoting/protocol/pepper_channel.h b/remoting/protocol/pepper_channel.h
new file mode 100644
index 0000000..6ae46bb
--- /dev/null
+++ b/remoting/protocol/pepper_channel.h
@@ -0,0 +1,50 @@
+// 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_PEPPER_CHANNEL_H_
+#define REMOTING_PROTOCOL_PEPPER_CHANNEL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/threading/non_thread_safe.h"
+
+namespace pp {
+class Instance;
+} // namespace pp
+
+namespace cricket {
+class Candidate;
+} // namespace cricket
+
+namespace remoting {
+namespace protocol {
+
+struct TransportConfig;
+
+// Interface for stream and datagram channels used by PepperSession.
+class PepperChannel : public base::NonThreadSafe {
+ public:
+ PepperChannel() { }
+ virtual ~PepperChannel() { }
+
+ // Connect the channel using specified |config|.
+ virtual void Connect(pp::Instance* pp_instance,
+ const TransportConfig& config,
+ const std::string& remote_cert) = 0;
+
+ // Adds |candidate| received from the peer.
+ virtual void AddRemoveCandidate(const cricket::Candidate& candidate) = 0;
+
+ // Name of the channel.
+ virtual const std::string& name() = 0;
+
+ protected:
+ DISALLOW_COPY_AND_ASSIGN(PepperChannel);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_PEPPER_CHANNEL_H_
diff --git a/remoting/protocol/pepper_session.cc b/remoting/protocol/pepper_session.cc
new file mode 100644
index 0000000..03167a90
--- /dev/null
+++ b/remoting/protocol/pepper_session.cc
@@ -0,0 +1,396 @@
+// 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/pepper_session.h"
+
+#include "base/bind.h"
+#include "base/rand_util.h"
+#include "base/stl_util.h"
+#include "base/string_number_conversions.h"
+#include "remoting/base/constants.h"
+#include "remoting/jingle_glue/iq_request.h"
+#include "remoting/protocol/content_description.h"
+#include "remoting/protocol/jingle_messages.h"
+#include "remoting/protocol/pepper_session_manager.h"
+#include "remoting/protocol/pepper_stream_channel.h"
+#include "third_party/libjingle/source/talk/p2p/base/candidate.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
+
+using buzz::XmlElement;
+
+namespace remoting {
+namespace protocol {
+
+namespace {
+// Delay after candidate creation before sending transport-info
+// message. This is neccessary to be able to pack multiple candidates
+// into one transport-info messages. The value needs to be greater
+// than zero because ports are opened asynchronously in the browser
+// process.
+const int kTransportInfoSendDelayMs = 2;
+} // namespace
+
+PepperSession::PepperSession(PepperSessionManager* session_manager)
+ : session_manager_(session_manager),
+ state_(INITIALIZING),
+ error_(ERROR_NO_ERROR) {
+}
+
+PepperSession::~PepperSession() {
+ control_channel_socket_.reset();
+ event_channel_socket_.reset();
+ STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
+ session_manager_->SessionDestroyed(this);
+}
+
+PepperSession::Error PepperSession::error() {
+ DCHECK(CalledOnValidThread());
+ return error_;
+}
+
+void PepperSession::SetStateChangeCallback(StateChangeCallback* callback) {
+ DCHECK(CalledOnValidThread());
+ state_change_callback_.reset(callback);
+}
+
+void PepperSession::StartConnection(
+ const std::string& peer_jid,
+ const std::string& peer_public_key,
+ const std::string& client_token,
+ CandidateSessionConfig* config,
+ Session::StateChangeCallback* state_change_callback) {
+ DCHECK(CalledOnValidThread());
+
+ peer_jid_ = peer_jid;
+ peer_public_key_ = peer_public_key;
+ initiator_token_ = client_token;
+ candidate_config_.reset(config);
+ state_change_callback_.reset(state_change_callback);
+
+ // Generate random session ID. There are usually not more than 1
+ // concurrent session per host, so a random 64-bit integer provides
+ // enough entropy. In the worst case connection will fail when two
+ // clients generate the same session ID concurrently.
+ session_id_ = base::Int64ToString(base::RandGenerator(kint64max));
+
+ // Send session-initiate message.
+ JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE,
+ session_id_);
+ message.from = session_manager_->local_jid_;
+ message.description.reset(
+ new ContentDescription(candidate_config_->Clone(), initiator_token_, ""));
+ initiate_request_.reset(session_manager_->CreateIqRequest());
+ initiate_request_->set_callback(base::Bind(
+ &PepperSession::OnSessionInitiateResponse, base::Unretained(this)));
+ initiate_request_->SendIq(message.ToXml());
+
+ SetState(CONNECTING);
+}
+
+void PepperSession::OnSessionInitiateResponse(
+ const buzz::XmlElement* response) {
+ const std::string& type = response->Attr(buzz::QName("", "type"));
+ if (type != "result") {
+ LOG(ERROR) << "Received error in response to session-initiate message: \""
+ << response->Str()
+ << "\" Terminating the session.";
+
+ // TODO(sergeyu): There may be different reasons for error
+ // here. Parse the response stanza to find failure reason.
+ OnError(ERROR_PEER_IS_OFFLINE);
+ }
+}
+
+void PepperSession::OnError(Error error) {
+ error_ = error;
+ CloseInternal(true);
+}
+
+void PepperSession::CreateStreamChannel(
+ const std::string& name,
+ const StreamChannelCallback& callback) {
+ DCHECK(!channels_[name]);
+
+ PepperStreamChannel* channel = new PepperStreamChannel(this, name, callback);
+ channels_[name] = channel;
+ channel->Connect(session_manager_->pp_instance_,
+ session_manager_->transport_config_, remote_cert_);
+}
+
+void PepperSession::CreateDatagramChannel(
+ const std::string& name,
+ const DatagramChannelCallback& callback) {
+ // TODO(sergeyu): Implement datagram channel support.
+ NOTREACHED();
+}
+
+net::Socket* PepperSession::control_channel() {
+ DCHECK(CalledOnValidThread());
+ return control_channel_socket_.get();
+}
+
+net::Socket* PepperSession::event_channel() {
+ DCHECK(CalledOnValidThread());
+ return event_channel_socket_.get();
+}
+
+const std::string& PepperSession::jid() {
+ DCHECK(CalledOnValidThread());
+ return peer_jid_;
+}
+
+const CandidateSessionConfig* PepperSession::candidate_config() {
+ DCHECK(CalledOnValidThread());
+ return candidate_config_.get();
+}
+
+const SessionConfig& PepperSession::config() {
+ DCHECK(CalledOnValidThread());
+ return config_;
+}
+
+void PepperSession::set_config(const SessionConfig& config) {
+ DCHECK(CalledOnValidThread());
+ // set_config() should never be called on the client.
+ NOTREACHED();
+}
+
+const std::string& PepperSession::initiator_token() {
+ DCHECK(CalledOnValidThread());
+ return initiator_token_;
+}
+
+void PepperSession::set_initiator_token(const std::string& initiator_token) {
+ DCHECK(CalledOnValidThread());
+ initiator_token_ = initiator_token;
+}
+
+const std::string& PepperSession::receiver_token() {
+ DCHECK(CalledOnValidThread());
+ return receiver_token_;
+}
+
+void PepperSession::set_receiver_token(const std::string& receiver_token) {
+ DCHECK(CalledOnValidThread());
+ // set_receiver_token() should not be called on the client side.
+ NOTREACHED();
+}
+
+void PepperSession::set_shared_secret(const std::string& secret) {
+ DCHECK(CalledOnValidThread());
+ shared_secret_ = secret;
+}
+
+const std::string& PepperSession::shared_secret() {
+ DCHECK(CalledOnValidThread());
+ return shared_secret_;
+}
+
+void PepperSession::Close() {
+ DCHECK(CalledOnValidThread());
+
+ if (state_ == CONNECTING || state_ == CONNECTED ||
+ state_ == CONNECTED_CHANNELS) {
+ // Send session-terminate message.
+ JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE,
+ session_id_);
+ scoped_ptr<IqRequest> terminate_request(
+ session_manager_->CreateIqRequest());
+ terminate_request->SendIq(message.ToXml());
+ }
+
+ CloseInternal(false);
+}
+
+void PepperSession::OnIncomingMessage(const JingleMessage& message,
+ JingleMessageReply* reply) {
+ DCHECK(CalledOnValidThread());
+
+ if (message.from != peer_jid_) {
+ // Ignore messages received from a different Jid.
+ *reply = JingleMessageReply(JingleMessageReply::INVALID_SID);
+ return;
+ }
+
+ switch (message.action) {
+ case JingleMessage::SESSION_ACCEPT:
+ OnAccept(message, reply);
+ break;
+
+ case JingleMessage::TRANSPORT_INFO:
+ ProcessTransportInfo(message);
+ break;
+
+ case JingleMessage::SESSION_REJECT:
+ OnReject(message, reply);
+ break;
+
+ case JingleMessage::SESSION_TERMINATE:
+ OnTerminate(message, reply);
+ break;
+
+ default:
+ *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST);
+ }
+}
+
+void PepperSession::OnAccept(const JingleMessage& message,
+ JingleMessageReply* reply) {
+ if (state_ != CONNECTING) {
+ *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST);
+ return;
+ }
+
+ if (!InitializeConfigFromDescription(message.description.get())) {
+ OnError(ERROR_INCOMPATIBLE_PROTOCOL);
+ return;
+ }
+
+ CreateChannels();
+ SetState(CONNECTED);
+
+ // In case there is transport information in the accept message.
+ ProcessTransportInfo(message);
+}
+
+void PepperSession::ProcessTransportInfo(const JingleMessage& message) {
+ for (std::list<cricket::Candidate>::const_iterator it =
+ message.candidates.begin();
+ it != message.candidates.end(); ++it) {
+ ChannelsMap::iterator channel = channels_.find(it->name());
+ if (channel == channels_.end()) {
+ LOG(WARNING) << "Received candidate for unknown channel " << it->name();
+ continue;
+ }
+ channel->second->AddRemoveCandidate(*it);
+ }
+}
+
+void PepperSession::OnReject(const JingleMessage& message,
+ JingleMessageReply* reply) {
+ if (state_ != CONNECTING) {
+ *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST);
+ return;
+ }
+
+ // TODO(sergeyu): Parse exact rejection reason from reply and pass it
+ // to OnError().
+ OnError(ERROR_SESSION_REJECTED);
+}
+
+void PepperSession::OnTerminate(const JingleMessage& message,
+ JingleMessageReply* reply) {
+ if (state_ == CONNECTING) {
+ // If we are not connected yet, then interpret terminate message
+ // as rejection.
+ OnError(ERROR_SESSION_REJECTED);
+ return;
+ }
+
+ CloseInternal(false);
+}
+
+bool PepperSession::InitializeConfigFromDescription(
+ const ContentDescription* description) {
+ DCHECK(description);
+
+ remote_cert_ = description->certificate();
+ if (remote_cert_.empty()) {
+ LOG(ERROR) << "session-accept does not specify certificate";
+ return false;
+ }
+
+ if (!description->config()->GetFinalConfig(&config_)) {
+ LOG(ERROR) << "session-accept does not specify configuration";
+ return false;
+ }
+ if (!candidate_config()->IsSupported(config_)) {
+ LOG(ERROR) << "session-accept specifies an invalid configuration";
+ return false;
+ }
+
+ return true;
+}
+
+void PepperSession::AddLocalCandidate(const cricket::Candidate& candidate) {
+ pending_candidates_.push_back(candidate);
+
+ if (!transport_infos_timer_.IsRunning()) {
+ // Delay sending the new candidates in case we get more candidates
+ // that we can send in one message.
+ transport_infos_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
+ this, &PepperSession::SendTransportInfo);
+ }
+}
+
+void PepperSession::OnDeleteChannel(PepperChannel* channel) {
+ ChannelsMap::iterator it = channels_.find(channel->name());
+ DCHECK_EQ(it->second, channel);
+ channels_.erase(it);
+}
+
+void PepperSession::SendTransportInfo() {
+ JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_);
+ message.candidates.swap(pending_candidates_);
+ scoped_ptr<IqRequest> request(session_manager_->CreateIqRequest());
+ request->SendIq(message.ToXml());
+}
+
+void PepperSession::CreateChannels() {
+ CreateStreamChannel(
+ kControlChannelName,
+ base::Bind(&PepperSession::OnChannelConnected,
+ base::Unretained(this), &control_channel_socket_));
+ CreateStreamChannel(
+ kEventChannelName,
+ base::Bind(&PepperSession::OnChannelConnected,
+ base::Unretained(this), &event_channel_socket_));
+}
+
+void PepperSession::OnChannelConnected(
+ scoped_ptr<net::Socket>* socket_container,
+ net::StreamSocket* socket) {
+ if (!socket) {
+ LOG(ERROR) << "Failed to connect control or events channel. "
+ << "Terminating connection";
+ OnError(ERROR_CHANNEL_CONNECTION_FAILURE);
+ return;
+ }
+
+ socket_container->reset(socket);
+
+ if (control_channel_socket_.get() && event_channel_socket_.get())
+ SetState(CONNECTED_CHANNELS);
+}
+
+void PepperSession::CloseInternal(bool failed) {
+ DCHECK(CalledOnValidThread());
+
+ if (state_ != FAILED && state_ != CLOSED) {
+ control_channel_socket_.reset();
+ event_channel_socket_.reset();
+
+ if (failed)
+ SetState(FAILED);
+ else
+ SetState(CLOSED);
+ }
+}
+
+void PepperSession::SetState(State new_state) {
+ DCHECK(CalledOnValidThread());
+
+ if (new_state != state_) {
+ DCHECK_NE(state_, CLOSED);
+ DCHECK_NE(state_, FAILED);
+
+ state_ = new_state;
+ if (state_change_callback_.get())
+ state_change_callback_->Run(new_state);
+ }
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/pepper_session.h b/remoting/protocol/pepper_session.h
new file mode 100644
index 0000000..99b9f6a
--- /dev/null
+++ b/remoting/protocol/pepper_session.h
@@ -0,0 +1,168 @@
+// 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_PEPPER_SESSION_H_
+#define REMOTING_PROTOCOL_PEPPER_SESSION_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "base/timer.h"
+#include "crypto/rsa_private_key.h"
+#include "net/base/completion_callback.h"
+#include "remoting/protocol/jingle_messages.h"
+#include "remoting/protocol/session.h"
+#include "remoting/protocol/session_config.h"
+
+namespace net {
+class CertVerifier;
+class ClientSocketFactory;
+class Socket;
+class StreamSocket;
+class X509Certificate;
+} // namespace net
+
+namespace pp {
+class Instance;
+} // namespace pp
+
+namespace remoting {
+
+class IqRequest;
+
+namespace protocol {
+
+class PepperChannel;
+class PepperSessionManager;
+class SocketWrapper;
+
+// Implements the protocol::Session interface using the Pepper P2P
+// Transport API. Created by PepperSessionManager for incoming and
+// outgoing connections.
+class PepperSession : public Session {
+ public:
+ // TODO(sergeyu): Move this type and error() method to the Session
+ // interface.
+ enum Error {
+ ERROR_NO_ERROR = 0,
+ ERROR_PEER_IS_OFFLINE,
+ ERROR_SESSION_REJECTED,
+ ERROR_INCOMPATIBLE_PROTOCOL,
+ ERROR_CHANNEL_CONNECTION_FAILURE,
+ };
+
+ virtual ~PepperSession();
+
+ Error error();
+
+ // 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 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 set_shared_secret(const std::string& secret) OVERRIDE;
+ virtual const std::string& shared_secret() OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ private:
+ friend class PepperSessionManager;
+ friend class PepperStreamChannel;
+
+ typedef std::map<std::string, PepperChannel*> ChannelsMap;
+
+ PepperSession(PepperSessionManager* session_manager);
+
+ // Start cs connection by sending session-initiate message.
+ void StartConnection(const std::string& peer_jid,
+ const std::string& peer_public_key,
+ const std::string& client_token,
+ CandidateSessionConfig* config,
+ Session::StateChangeCallback* state_change_callback);
+
+ // Handler for session-initiate response.
+ void OnSessionInitiateResponse(const buzz::XmlElement* response);
+
+ // Called when an error occurs. Sets |error_| and closes the session.
+ void OnError(Error error);
+
+ // Called by PepperSessionManager on incoming |message|. Must fill
+ // in |reply|.
+ void OnIncomingMessage(const JingleMessage& message,
+ JingleMessageReply* reply);
+
+ // Message handlers for incoming messages.
+ void OnAccept(const JingleMessage& message, JingleMessageReply* reply);
+ void OnReject(const JingleMessage& message, JingleMessageReply* reply);
+ void OnTerminate(const JingleMessage& message, JingleMessageReply* reply);
+ void ProcessTransportInfo(const JingleMessage& message);
+
+ // Called from OnAccept() to initialize session config.
+ bool InitializeConfigFromDescription(const ContentDescription* description);
+
+ // Called by PepperChannel.
+ void AddLocalCandidate(const cricket::Candidate& candidate);
+ void OnDeleteChannel(PepperChannel* channel);
+
+ void SendTransportInfo();
+
+ // Helper methods to create event and control channels.
+ // TODO(sergeyu): Remove these methods.
+ void CreateChannels();
+ void OnChannelConnected(scoped_ptr<net::Socket>* socket_container,
+ net::StreamSocket* socket);
+
+ // Close all the channels and terminate the session.
+ void CloseInternal(bool failed);
+
+ // Sets |state_| to |new_state| and calls state change callback.
+ void SetState(State new_state);
+
+ PepperSessionManager* session_manager_;
+ std::string peer_jid_;
+ std::string peer_public_key_;
+ scoped_ptr<CandidateSessionConfig> candidate_config_;
+ scoped_ptr<StateChangeCallback> state_change_callback_;
+
+ std::string session_id_;
+ State state_;
+ Error error_;
+
+ std::string remote_cert_;
+ SessionConfig config_;
+
+ std::string shared_secret_;
+ std::string initiator_token_;
+ std::string receiver_token_;
+
+ scoped_ptr<IqRequest> initiate_request_;
+
+ ChannelsMap channels_;
+
+ scoped_ptr<net::Socket> control_channel_socket_;
+ scoped_ptr<net::Socket> event_channel_socket_;
+
+ base::OneShotTimer<PepperSession> transport_infos_timer_;
+ std::list<cricket::Candidate> pending_candidates_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperSession);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_PEPPER_SESSION_H_
diff --git a/remoting/protocol/pepper_session_manager.cc b/remoting/protocol/pepper_session_manager.cc
new file mode 100644
index 0000000..28d979d
--- /dev/null
+++ b/remoting/protocol/pepper_session_manager.cc
@@ -0,0 +1,146 @@
+// 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/pepper_session_manager.h"
+
+#include "base/bind.h"
+#include "remoting/jingle_glue/jingle_info_request.h"
+#include "remoting/jingle_glue/signal_strategy.h"
+#include "remoting/protocol/jingle_messages.h"
+#include "remoting/protocol/pepper_session.h"
+#include "third_party/libjingle/source/talk/base/socketaddress.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
+
+using buzz::QName;
+
+namespace remoting {
+namespace protocol {
+
+PepperSessionManager::PepperSessionManager(pp::Instance* pp_instance)
+ : pp_instance_(pp_instance),
+ signal_strategy_(NULL),
+ listener_(NULL),
+ allow_nat_traversal_(false) {
+}
+
+PepperSessionManager::~PepperSessionManager() {
+ Close();
+}
+
+void PepperSessionManager::Init(
+ const std::string& local_jid,
+ SignalStrategy* signal_strategy,
+ SessionManager::Listener* listener,
+ crypto::RSAPrivateKey* private_key,
+ const std::string& certificate,
+ bool allow_nat_traversal) {
+ listener_ = listener;
+ local_jid_ = local_jid;
+ signal_strategy_ = signal_strategy;
+ private_key_.reset(private_key);
+ certificate_ = certificate;
+ allow_nat_traversal_ = allow_nat_traversal;
+
+ signal_strategy_->SetListener(this);
+
+ // If NAT traversal is enabled then we need to request STUN/Relay info.
+ if (allow_nat_traversal) {
+ jingle_info_request_.reset(
+ new JingleInfoRequest(signal_strategy_->CreateIqRequest(), NULL));
+ jingle_info_request_->Send(base::Bind(
+ &PepperSessionManager::OnJingleInfo, base::Unretained(this)));
+ } else {
+ listener_->OnSessionManagerInitialized();
+ }
+}
+
+void PepperSessionManager::OnJingleInfo(
+ const std::string& relay_token,
+ const std::vector<std::string>& relay_hosts,
+ const std::vector<talk_base::SocketAddress>& stun_hosts) {
+ DCHECK(CalledOnValidThread());
+
+ // TODO(sergeyu): Add support for multiple STUN/relay servers when
+ // it's implemented in libjingle and P2P Transport API.
+ transport_config_.stun_server = stun_hosts[0].ToString();
+ transport_config_.relay_server = relay_hosts[0];
+ transport_config_.relay_token = relay_token;
+ LOG(INFO) << "STUN server: " << transport_config_.stun_server
+ << " Relay server: " << transport_config_.relay_server
+ << " Relay token: " << transport_config_.relay_token;
+
+ listener_->OnSessionManagerInitialized();
+}
+
+Session* PepperSessionManager::Connect(
+ const std::string& host_jid,
+ const std::string& host_public_key,
+ const std::string& client_token,
+ CandidateSessionConfig* config,
+ Session::StateChangeCallback* state_change_callback) {
+ PepperSession* session = new PepperSession(this);
+ session->StartConnection(host_jid, host_public_key, client_token,
+ config, state_change_callback);
+ sessions_[session->session_id_] = session;
+ return session;
+}
+
+void PepperSessionManager::Close() {
+ DCHECK(CalledOnValidThread());
+
+ // Close() can be called only after all sessions are destroyed.
+ DCHECK(sessions_.empty());
+
+ listener_ = NULL;
+ jingle_info_request_.reset();
+
+ signal_strategy_->SetListener(NULL);
+}
+
+bool PepperSessionManager::OnIncomingStanza(const buzz::XmlElement* stanza) {
+ if (!JingleMessage::IsJingleMessage(stanza))
+ return false;
+
+ JingleMessage message;
+ std::string error;
+ if (!message.ParseXml(stanza, &error)) {
+ SendReply(stanza, JingleMessageReply(JingleMessageReply::BAD_REQUEST));
+ return true;
+ }
+
+ if (message.action == JingleMessage::SESSION_INITIATE) {
+ SendReply(stanza, JingleMessageReply(
+ JingleMessageReply::NOT_IMPLEMENTED,
+ "Can't accept sessions on the client"));
+ return true;
+ }
+
+ SessionsMap::iterator it = sessions_.find(message.sid);
+ if (it == sessions_.end()) {
+ SendReply(stanza, JingleMessageReply(JingleMessageReply::INVALID_SID));
+ return true;
+ }
+
+ JingleMessageReply reply;
+ it->second->OnIncomingMessage(message, &reply);
+ SendReply(stanza, reply);
+ return true;
+}
+
+IqRequest* PepperSessionManager::CreateIqRequest() {
+ return signal_strategy_->CreateIqRequest();
+}
+
+void PepperSessionManager::SendReply(const buzz::XmlElement* original_stanza,
+ const JingleMessageReply& reply) {
+ buzz::XmlElement* stanza = reply.ToXml(original_stanza);
+ signal_strategy_->SendStanza(stanza);
+}
+
+void PepperSessionManager::SessionDestroyed(PepperSession* session) {
+ sessions_.erase(session->session_id_);
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/pepper_session_manager.h b/remoting/protocol/pepper_session_manager.h
new file mode 100644
index 0000000..b8f7166
--- /dev/null
+++ b/remoting/protocol/pepper_session_manager.h
@@ -0,0 +1,105 @@
+// 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_PEPPER_SESSION_MANAGER_H_
+#define REMOTING_PROTOCOL_PEPPER_SESSION_MANAGER_H_
+
+#include <map>
+#include <list>
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "net/base/x509_certificate.h"
+#include "remoting/jingle_glue/signal_strategy.h"
+#include "remoting/protocol/pepper_channel.h"
+#include "remoting/protocol/session_manager.h"
+#include "remoting/protocol/transport_config.h"
+
+namespace pp {
+class Instance;
+} // namespace pp
+
+namespace buzz {
+class XmlElement;
+} // namespace buzz
+
+namespace talk_base {
+class SocketAddress;
+} // namespace talk_base
+
+namespace remoting {
+
+class JingleInfoRequest;
+
+namespace protocol {
+
+struct JingleMessage;
+struct JingleMessageReply;
+class PepperSession;
+
+// This class implements SessionManager interface on top of the Pepper
+// P2P Transport API.
+class PepperSessionManager : public SessionManager,
+ public SignalStrategy::Listener {
+ public:
+ explicit PepperSessionManager(pp::Instance* pp_instance);
+ virtual ~PepperSessionManager();
+
+ // SessionManager interface.
+ virtual void Init(const std::string& local_jid,
+ SignalStrategy* signal_strategy,
+ SessionManager::Listener* listener,
+ crypto::RSAPrivateKey* private_key,
+ const std::string& certificate,
+ bool allow_nat_traversal) OVERRIDE;
+ virtual Session* Connect(
+ const std::string& host_jid,
+ const std::string& host_public_key,
+ const std::string& client_token,
+ CandidateSessionConfig* config,
+ Session::StateChangeCallback* state_change_callback) OVERRIDE;
+ virtual void Close() OVERRIDE;
+
+ // SignalStrategy::Listener interface.
+ virtual bool OnIncomingStanza(const buzz::XmlElement* stanza) OVERRIDE;
+
+ private:
+ friend class PepperSession;
+
+ typedef std::map<std::string, PepperSession*> SessionsMap;
+
+ void OnJingleInfo(
+ const std::string& relay_token,
+ const std::vector<std::string>& relay_hosts,
+ const std::vector<talk_base::SocketAddress>& stun_hosts);
+
+ IqRequest* CreateIqRequest();
+ void SendReply(const buzz::XmlElement* original_stanza,
+ const JingleMessageReply& reply);
+
+ // Called by PepperSession when it is being destroyed.
+ void SessionDestroyed(PepperSession* session);
+
+ pp::Instance* pp_instance_;
+
+ std::string local_jid_;
+ SignalStrategy* signal_strategy_;
+ SessionManager::Listener* listener_;
+ scoped_ptr<crypto::RSAPrivateKey> private_key_;
+ std::string certificate_;
+ bool allow_nat_traversal_;
+
+ TransportConfig transport_config_;
+
+ scoped_ptr<JingleInfoRequest> jingle_info_request_;
+
+ SessionsMap sessions_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperSessionManager);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_PEPPER_SESSION_MANAGER_H_
diff --git a/remoting/protocol/pepper_stream_channel.cc b/remoting/protocol/pepper_stream_channel.cc
new file mode 100644
index 0000000..9769adc
--- /dev/null
+++ b/remoting/protocol/pepper_stream_channel.cc
@@ -0,0 +1,264 @@
+// 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/pepper_stream_channel.h"
+
+#include "base/bind.h"
+#include "crypto/hmac.h"
+#include "jingle/glue/utils.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/socket/ssl_client_socket.h"
+#include "net/socket/client_socket_factory.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/dev/transport_dev.h"
+#include "ppapi/cpp/var.h"
+#include "remoting/protocol/channel_authenticator.h"
+#include "remoting/protocol/pepper_session.h"
+#include "remoting/protocol/transport_config.h"
+#include "third_party/libjingle/source/talk/p2p/base/candidate.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;
+
+// Values for the TCP send and receive buffer size. This should be tuned to
+// accomodate high latency network but not backlog the decoding pipeline.
+const int kTcpReceiveBufferSize = 256 * 1024;
+const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
+
+// Helper method to create a SSL client socket.
+net::SSLClientSocket* CreateSSLClientSocket(
+ net::StreamSocket* socket, const std::string& der_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.der_cert = der_cert;
+ ssl_config.allowed_bad_certs.push_back(cert_and_status);
+
+ // Revocation checking is not needed because we use self-signed
+ // certs. Disable it so that SSL layer doesn't try to initialize
+ // OCSP (OCSP works only on IO thread).
+ ssl_config.rev_checking_enabled = false;
+
+ // SSLClientSocket takes ownership of the |socket|.
+ net::HostPortPair host_and_port("chromoting", 0);
+ net::SSLClientSocketContext context;
+ context.cert_verifier = cert_verifier;
+ net::SSLClientSocket* ssl_socket =
+ net::ClientSocketFactory::GetDefaultFactory()->CreateSSLClientSocket(
+ socket, host_and_port, ssl_config, NULL, context);
+ return ssl_socket;
+}
+
+} // namespace
+
+PepperStreamChannel::PepperStreamChannel(
+ PepperSession* session,
+ const std::string& name,
+ const Session::StreamChannelCallback& callback)
+ : session_(session),
+ name_(name),
+ callback_(callback),
+ channel_(NULL),
+ connected_(false),
+ ssl_client_socket_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(p2p_connect_callback_(
+ this, &PepperStreamChannel::OnP2PConnect)),
+ ALLOW_THIS_IN_INITIALIZER_LIST(ssl_connect_callback_(
+ this, &PepperStreamChannel::OnSSLConnect)) {
+}
+
+PepperStreamChannel::~PepperStreamChannel() {
+ // Verify that the |channel_| is ether destroyed or we own it.
+ DCHECK_EQ(channel_, owned_channel_.get());
+ // Channel should be already destroyed if we were connected.
+ DCHECK(!connected_ || channel_ == NULL);
+}
+
+void PepperStreamChannel::Connect(pp::Instance* pp_instance,
+ const TransportConfig& transport_config,
+ const std::string& remote_cert) {
+ DCHECK(CalledOnValidThread());
+
+ remote_cert_ = remote_cert;
+
+ pp::Transport_Dev* transport =
+ new pp::Transport_Dev(pp_instance, name_.c_str(), "tcp");
+
+ if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_RECEIVE_WINDOW,
+ pp::Var(kTcpReceiveBufferSize)) != PP_OK) {
+ LOG(ERROR) << "Failed to set TCP receive window";
+ }
+ if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_SEND_WINDOW,
+ pp::Var(kTcpSendBufferSize)) != PP_OK) {
+ LOG(ERROR) << "Failed to set TCP send window";
+ }
+
+ if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_NO_DELAY,
+ pp::Var(true)) != PP_OK) {
+ LOG(ERROR) << "Failed to set TCP_NODELAY";
+ }
+
+ if (transport->SetProperty(PP_TRANSPORTPROPERTY_TCP_ACK_DELAY,
+ pp::Var(kTcpAckDelayMilliseconds)) != PP_OK) {
+ LOG(ERROR) << "Failed to set TCP ACK delay.";
+ }
+
+ if (transport_config.nat_traversal) {
+ if (transport->SetProperty(
+ PP_TRANSPORTPROPERTY_STUN_SERVER,
+ pp::Var(transport_config.stun_server)) != PP_OK) {
+ LOG(ERROR) << "Failed to set STUN server.";
+ }
+
+ if (transport->SetProperty(
+ PP_TRANSPORTPROPERTY_RELAY_SERVER,
+ pp::Var(transport_config.relay_server)) != PP_OK) {
+ LOG(ERROR) << "Failed to set Relay server.";
+ }
+
+ if (transport->SetProperty(
+ PP_TRANSPORTPROPERTY_RELAY_TOKEN,
+ pp::Var(transport_config.relay_token)) != PP_OK) {
+ LOG(ERROR) << "Failed to set Relay token.";
+ }
+ }
+
+ channel_ = new PepperTransportSocketAdapter(transport, name_, this);
+ owned_channel_.reset(channel_);
+
+ int result = channel_->Connect(&p2p_connect_callback_);
+ if (result != net::ERR_IO_PENDING)
+ OnP2PConnect(result);
+}
+
+void PepperStreamChannel::AddRemoveCandidate(
+ const cricket::Candidate& candidate) {
+ DCHECK(CalledOnValidThread());
+ if (channel_)
+ channel_->AddRemoteCandidate(jingle_glue::SerializeP2PCandidate(candidate));
+}
+
+const std::string& PepperStreamChannel::name() {
+ DCHECK(CalledOnValidThread());
+ return name_;
+}
+
+void PepperStreamChannel::OnChannelDeleted() {
+ if (connected_) {
+ channel_ = NULL;
+ // The PepperTransportSocketAdapter is being deleted, so delete the
+ // channel too.
+ session_->OnDeleteChannel(this);
+ delete this;
+ }
+}
+
+void PepperStreamChannel::OnChannelNewLocalCandidate(
+ const std::string& candidate) {
+ DCHECK(CalledOnValidThread());
+
+ cricket::Candidate candidate_value;
+ if (!jingle_glue::DeserializeP2PCandidate(candidate, &candidate_value)) {
+ LOG(ERROR) << "Failed to parse candidate " << candidate;
+ }
+ session_->AddLocalCandidate(candidate_value);
+}
+
+void PepperStreamChannel::OnP2PConnect(int result) {
+ DCHECK(CalledOnValidThread());
+
+ if (result != net::OK || !EstablishSSLConnection())
+ NotifyConnectFailed();
+}
+
+bool PepperStreamChannel::EstablishSSLConnection() {
+ DCHECK(CalledOnValidThread());
+
+ cert_verifier_.reset(new net::CertVerifier());
+
+ // Create client SSL socket.
+ ssl_client_socket_ = CreateSSLClientSocket(
+ owned_channel_.release(), remote_cert_, cert_verifier_.get());
+ socket_.reset(ssl_client_socket_);
+
+ int result = ssl_client_socket_->Connect(&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 PepperStreamChannel::OnSSLConnect(int result) {
+ DCHECK(CalledOnValidThread());
+
+ if (result != net::OK) {
+ LOG(ERROR) << "Error during SSL connection: " << result;
+ NotifyConnectFailed();
+ return;
+ }
+
+ DCHECK(socket_->IsConnected());
+ AuthenticateChannel();
+}
+
+void PepperStreamChannel::AuthenticateChannel() {
+ DCHECK(CalledOnValidThread());
+
+ authenticator_.reset(new ClientChannelAuthenticator(ssl_client_socket_));
+ authenticator_->Authenticate(
+ session_->shared_secret(),
+ base::Bind(&PepperStreamChannel::OnAuthenticationDone,
+ base::Unretained(this)));
+}
+
+void PepperStreamChannel::OnAuthenticationDone(
+ ChannelAuthenticator::Result result) {
+ DCHECK(CalledOnValidThread());
+
+ switch (result) {
+ case ChannelAuthenticator::SUCCESS:
+ NotifyConnected(socket_.release());
+ break;
+
+ case ChannelAuthenticator::FAILURE:
+ NotifyConnectFailed();
+ break;
+ }
+}
+
+void PepperStreamChannel::NotifyConnected(net::StreamSocket* socket) {
+ DCHECK(!connected_);
+ callback_.Run(socket);
+ connected_ = true;
+}
+
+void PepperStreamChannel::NotifyConnectFailed() {
+ channel_ = NULL;
+ owned_channel_.reset();
+ socket_.reset();
+
+ NotifyConnected(NULL);
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/pepper_stream_channel.h b/remoting/protocol/pepper_stream_channel.h
new file mode 100644
index 0000000..d5afe27
--- /dev/null
+++ b/remoting/protocol/pepper_stream_channel.h
@@ -0,0 +1,92 @@
+// 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_PEPPER_STREAM_CHANNEL_H_
+#define REMOTING_PROTOCOL_PEPPER_STREAM_CHANNEL_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/completion_callback.h"
+#include "remoting/protocol/channel_authenticator.h"
+#include "remoting/protocol/pepper_channel.h"
+#include "remoting/protocol/pepper_transport_socket_adapter.h"
+#include "remoting/protocol/session.h"
+
+namespace net {
+class CertVerifier;
+class StreamSocket;
+class SSLClientSocket;
+class SSLServerSocket;
+} // namespace net
+
+namespace remoting {
+namespace protocol {
+
+class PepperSession;
+
+class PepperStreamChannel : public PepperChannel,
+ public PepperTransportSocketAdapter::Observer {
+ public:
+ PepperStreamChannel(PepperSession* session,
+ const std::string& name,
+ const Session::StreamChannelCallback& callback);
+ virtual ~PepperStreamChannel();
+
+ // PepperChannel implementation.
+ virtual void Connect(pp::Instance* pp_instance,
+ const TransportConfig& transport_config,
+ const std::string& remote_cert) OVERRIDE;
+ virtual void AddRemoveCandidate(const cricket::Candidate& candidate) OVERRIDE;
+ virtual const std::string& name() OVERRIDE;
+
+ // PepperTransportSocketAdapter implementation.
+ virtual void OnChannelDeleted() OVERRIDE;
+ virtual void OnChannelNewLocalCandidate(
+ const std::string& candidate) OVERRIDE;
+
+ private:
+ void OnP2PConnect(int result);
+
+ bool EstablishSSLConnection();
+ void OnSSLConnect(int result);
+
+ void AuthenticateChannel();
+ void OnAuthenticationDone(ChannelAuthenticator::Result result);
+
+ void NotifyConnected(net::StreamSocket* socket);
+ void NotifyConnectFailed();
+
+ PepperSession* session_;
+ std::string name_;
+ Session::StreamChannelCallback callback_;
+
+ std::string remote_cert_;
+
+ // We own |channel_| until it is connected. After that
+ // SSLClientSocket owns it.
+ scoped_ptr<PepperTransportSocketAdapter> owned_channel_;
+ PepperTransportSocketAdapter* channel_;
+
+ // Indicates that we've finished connecting.
+ bool connected_;
+
+ scoped_ptr<net::StreamSocket> socket_;
+ net::SSLClientSocket* ssl_client_socket_;
+
+ // Used to verify the certificate received in SSLClientSocket.
+ scoped_ptr<net::CertVerifier> cert_verifier_;
+
+ scoped_ptr<ChannelAuthenticator> authenticator_;
+
+ // Callback called by the TCP and SSL layers.
+ net::CompletionCallbackImpl<PepperStreamChannel> p2p_connect_callback_;
+ net::CompletionCallbackImpl<PepperStreamChannel> ssl_connect_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperStreamChannel);
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_PEPPER_STREAM_CHANNEL_H_
diff --git a/remoting/protocol/pepper_transport_socket_adapter.cc b/remoting/protocol/pepper_transport_socket_adapter.cc
index d247e05..1d65be0 100644
--- a/remoting/protocol/pepper_transport_socket_adapter.cc
+++ b/remoting/protocol/pepper_transport_socket_adapter.cc
@@ -5,8 +5,10 @@
#include "remoting/protocol/pepper_transport_socket_adapter.h"
#include "base/logging.h"
+#include "net/base/address_list.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/dev/transport_dev.h"
#include "ppapi/cpp/var.h"
@@ -39,18 +41,17 @@ int PPErrorToNetError(int result) {
} // namespace
PepperTransportSocketAdapter::PepperTransportSocketAdapter(
- pp::Instance* pp_instance,
+ pp::Transport_Dev* transport,
const std::string& name,
Observer* observer)
: name_(name),
observer_(observer),
+ transport_(transport),
connected_(false),
get_address_pending_(false),
read_callback_(NULL),
write_callback_(NULL) {
callback_factory_.Initialize(this);
- transport_.reset(new pp::Transport_Dev(
- pp_instance, name_.c_str(), kTcpProtocol));
}
PepperTransportSocketAdapter::~PepperTransportSocketAdapter() {
@@ -148,8 +149,11 @@ bool PepperTransportSocketAdapter::IsConnectedAndIdle() const {
int PepperTransportSocketAdapter::GetPeerAddress(
net::AddressList* address) const {
- NOTIMPLEMENTED();
- return net::ERR_FAILED;
+ // We don't have a meaningful peer address, but we can't return an
+ // error, so we return a INADDR_ANY instead.
+ net::IPAddressNumber ip_address(4);
+ *address = net::AddressList::CreateFromIPAddress(ip_address, 0);
+ return net::OK;
}
int PepperTransportSocketAdapter::GetLocalAddress(
diff --git a/remoting/protocol/pepper_transport_socket_adapter.h b/remoting/protocol/pepper_transport_socket_adapter.h
index c69f8d2..92cc410 100644
--- a/remoting/protocol/pepper_transport_socket_adapter.h
+++ b/remoting/protocol/pepper_transport_socket_adapter.h
@@ -38,7 +38,7 @@ class PepperTransportSocketAdapter : public base::NonThreadSafe,
virtual void OnChannelNewLocalCandidate(const std::string& candidate) = 0;
};
- PepperTransportSocketAdapter(pp::Instance* pp_instance,
+ PepperTransportSocketAdapter(pp::Transport_Dev* transport,
const std::string& name,
Observer* observer);
virtual ~PepperTransportSocketAdapter();
diff --git a/remoting/protocol/transport_config.cc b/remoting/protocol/transport_config.cc
new file mode 100644
index 0000000..bd2be68
--- /dev/null
+++ b/remoting/protocol/transport_config.cc
@@ -0,0 +1,18 @@
+// 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/transport_config.h"
+
+namespace remoting {
+namespace protocol {
+
+TransportConfig::TransportConfig()
+ : nat_traversal(false) {
+}
+
+TransportConfig::~TransportConfig() {
+}
+
+} // namespace protocol
+} // namespace remoting
diff --git a/remoting/protocol/transport_config.h b/remoting/protocol/transport_config.h
new file mode 100644
index 0000000..c1105ef
--- /dev/null
+++ b/remoting/protocol/transport_config.h
@@ -0,0 +1,26 @@
+// 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_TRANSPORT_CONFIG_H_
+#define REMOTING_PROTOCOL_TRANSPORT_CONFIG_H_
+
+#include <string>
+
+namespace remoting {
+namespace protocol {
+
+struct TransportConfig {
+ TransportConfig();
+ ~TransportConfig();
+
+ bool nat_traversal;
+ std::string stun_server;
+ std::string relay_server;
+ std::string relay_token;
+};
+
+} // namespace protocol
+} // namespace remoting
+
+#endif // REMOTING_PROTOCOL_TRANSPORT_CONFIG_H_
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 01c4d39..8d9444b 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -708,6 +708,13 @@
'protocol/message_decoder.h',
'protocol/message_reader.cc',
'protocol/message_reader.h',
+ 'protocol/pepper_channel.h',
+ 'protocol/pepper_session.cc',
+ 'protocol/pepper_session.h',
+ 'protocol/pepper_session_manager.cc',
+ 'protocol/pepper_session_manager.h',
+ 'protocol/pepper_stream_channel.cc',
+ 'protocol/pepper_stream_channel.h',
'protocol/pepper_transport_socket_adapter.cc',
'protocol/pepper_transport_socket_adapter.h',
'protocol/protobuf_video_reader.cc',
@@ -734,6 +741,8 @@
'protocol/session_manager.h',
'protocol/socket_reader_base.cc',
'protocol/socket_reader_base.h',
+ 'protocol/transport_config.cc',
+ 'protocol/transport_config.h',
'protocol/util.cc',
'protocol/util.h',
'protocol/video_reader.cc',