summaryrefslogtreecommitdiffstats
path: root/content/renderer/p2p/p2p_transport_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'content/renderer/p2p/p2p_transport_impl.cc')
-rw-r--r--content/renderer/p2p/p2p_transport_impl.cc161
1 files changed, 161 insertions, 0 deletions
diff --git a/content/renderer/p2p/p2p_transport_impl.cc b/content/renderer/p2p/p2p_transport_impl.cc
new file mode 100644
index 0000000..d5f2afe
--- /dev/null
+++ b/content/renderer/p2p/p2p_transport_impl.cc
@@ -0,0 +1,161 @@
+// 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 "content/renderer/p2p/p2p_transport_impl.h"
+
+#include "base/values.h"
+#include "content/renderer/p2p/ipc_network_manager.h"
+#include "content/renderer/p2p/ipc_socket_factory.h"
+#include "content/renderer/render_view.h"
+#include "chrome/common/json_value_serializer.h"
+#include "jingle/glue/channel_socket_adapter.h"
+#include "jingle/glue/thread_wrapper.h"
+#include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
+#include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h"
+
+P2PTransportImpl::P2PTransportImpl(
+ talk_base::NetworkManager* network_manager,
+ talk_base::PacketSocketFactory* socket_factory)
+ : event_handler_(NULL),
+ state_(STATE_NONE),
+ network_manager_(network_manager),
+ socket_factory_(socket_factory) {
+}
+
+P2PTransportImpl::~P2PTransportImpl() {
+}
+
+bool P2PTransportImpl::Init(const std::string& name, const std::string& config,
+ EventHandler* event_handler) {
+ DCHECK(event_handler);
+
+ // Before proceeding, ensure we have libjingle thread wrapper for
+ // the current thread.
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
+
+ name_ = name;
+ event_handler_ = event_handler;
+
+ // TODO(sergeyu): Implement PortAllocator that can parse |config|
+ // and use it here instead of BasicPortAllocator.
+ allocator_.reset(new cricket::BasicPortAllocator(
+ network_manager_, socket_factory_));
+
+ channel_.reset(new cricket::P2PTransportChannel(
+ name, "", NULL, allocator_.get()));
+ channel_->SignalRequestSignaling.connect(
+ this, &P2PTransportImpl::OnRequestSignaling);
+ channel_->SignalWritableState.connect(
+ this, &P2PTransportImpl::OnReadableState);
+ channel_->SignalWritableState.connect(
+ this, &P2PTransportImpl::OnWriteableState);
+ channel_->SignalCandidateReady.connect(
+ this, &P2PTransportImpl::OnCandidateReady);
+
+ channel_adapter_.reset(new jingle_glue::TransportChannelSocketAdapter(
+ channel_.get()));
+
+ channel_->Connect();
+
+ return true;
+}
+
+bool P2PTransportImpl::AddRemoteCandidate(const std::string& address) {
+ cricket::Candidate candidate;
+ if (!DeserializeCandidate(address, &candidate)) {
+ return false;
+ }
+
+ channel_->OnCandidate(candidate);
+ return true;
+}
+
+void P2PTransportImpl::OnRequestSignaling() {
+ channel_->OnSignalingReady();
+}
+
+void P2PTransportImpl::OnCandidateReady(
+ cricket::TransportChannelImpl* channel,
+ const cricket::Candidate& candidate) {
+ event_handler_->OnCandidateReady(SerializeCandidate(candidate));
+}
+
+void P2PTransportImpl::OnReadableState(cricket::TransportChannel* channel) {
+ state_ = static_cast<State>(state_ | STATE_READABLE);
+ event_handler_->OnStateChange(state_);
+}
+
+void P2PTransportImpl::OnWriteableState(cricket::TransportChannel* channel) {
+ state_ = static_cast<State>(state_ | STATE_WRITABLE);
+ event_handler_->OnStateChange(state_);
+}
+
+std::string P2PTransportImpl::SerializeCandidate(
+ const cricket::Candidate& candidate) {
+
+ // TODO(sergeyu): Use SDP to format candidates?
+ DictionaryValue value;
+ value.SetString("name", candidate.name());
+ value.SetString("ip", candidate.address().IPAsString());
+ value.SetInteger("port", candidate.address().port());
+ value.SetString("type", candidate.type());
+ value.SetString("protocol", candidate.protocol());
+ value.SetString("username", candidate.username());
+ value.SetString("password", candidate.password());
+ value.SetDouble("preference", candidate.preference());
+ value.SetInteger("generation", candidate.generation());
+
+ std::string result;
+ JSONStringValueSerializer serializer(&result);
+ serializer.Serialize(value);
+ return result;
+}
+
+bool P2PTransportImpl::DeserializeCandidate(const std::string& address,
+ cricket::Candidate* candidate) {
+ JSONStringValueSerializer deserializer(address);
+ scoped_ptr<Value> value(deserializer.Deserialize(NULL, NULL));
+ if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY)) {
+ return false;
+ }
+
+ DictionaryValue* dic_value = static_cast<DictionaryValue*>(value.get());
+
+ std::string name;
+ std::string ip;
+ int port;
+ std::string type;
+ std::string protocol;
+ std::string username;
+ std::string password;
+ double preference;
+ int generation;
+
+ if (!dic_value->GetString("name", &name) ||
+ !dic_value->GetString("ip", &ip) ||
+ !dic_value->GetInteger("port", &port) ||
+ !dic_value->GetString("type", &type) ||
+ !dic_value->GetString("protocol", &protocol) ||
+ !dic_value->GetString("username", &username) ||
+ !dic_value->GetString("password", &password) ||
+ !dic_value->GetDouble("preference", &preference) ||
+ !dic_value->GetInteger("generation", &generation)) {
+ return false;
+ }
+
+ candidate->set_name(name);
+ candidate->set_address(talk_base::SocketAddress(ip, port));
+ candidate->set_type(type);
+ candidate->set_protocol(protocol);
+ candidate->set_username(username);
+ candidate->set_password(password);
+ candidate->set_preference(static_cast<float>(preference));
+ candidate->set_generation(generation);
+
+ return true;
+}
+
+net::Socket* P2PTransportImpl::GetChannel() {
+ return channel_adapter_.get();
+}