OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/renderer_host/pepper/pepper_udp_socket.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/compiler_specific.h" | |
10 #include "base/logging.h" | |
11 #include "content/browser/renderer_host/pepper/pepper_message_filter.h" | |
12 #include "content/public/browser/browser_thread.h" | |
13 #include "net/base/io_buffer.h" | |
14 #include "net/base/net_errors.h" | |
15 #include "net/udp/udp_server_socket.h" | |
16 #include "ppapi/proxy/ppapi_messages.h" | |
17 #include "ppapi/shared_impl/private/net_address_private_impl.h" | |
18 #include "ppapi/shared_impl/private/udp_socket_private_impl.h" | |
19 | |
20 using ppapi::NetAddressPrivateImpl; | |
21 | |
22 namespace content { | |
23 | |
24 PepperUDPSocket::PepperUDPSocket( | |
25 PepperMessageFilter* manager, | |
26 int32 routing_id, | |
27 uint32 plugin_dispatcher_id, | |
28 uint32 socket_id) | |
29 : manager_(manager), | |
30 routing_id_(routing_id), | |
31 plugin_dispatcher_id_(plugin_dispatcher_id), | |
32 socket_id_(socket_id), | |
33 allow_address_reuse_(false), | |
34 allow_broadcast_(false) { | |
35 DCHECK(manager); | |
36 } | |
37 | |
38 PepperUDPSocket::~PepperUDPSocket() { | |
39 // Make sure there are no further callbacks from socket_. | |
40 if (socket_.get()) | |
41 socket_->Close(); | |
42 } | |
43 | |
44 void PepperUDPSocket::AllowAddressReuse(bool value) { | |
45 allow_address_reuse_ = value; | |
46 } | |
47 | |
48 void PepperUDPSocket::AllowBroadcast(bool value) { | |
49 allow_broadcast_ = value; | |
50 } | |
51 | |
52 void PepperUDPSocket::Bind(const PP_NetAddress_Private& addr) { | |
53 socket_.reset(new net::UDPServerSocket(NULL, net::NetLog::Source())); | |
54 | |
55 net::IPAddressNumber address; | |
56 int port; | |
57 if (!socket_.get() || | |
58 !NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { | |
59 SendBindACKError(); | |
60 return; | |
61 } | |
62 | |
63 if (allow_address_reuse_) | |
64 socket_->AllowAddressReuse(); | |
65 if (allow_broadcast_) | |
66 socket_->AllowBroadcast(); | |
67 | |
68 int result = socket_->Listen(net::IPEndPoint(address, port)); | |
69 | |
70 if (result == net::OK && | |
71 socket_->GetLocalAddress(&bound_address_) != net::OK) { | |
72 SendBindACKError(); | |
73 return; | |
74 } | |
75 | |
76 OnBindCompleted(result); | |
77 } | |
78 | |
79 void PepperUDPSocket::RecvFrom(int32_t num_bytes) { | |
80 if (recvfrom_buffer_.get() || num_bytes < 0) { | |
81 SendRecvFromACKError(); | |
82 return; | |
83 } | |
84 | |
85 if (num_bytes > ppapi::UDPSocketPrivateImpl::kMaxReadSize) { | |
86 NOTREACHED(); | |
87 num_bytes = ppapi::UDPSocketPrivateImpl::kMaxReadSize; | |
88 } | |
89 | |
90 recvfrom_buffer_ = new net::IOBuffer(num_bytes); | |
91 int result = socket_->RecvFrom( | |
92 recvfrom_buffer_, num_bytes, &recvfrom_address_, | |
93 base::Bind(&PepperUDPSocket::OnRecvFromCompleted, | |
94 base::Unretained(this))); | |
95 | |
96 if (result != net::ERR_IO_PENDING) | |
97 OnRecvFromCompleted(result); | |
98 } | |
99 | |
100 void PepperUDPSocket::SendTo(const std::string& data, | |
101 const PP_NetAddress_Private& addr) { | |
102 if (sendto_buffer_.get() || data.empty()) { | |
103 SendSendToACKError(); | |
104 return; | |
105 } | |
106 | |
107 net::IPAddressNumber address; | |
108 int port; | |
109 if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) { | |
110 SendSendToACKError(); | |
111 return; | |
112 } | |
113 | |
114 int data_size = data.size(); | |
115 if (data_size > ppapi::UDPSocketPrivateImpl::kMaxWriteSize) { | |
116 NOTREACHED(); | |
117 data_size = ppapi::UDPSocketPrivateImpl::kMaxWriteSize; | |
118 } | |
119 | |
120 sendto_buffer_ = new net::IOBuffer(data_size); | |
121 memcpy(sendto_buffer_->data(), data.data(), data_size); | |
122 int result = socket_->SendTo( | |
123 sendto_buffer_, data_size, net::IPEndPoint(address, port), | |
124 base::Bind(&PepperUDPSocket::OnSendToCompleted, base::Unretained(this))); | |
125 | |
126 if (result != net::ERR_IO_PENDING) | |
127 OnSendToCompleted(result); | |
128 } | |
129 | |
130 void PepperUDPSocket::SendRecvFromACKError() { | |
131 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
132 manager_->Send(new PpapiMsg_PPBUDPSocket_RecvFromACK( | |
133 routing_id_, plugin_dispatcher_id_, socket_id_, false, std::string(), | |
134 addr)); | |
135 } | |
136 | |
137 void PepperUDPSocket::SendSendToACKError() { | |
138 manager_->Send(new PpapiMsg_PPBUDPSocket_SendToACK( | |
139 routing_id_, plugin_dispatcher_id_, socket_id_, false, 0)); | |
140 } | |
141 | |
142 void PepperUDPSocket::SendBindACKError() { | |
143 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
144 manager_->Send(new PpapiMsg_PPBUDPSocket_BindACK( | |
145 routing_id_, plugin_dispatcher_id_, socket_id_, false, addr)); | |
146 } | |
147 | |
148 void PepperUDPSocket::OnBindCompleted(int result) { | |
149 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
150 if (result < 0 || | |
151 !NetAddressPrivateImpl::IPEndPointToNetAddress(bound_address_.address(), | |
152 bound_address_.port(), | |
153 &addr)) { | |
154 SendBindACKError(); | |
155 } else { | |
156 manager_->Send(new PpapiMsg_PPBUDPSocket_BindACK( | |
157 routing_id_, plugin_dispatcher_id_, socket_id_, true, addr)); | |
158 } | |
159 } | |
160 | |
161 void PepperUDPSocket::OnRecvFromCompleted(int result) { | |
162 DCHECK(recvfrom_buffer_.get()); | |
163 | |
164 // Convert IPEndPoint we get back from RecvFrom to a PP_NetAddress_Private, | |
165 // to send back. | |
166 PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress; | |
167 if (result < 0 || | |
168 !NetAddressPrivateImpl::IPEndPointToNetAddress( | |
169 recvfrom_address_.address(), | |
170 recvfrom_address_.port(), | |
171 &addr)) { | |
172 SendRecvFromACKError(); | |
173 } else { | |
174 manager_->Send(new PpapiMsg_PPBUDPSocket_RecvFromACK( | |
175 routing_id_, plugin_dispatcher_id_, socket_id_, true, | |
176 std::string(recvfrom_buffer_->data(), result), addr)); | |
177 } | |
178 | |
179 recvfrom_buffer_ = NULL; | |
180 } | |
181 | |
182 void PepperUDPSocket::OnSendToCompleted(int result) { | |
183 DCHECK(sendto_buffer_.get()); | |
184 | |
185 if (result < 0) { | |
186 SendSendToACKError(); | |
187 } else { | |
188 manager_->Send(new PpapiMsg_PPBUDPSocket_SendToACK( | |
189 routing_id_, plugin_dispatcher_id_, socket_id_, true, result)); | |
190 } | |
191 | |
192 sendto_buffer_ = NULL; | |
193 } | |
194 | |
195 } // namespace content | |
OLD | NEW |