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

Side by Side 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: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/plugins/ppapi/ppb_transport_impl.h" 5 #include "webkit/plugins/ppapi/ppb_transport_impl.h"
6 6
7 #include "base/singleton.h" 7 #include "ppapi/c/pp_completion_callback.h"
brettw 2011/02/10 07:19:16 Be sure the file list it alphabetized.
Sergey Ulanov 2011/02/10 21:14:54 Done.
8 #include "base/threading/thread_local.h" 8 #include "ppapi/c/pp_errors.h"
9 #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
10 #include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
9 #include "ppapi/c/dev/ppb_transport_dev.h" 11 #include "ppapi/c/dev/ppb_transport_dev.h"
10 #include "webkit/plugins/ppapi/common.h" 12 #include "webkit/plugins/ppapi/common.h"
11 #include "webkit/plugins/ppapi/plugin_module.h" 13 #include "webkit/plugins/ppapi/plugin_module.h"
12 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h" 14 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
15 #include "webkit/plugins/ppapi/var.h"
13 16
14 namespace webkit { 17 namespace webkit {
15 namespace ppapi { 18 namespace ppapi {
16 19
17 namespace { 20 namespace {
18 21
19 // Creates a new transport object with the specified name 22 PP_Resource CreateTransport(PP_Instance instance_id, const char* name,
20 // using the specified protocol.
21 PP_Resource CreateTransport(PP_Instance instance,
22 const char* name,
23 const char* proto) { 23 const char* proto) {
24 // TODO(juberti): implement me 24 PluginInstance* instance = ResourceTracker::Get()->GetInstance(instance_id);
25 PP_Resource p(0); 25 if (!instance)
26 return p; 26 return 0;
27
28 scoped_refptr<PPB_Transport_Impl> t(new PPB_Transport_Impl(instance));
29 if (!t->Init(name, proto))
30 return 0;
31
32 return t->GetReference();
27 } 33 }
28 34
29 // Returns whether or not resource is PPB_Transport_Impl
30 PP_Bool IsTransport(PP_Resource resource) { 35 PP_Bool IsTransport(PP_Resource resource) {
31 return BoolToPPBool(!!Resource::GetAs<PPB_Transport_Impl>(resource)); 36 return BoolToPPBool(Resource::GetAs<PPB_Transport_Impl>(resource) != NULL);
32 } 37 }
33 38
34 // Returns whether the transport is currently writable 39 PP_Bool IsWritable(PP_Resource resource) {
35 // (i.e. can send data to the remote peer) 40 scoped_refptr<PPB_Transport_Impl> t(
36 PP_Bool IsWritable(PP_Resource transport) { 41 Resource::GetAs<PPB_Transport_Impl>(resource));
37 // TODO(juberti): impelement me 42 return BoolToPPBool((t.get()) ? t->IsWritable() : false);
38 return PP_FALSE;
39 } 43 }
40 44
41 45 int32_t Connect(PP_Resource resource, PP_CompletionCallback callback) {
42 // TODO(juberti): other getters/setters 46 scoped_refptr<PPB_Transport_Impl> t(
43 // connect state 47 Resource::GetAs<PPB_Transport_Impl>(resource));
44 // connect type, protocol 48 return (t.get()) ? t->Connect(callback) : PP_ERROR_BADRESOURCE;
45 // RTT
46
47
48 // Establishes a connection to the remote peer.
49 // Returns PP_ERROR_WOULDBLOCK and notifies on |cb|
50 // when connectivity is established (or timeout occurs).
51 int32_t Connect(PP_Resource transport,
52 PP_CompletionCallback cb) {
53 // TODO(juberti): impelement me
54 return 0;
55 } 49 }
56 50
57 51 int32_t GetNextAddress(PP_Resource resource, PP_Var* address,
brettw 2011/02/10 07:19:16 I was a little unclear about how this is supposed
Sergey Ulanov 2011/02/10 21:14:54 FileIO API uses exactly the same approach (see PPB
brettw 2011/02/14 17:13:58 Yes, I think this makes sense for reading since we
Sergey Ulanov 2011/02/14 22:22:55 Yes, I seen now. Thanks for explaining it. I've al
58 // Obtains another ICE candidate address to be provided 52 PP_CompletionCallback callback) {
59 // to the remote peer. Returns PP_ERROR_WOULDBLOCK 53 scoped_refptr<PPB_Transport_Impl> t(
60 // if there are no more addresses to be sent. 54 Resource::GetAs<PPB_Transport_Impl>(resource));
61 int32_t GetNextAddress(PP_Resource transport, 55 return (t.get())? t->GetNextAddress(address, callback) : PP_ERROR_BADRESOURCE;
62 PP_Var* address,
63 PP_CompletionCallback cb) {
64 // TODO(juberti): implement me
65 return 0;
66 } 56 }
67 57
68 58 int32_t ReceiveRemoteAddress(PP_Resource resource, PP_Var address) {
69 // Provides an ICE candidate address that was received 59 scoped_refptr<PPB_Transport_Impl> t(
70 // from the remote peer. 60 Resource::GetAs<PPB_Transport_Impl>(resource));
71 int32_t ReceiveRemoteAddress(PP_Resource transport, 61 return (t.get())? t->ReceiveRemoteAddress(address) : PP_ERROR_BADRESOURCE;
72 PP_Var address) {
73 // TODO(juberti): implement me
74 return 0;
75 } 62 }
76 63
77 64 int32_t Recv(PP_Resource resource, void* data, uint32_t len,
78 // Like recv(), receives data. Returns PP_ERROR_WOULDBLOCK 65 PP_CompletionCallback callback) {
79 // if there is currently no data to receive. 66 scoped_refptr<PPB_Transport_Impl> t(
80 int32_t Recv(PP_Resource transport, 67 Resource::GetAs<PPB_Transport_Impl>(resource));
81 void* data, 68 return (t.get())? t->Recv(data, len, callback) : PP_ERROR_BADRESOURCE;
82 uint32_t len,
83 PP_CompletionCallback cb) {
84 // TODO(juberti): implement me
85 return 0;
86 } 69 }
87 70
88 71 int32_t Send(PP_Resource resource, const void* data, uint32_t len,
89 // Like send(), sends data. Returns PP_ERROR_WOULDBLOCK 72 PP_CompletionCallback callback) {
90 // if the socket is currently flow-controlled. 73 scoped_refptr<PPB_Transport_Impl> t(
91 int32_t Send(PP_Resource transport, 74 Resource::GetAs<PPB_Transport_Impl>(resource));
92 const void* data, 75 return (t.get())? t->Send(data, len, callback) : PP_ERROR_BADRESOURCE;
93 uint32_t len,
94 PP_CompletionCallback cb) {
95 // TODO(juberti): implement me
96 return 0;
97 } 76 }
98 77
99
100 // Disconnects from the remote peer. 78 // Disconnects from the remote peer.
101 int32_t Close(PP_Resource transport) { 79 int32_t Close(PP_Resource resource) {
102 // TODO(juberti): implement me 80 scoped_refptr<PPB_Transport_Impl> t(
103 return 0; 81 Resource::GetAs<PPB_Transport_Impl>(resource));
82 return (t.get())? t->Close() : PP_ERROR_BADRESOURCE;
104 } 83 }
105 84
106
107 const PPB_Transport_Dev ppb_transport = { 85 const PPB_Transport_Dev ppb_transport = {
108 &CreateTransport, 86 &CreateTransport,
109 &IsTransport, 87 &IsTransport,
110 &IsWritable, 88 &IsWritable,
111 &Connect, 89 &Connect,
112 &GetNextAddress, 90 &GetNextAddress,
113 &ReceiveRemoteAddress, 91 &ReceiveRemoteAddress,
114 &Recv, 92 &Recv,
115 &Send, 93 &Send,
116 &Close, 94 &Close,
117 }; 95 };
118 96
119 } // namespace 97 } // namespace
120 98
121 PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance) 99 PPB_Transport_Impl::PPB_Transport_Impl(PluginInstance* instance)
122 : Resource(instance) { 100 : Resource(instance),
123 // TODO(juberti): impl 101 network_manager_(new talk_base::NetworkManager()),
102 allocator_(new cricket::HttpPortAllocator(network_manager_.get(), "")) {
103 std::vector<talk_base::SocketAddress> stun_hosts;
104 stun_hosts.push_back(talk_base::SocketAddress("stun.l.google.com", 19302));
105 allocator_->SetStunHosts(stun_hosts);
106 // TODO(sergeyu): Use port allocator that works inside sandbox.
107 }
108
109 PPB_Transport_Impl::~PPB_Transport_Impl() {
124 } 110 }
125 111
126 const PPB_Transport_Dev* PPB_Transport_Impl::GetInterface() { 112 const PPB_Transport_Dev* PPB_Transport_Impl::GetInterface() {
127 return &ppb_transport; 113 return &ppb_transport;
128 } 114 }
129 115
130 PPB_Transport_Impl::~PPB_Transport_Impl() {
131 // TODO(juberti): teardown
132 }
133
134 PPB_Transport_Impl* PPB_Transport_Impl::AsPPB_Transport_Impl() { 116 PPB_Transport_Impl* PPB_Transport_Impl::AsPPB_Transport_Impl() {
135 return this; 117 return this;
136 } 118 }
137 119
138 bool PPB_Transport_Impl::Init(const char* name, const char* proto) { 120 bool PPB_Transport_Impl::Init(const char* name, const char* proto) {
139 // TODO(juberti): impl 121 // For now, always create http://www.google.com/transport/p2p .
122 channel_.reset(new cricket::P2PTransportChannel(
123 name, "", NULL, allocator_.get()));
124 channel_->SignalRequestSignaling.connect(
125 this, &PPB_Transport_Impl::OnRequestSignaling);
126 channel_->SignalWritableState.connect(
127 this, &PPB_Transport_Impl::OnWriteableState);
128 channel_->SignalCandidateReady.connect(
129 this, &PPB_Transport_Impl::OnCandidateReady);
130 channel_->SignalReadPacket.connect(
131 this, &PPB_Transport_Impl::OnReadPacket);
132 return true;
133 }
134
135 bool PPB_Transport_Impl::IsWritable() const {
136 return channel_->writable();
137 }
138
139 int32_t PPB_Transport_Impl::Connect(PP_CompletionCallback callback) {
140 // TODO(juberti): Fail if we're already connected.
141 if (connect_callback_.get() && !connect_callback_->completed())
142 return PP_ERROR_INPROGRESS;
143
144 channel_->Connect();
145
146 PP_Resource resource_id = GetReferenceNoAddRef();
147 CHECK(resource_id);
148 connect_callback_ = new TrackedCompletionCallback(
149 instance()->module()->GetCallbackTracker(), resource_id, callback);
150 return PP_ERROR_WOULDBLOCK;
151 }
152
153 int32_t PPB_Transport_Impl::GetNextAddress(PP_Var* address,
154 PP_CompletionCallback callback) {
155 if (next_address_callback_.get() && !next_address_callback_->completed())
156 return PP_ERROR_INPROGRESS;
157
158 if (!local_candidates_.empty()) {
159 Serialize(local_candidates_.front(), address);
160 local_candidates_.pop_front();
161 return PP_OK;
162 }
163
164 next_address_ = address;
165
166 PP_Resource resource_id = GetReferenceNoAddRef();
167 CHECK(resource_id);
168 next_address_callback_ = new TrackedCompletionCallback(
169 instance()->module()->GetCallbackTracker(), resource_id, callback);
170 return PP_ERROR_WOULDBLOCK;
171 }
172
173 int32_t PPB_Transport_Impl::ReceiveRemoteAddress(PP_Var address) {
174 cricket::Candidate candidate;
175 if (!Deserialize(address, &candidate)) {
176 return PP_ERROR_FAILED;
177 }
178
179 channel_->OnCandidate(candidate);
180 return PP_OK;
181 }
182
183 int32_t PPB_Transport_Impl::Recv(void* data, uint32_t len,
184 PP_CompletionCallback callback) {
185 if (recv_callback_.get() && !recv_callback_->completed())
186 return PP_ERROR_INPROGRESS;
187
188 // TODO(juberti): Should we store packets that are received when
189 // no callback is installed?
190
191 recv_buffer_ = data;
brettw 2011/02/10 07:19:16 This has the same problem as GetNextAddress with r
Sergey Ulanov 2011/02/10 21:14:54 We do have Close() in this interface. I've added l
192 recv_buffer_size_ = len;
193
194 PP_Resource resource_id = GetReferenceNoAddRef();
195 CHECK(resource_id);
196 recv_callback_ = new TrackedCompletionCallback(
197 instance()->module()->GetCallbackTracker(), resource_id, callback);
198 return PP_ERROR_WOULDBLOCK;
199 }
200
201 int32_t PPB_Transport_Impl::Send(const void* data, uint32_t len,
202 PP_CompletionCallback callback) {
203 return channel_->SendPacket(static_cast<const char*>(data), len);
204 }
205
206 int32_t PPB_Transport_Impl::Close() {
207 channel_->Reset();
208 return PP_OK;
209 }
210
211 void PPB_Transport_Impl::OnRequestSignaling() {
212 channel_->OnSignalingReady();
213 }
214
215 void PPB_Transport_Impl::OnCandidateReady(
216 cricket::TransportChannelImpl* channel,
217 const cricket::Candidate& candidate) {
218 if (next_address_callback_.get() && next_address_callback_->completed()) {
219 scoped_refptr<TrackedCompletionCallback> callback;
220 callback.swap(next_address_callback_);
221 Serialize(candidate, next_address_);
222 callback->Run(PP_OK);
223 } else {
224 local_candidates_.push_back(candidate);
225 }
226 }
227
228 void PPB_Transport_Impl::OnWriteableState(cricket::TransportChannel* channel) {
229 if (connect_callback_.get() && connect_callback_->completed()) {
230 scoped_refptr<TrackedCompletionCallback> callback;
231 callback.swap(connect_callback_);
232 callback->Run(PP_OK);
233 }
234 }
235
236 void PPB_Transport_Impl::OnReadPacket(cricket::TransportChannel* channel,
237 const char* data, size_t len) {
238 if (recv_callback_.get() && recv_callback_->completed()) {
239 scoped_refptr<TrackedCompletionCallback> callback;
240 callback.swap(recv_callback_);
241
242 if (len <= recv_buffer_size_) {
243 memcpy(recv_buffer_, data, len);
244 callback->Run(PP_OK);
245 } else {
246 callback->Run(PP_ERROR_FAILED);
247 }
248 }
249 // TODO(sergeyu): Buffer incoming packet if there is no pending read.
250 }
251
252 bool PPB_Transport_Impl::Serialize(const cricket::Candidate& candidate,
253 PP_Var* address) {
254 // TODO(juberti): Come up with a real wire format!
255 std::string blob = candidate.ToString();
256 *address = StringVar::StringToPPVar(instance()->module(), blob);
257 return true;
258 }
259
260 bool PPB_Transport_Impl::Deserialize(PP_Var address,
261 cricket::Candidate* candidate) {
262 // TODO(juberti): Implement this.
140 return false; 263 return false;
141 } 264 }
142 265
143 } // namespace ppapi 266 } // namespace ppapi
144 } // namespace webkit 267 } // namespace webkit
145
OLDNEW
« ppapi/tests/test_transport.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