summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jingle/glue/pseudotcp_adapter.cc4
-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
16 files changed, 1290 insertions, 15 deletions
diff --git a/jingle/glue/pseudotcp_adapter.cc b/jingle/glue/pseudotcp_adapter.cc
index e2b3130..94c81aa 100644
--- a/jingle/glue/pseudotcp_adapter.cc
+++ b/jingle/glue/pseudotcp_adapter.cc
@@ -447,8 +447,8 @@ bool PseudoTcpAdapter::IsConnectedAndIdle() const {
int PseudoTcpAdapter::GetPeerAddress(net::AddressList* address) const {
DCHECK(CalledOnValidThread());
- // We actually don't know the peer address. Returning so the upper layers
- // won't complain.
+ // 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;
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',