Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1955)

Unified Diff: webkit/plugins/ppapi/ppb_transport_impl.cc

Issue 6478018: Basic implementation of Pepper Transport API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: updated copyright year Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webkit/plugins/ppapi/ppb_transport_impl.cc
diff --git a/webkit/plugins/ppapi/ppb_transport_impl.cc b/webkit/plugins/ppapi/ppb_transport_impl.cc
index 69139e750065d61e402a55b8627334cf6df8c713..7f32f5f8e11705d03ebbe4065d2a6ab420e35025 100644
--- a/webkit/plugins/ppapi/ppb_transport_impl.cc
+++ b/webkit/plugins/ppapi/ppb_transport_impl.cc
@@ -1,109 +1,87 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "webkit/plugins/ppapi/ppb_transport_impl.h"
-#include "base/singleton.h"
-#include "base/threading/thread_local.h"
#include "ppapi/c/dev/ppb_transport_dev.h"
+#include "ppapi/c/pp_completion_callback.h"
+#include "ppapi/c/pp_errors.h"
+#include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
+#include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
#include "webkit/plugins/ppapi/common.h"
#include "webkit/plugins/ppapi/plugin_module.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
+#include "webkit/plugins/ppapi/var.h"
namespace webkit {
namespace ppapi {
namespace {
-// Creates a new transport object with the specified name
-// using the specified protocol.
-PP_Resource CreateTransport(PP_Instance instance,
- const char* name,
+PP_Resource CreateTransport(PP_Instance instance_id, const char* name,
const char* proto) {
- // TODO(juberti): implement me
- PP_Resource p(0);
- return p;
+ PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
+ if (!instance)
+ return 0;
+
+ scoped_refptr<PPB_Transport_Impl> t(new PPB_Transport_Impl(instance));
+ if (!t->Init(name, proto))
+ return 0;
+
+ return t->GetReference();
}
-// Returns whether or not resource is PPB_Transport_Impl
PP_Bool IsTransport(PP_Resource resource) {
- return BoolToPPBool(!!Resource::GetAs<PPB_Transport_Impl>(resource));
+ return BoolToPPBool(Resource::GetAs<PPB_Transport_Impl>(resource) != NULL);
}
-// Returns whether the transport is currently writable
-// (i.e. can send data to the remote peer)
-PP_Bool IsWritable(PP_Resource transport) {
- // TODO(juberti): impelement me
- return PP_FALSE;
+PP_Bool IsWritable(PP_Resource resource) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return BoolToPPBool((t.get()) ? t->IsWritable() : false);
}
-
-// TODO(juberti): other getters/setters
-// connect state
-// connect type, protocol
-// RTT
-
-
-// Establishes a connection to the remote peer.
-// Returns PP_ERROR_WOULDBLOCK and notifies on |cb|
-// when connectivity is established (or timeout occurs).
-int32_t Connect(PP_Resource transport,
- PP_CompletionCallback cb) {
- // TODO(juberti): impelement me
- return 0;
+int32_t Connect(PP_Resource resource, PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get()) ? t->Connect(callback) : PP_ERROR_BADRESOURCE;
}
-
-// Obtains another ICE candidate address to be provided
-// to the remote peer. Returns PP_ERROR_WOULDBLOCK
-// if there are no more addresses to be sent.
-int32_t GetNextAddress(PP_Resource transport,
- PP_Var* address,
- PP_CompletionCallback cb) {
- // TODO(juberti): implement me
- return 0;
+int32_t GetNextAddress(PP_Resource resource, PP_Var* address,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get())? t->GetNextAddress(address, callback) : PP_ERROR_BADRESOURCE;
}
-
-// Provides an ICE candidate address that was received
-// from the remote peer.
-int32_t ReceiveRemoteAddress(PP_Resource transport,
- PP_Var address) {
- // TODO(juberti): implement me
- return 0;
+int32_t ReceiveRemoteAddress(PP_Resource resource, PP_Var address) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get())? t->ReceiveRemoteAddress(address) : PP_ERROR_BADRESOURCE;
}
-
-// Like recv(), receives data. Returns PP_ERROR_WOULDBLOCK
-// if there is currently no data to receive.
-int32_t Recv(PP_Resource transport,
- void* data,
- uint32_t len,
- PP_CompletionCallback cb) {
- // TODO(juberti): implement me
- return 0;
+int32_t Recv(PP_Resource resource, void* data, uint32_t len,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get())? t->Recv(data, len, callback) : PP_ERROR_BADRESOURCE;
}
-
-// Like send(), sends data. Returns PP_ERROR_WOULDBLOCK
-// if the socket is currently flow-controlled.
-int32_t Send(PP_Resource transport,
- const void* data,
- uint32_t len,
- PP_CompletionCallback cb) {
- // TODO(juberti): implement me
- return 0;
+int32_t Send(PP_Resource resource, const void* data, uint32_t len,
+ PP_CompletionCallback callback) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get())? t->Send(data, len, callback) : PP_ERROR_BADRESOURCE;
}
-
// Disconnects from the remote peer.
-int32_t Close(PP_Resource transport) {
- // TODO(juberti): implement me
- return 0;
+int32_t Close(PP_Resource resource) {
+ scoped_refptr<PPB_Transport_Impl> t(
+ Resource::GetAs<PPB_Transport_Impl>(resource));
+ return (t.get())? t->Close() : PP_ERROR_BADRESOURCE;
}
-
const PPB_Transport_Dev ppb_transport = {
&CreateTransport,
&IsTransport,
@@ -119,16 +97,20 @@ const PPB_Transport_Dev ppb_transport = {
} // namespace
PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance)
- : Resource(instance) {
- // TODO(juberti): impl
+ : Resource(instance),
+ network_manager_(new talk_base::NetworkManager()),
+ allocator_(new cricket::HttpPortAllocator(network_manager_.get(), "")) {
+ std::vector<talk_base::SocketAddress> stun_hosts;
+ stun_hosts.push_back(talk_base::SocketAddress("stun.l.google.com", 19302));
+ allocator_->SetStunHosts(stun_hosts);
+ // TODO(sergeyu): Use port allocator that works inside sandbox.
}
-const PPB_Transport_Dev* PPB_Transport_Impl::GetInterface() {
- return &ppb_transport;
+PPB_Transport_Impl::~PPB_Transport_Impl() {
}
-PPB_Transport_Impl::~PPB_Transport_Impl() {
- // TODO(juberti): teardown
+const PPB_Transport_Dev* PPB_Transport_Impl::GetInterface() {
+ return &ppb_transport;
}
PPB_Transport_Impl* PPB_Transport_Impl::AsPPB_Transport_Impl() {
@@ -136,10 +118,149 @@ PPB_Transport_Impl* PPB_Transport_Impl::AsPPB_Transport_Impl() {
}
bool PPB_Transport_Impl::Init(const char* name, const char* proto) {
- // TODO(juberti): impl
+ // For now, always create http://www.google.com/transport/p2p .
+ channel_.reset(new cricket::P2PTransportChannel(
+ name, "", NULL, allocator_.get()));
+ channel_->SignalRequestSignaling.connect(
+ this, &PPB_Transport_Impl::OnRequestSignaling);
+ channel_->SignalWritableState.connect(
+ this, &PPB_Transport_Impl::OnWriteableState);
+ channel_->SignalCandidateReady.connect(
+ this, &PPB_Transport_Impl::OnCandidateReady);
+ channel_->SignalReadPacket.connect(
+ this, &PPB_Transport_Impl::OnReadPacket);
+ return true;
+}
+
+bool PPB_Transport_Impl::IsWritable() const {
+ return channel_->writable();
+}
+
+int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) {
+ // TODO(juberti): Fail if we're already connected.
+ if (connect_callback_.get() && !connect_callback_->completed())
+ return PP_ERROR_INPROGRESS;
+
+ channel_->Connect();
+
+ PP_Resource resource_id = GetReferenceNoAddRef();
+ CHECK(resource_id);
+ connect_callback_ = new TrackedCompletionCallback(
+ instance()->module()->GetCallbackTracker(), resource_id, callback);
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_Transport_Impl::GetNextAddress(PP_Var* address,
+ PP_CompletionCallback callback) {
+ if (next_address_callback_.get() && !next_address_callback_->completed())
+ return PP_ERROR_INPROGRESS;
+
+ if (!local_candidates_.empty()) {
+ Serialize(local_candidates_.front(), address);
+ local_candidates_.pop_front();
+ return PP_OK;
+ }
+
+ PP_Resource resource_id = GetReferenceNoAddRef();
+ CHECK(resource_id);
+ next_address_callback_ = new TrackedCompletionCallback(
+ instance()->module()->GetCallbackTracker(), resource_id, callback);
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_Transport_Impl::ReceiveRemoteAddress(PP_Var address) {
+ cricket::Candidate candidate;
+ if (!Deserialize(address, &candidate)) {
+ return PP_ERROR_FAILED;
+ }
+
+ channel_->OnCandidate(candidate);
+ return PP_OK;
+}
+
+int32_t PPB_Transport_Impl::Recv(void* data, uint32_t len,
+ PP_CompletionCallback callback) {
+ if (recv_callback_.get() && !recv_callback_->completed())
+ return PP_ERROR_INPROGRESS;
+
+ // TODO(juberti): Should we store packets that are received when
+ // no callback is installed?
+
+ recv_buffer_ = data;
+ recv_buffer_size_ = len;
+
+ PP_Resource resource_id = GetReferenceNoAddRef();
+ CHECK(resource_id);
+ recv_callback_ = new TrackedCompletionCallback(
+ instance()->module()->GetCallbackTracker(), resource_id, callback);
+ return PP_ERROR_WOULDBLOCK;
+}
+
+int32_t PPB_Transport_Impl::Send(const void* data, uint32_t len,
+ PP_CompletionCallback callback) {
+ return channel_->SendPacket(static_cast<const char*>(data), len);
+}
+
+int32_t PPB_Transport_Impl::Close() {
+ channel_->Reset();
+ instance()->module()->GetCallbackTracker()->AbortAll();
+ return PP_OK;
+}
+
+void PPB_Transport_Impl::OnRequestSignaling() {
+ channel_->OnSignalingReady();
+}
+
+void PPB_Transport_Impl::OnCandidateReady(
+ cricket::TransportChannelImpl* channel,
+ const cricket::Candidate& candidate) {
+ // Store the candidate first before calling the callback.
+ local_candidates_.push_back(candidate);
+
+ if (next_address_callback_.get() && next_address_callback_->completed()) {
+ scoped_refptr<TrackedCompletionCallback> callback;
+ callback.swap(next_address_callback_);
+ callback->Run(PP_OK);
+ }
+}
+
+void PPB_Transport_Impl::OnWriteableState(cricket::TransportChannel* channel) {
+ if (connect_callback_.get() && connect_callback_->completed()) {
+ scoped_refptr<TrackedCompletionCallback> callback;
+ callback.swap(connect_callback_);
+ callback->Run(PP_OK);
+ }
+}
+
+void PPB_Transport_Impl::OnReadPacket(cricket::TransportChannel* channel,
+ const char* data, size_t len) {
+ if (recv_callback_.get() && recv_callback_->completed()) {
+ scoped_refptr<TrackedCompletionCallback> callback;
+ callback.swap(recv_callback_);
+
+ if (len <= recv_buffer_size_) {
+ memcpy(recv_buffer_, data, len);
+ callback->Run(PP_OK);
+ } else {
+ callback->Run(PP_ERROR_FAILED);
+ }
+ }
+ // TODO(sergeyu): Buffer incoming packet if there is no pending read.
+}
+
+bool PPB_Transport_Impl::Serialize(const cricket::Candidate& candidate,
+ PP_Var* address) {
+ // TODO(juberti): Come up with a real wire format!
brettw 2011/02/14 23:16:39 We should release any existing value in the var he
Sergey Ulanov 2011/02/15 00:26:25 Done.
+ std::string blob = candidate.ToString();
+ *address = StringVar::StringToPPVar(instance()->module(), blob);
+ return true;
+}
+
+bool PPB_Transport_Impl::Deserialize(PP_Var address,
+ cricket::Candidate* candidate) {
+ // TODO(juberti): Implement this.
return false;
}
} // namespace ppapi
} // namespace webkit
-
« ppapi/cpp/dev/transport_dev.cc ('K') | « webkit/plugins/ppapi/ppb_transport_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698