OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/extensions/api/socket/udp_socket.h" | 5 #include "extensions/browser/api/socket/udp_socket.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "chrome/browser/extensions/api/api_resource.h" | 9 #include "chrome/browser/extensions/api/api_resource.h" |
10 #include "net/base/ip_endpoint.h" | 10 #include "net/base/ip_endpoint.h" |
11 #include "net/base/net_errors.h" | 11 #include "net/base/net_errors.h" |
12 #include "net/udp/datagram_socket.h" | 12 #include "net/udp/datagram_socket.h" |
13 #include "net/udp/udp_client_socket.h" | 13 #include "net/udp/udp_client_socket.h" |
14 | 14 |
15 namespace extensions { | 15 namespace extensions { |
16 | 16 |
17 static base::LazyInstance< | 17 static base::LazyInstance< |
18 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> > > | 18 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> > > |
19 g_factory = LAZY_INSTANCE_INITIALIZER; | 19 g_factory = LAZY_INSTANCE_INITIALIZER; |
20 | 20 |
21 // static | 21 // static |
22 template <> | 22 template <> |
23 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> >* | 23 BrowserContextKeyedAPIFactory<ApiResourceManager<ResumableUDPSocket> >* |
24 ApiResourceManager<ResumableUDPSocket>::GetFactoryInstance() { | 24 ApiResourceManager<ResumableUDPSocket>::GetFactoryInstance() { |
25 return g_factory.Pointer(); | 25 return g_factory.Pointer(); |
26 } | 26 } |
27 | 27 |
28 UDPSocket::UDPSocket(const std::string& owner_extension_id) | 28 UDPSocket::UDPSocket(const std::string& owner_extension_id) |
29 : Socket(owner_extension_id), | 29 : Socket(owner_extension_id), |
30 socket_(net::DatagramSocket::DEFAULT_BIND, | 30 socket_(net::DatagramSocket::DEFAULT_BIND, |
31 net::RandIntCallback(), | 31 net::RandIntCallback(), |
32 NULL, | 32 NULL, |
33 net::NetLog::Source()) { | 33 net::NetLog::Source()) {} |
34 } | |
35 | 34 |
36 UDPSocket::~UDPSocket() { | 35 UDPSocket::~UDPSocket() { Disconnect(); } |
37 Disconnect(); | |
38 } | |
39 | 36 |
40 void UDPSocket::Connect(const std::string& address, | 37 void UDPSocket::Connect(const std::string& address, |
41 int port, | 38 int port, |
42 const CompletionCallback& callback) { | 39 const CompletionCallback& callback) { |
43 int result = net::ERR_CONNECTION_FAILED; | 40 int result = net::ERR_CONNECTION_FAILED; |
44 do { | 41 do { |
45 if (is_connected_) | 42 if (is_connected_) |
46 break; | 43 break; |
47 | 44 |
48 net::IPEndPoint ip_end_point; | 45 net::IPEndPoint ip_end_point; |
(...skipping 22 matching lines...) Expand all Loading... |
71 | 68 |
72 void UDPSocket::Disconnect() { | 69 void UDPSocket::Disconnect() { |
73 is_connected_ = false; | 70 is_connected_ = false; |
74 socket_.Close(); | 71 socket_.Close(); |
75 read_callback_.Reset(); | 72 read_callback_.Reset(); |
76 recv_from_callback_.Reset(); | 73 recv_from_callback_.Reset(); |
77 send_to_callback_.Reset(); | 74 send_to_callback_.Reset(); |
78 multicast_groups_.clear(); | 75 multicast_groups_.clear(); |
79 } | 76 } |
80 | 77 |
81 void UDPSocket::Read(int count, | 78 void UDPSocket::Read(int count, const ReadCompletionCallback& callback) { |
82 const ReadCompletionCallback& callback) { | |
83 DCHECK(!callback.is_null()); | 79 DCHECK(!callback.is_null()); |
84 | 80 |
85 if (!read_callback_.is_null()) { | 81 if (!read_callback_.is_null()) { |
86 callback.Run(net::ERR_IO_PENDING, NULL); | 82 callback.Run(net::ERR_IO_PENDING, NULL); |
87 return; | 83 return; |
88 } else { | 84 } else { |
89 read_callback_ = callback; | 85 read_callback_ = callback; |
90 } | 86 } |
91 | 87 |
92 int result = net::ERR_FAILED; | 88 int result = net::ERR_FAILED; |
93 scoped_refptr<net::IOBuffer> io_buffer; | 89 scoped_refptr<net::IOBuffer> io_buffer; |
94 do { | 90 do { |
95 if (count < 0) { | 91 if (count < 0) { |
96 result = net::ERR_INVALID_ARGUMENT; | 92 result = net::ERR_INVALID_ARGUMENT; |
97 break; | 93 break; |
98 } | 94 } |
99 | 95 |
100 if (!socket_.is_connected()) { | 96 if (!socket_.is_connected()) { |
101 result = net::ERR_SOCKET_NOT_CONNECTED; | 97 result = net::ERR_SOCKET_NOT_CONNECTED; |
102 break; | 98 break; |
103 } | 99 } |
104 | 100 |
105 io_buffer = new net::IOBuffer(count); | 101 io_buffer = new net::IOBuffer(count); |
106 result = socket_.Read(io_buffer.get(), count, | 102 result = socket_.Read( |
107 base::Bind(&UDPSocket::OnReadComplete, base::Unretained(this), | 103 io_buffer.get(), |
108 io_buffer)); | 104 count, |
| 105 base::Bind( |
| 106 &UDPSocket::OnReadComplete, base::Unretained(this), io_buffer)); |
109 } while (false); | 107 } while (false); |
110 | 108 |
111 if (result != net::ERR_IO_PENDING) | 109 if (result != net::ERR_IO_PENDING) |
112 OnReadComplete(io_buffer, result); | 110 OnReadComplete(io_buffer, result); |
113 } | 111 } |
114 | 112 |
115 int UDPSocket::WriteImpl(net::IOBuffer* io_buffer, | 113 int UDPSocket::WriteImpl(net::IOBuffer* io_buffer, |
116 int io_buffer_size, | 114 int io_buffer_size, |
117 const net::CompletionCallback& callback) { | 115 const net::CompletionCallback& callback) { |
118 if (!socket_.is_connected()) | 116 if (!socket_.is_connected()) |
(...skipping 22 matching lines...) Expand all Loading... |
141 break; | 139 break; |
142 } | 140 } |
143 | 141 |
144 if (!socket_.is_connected()) { | 142 if (!socket_.is_connected()) { |
145 result = net::ERR_SOCKET_NOT_CONNECTED; | 143 result = net::ERR_SOCKET_NOT_CONNECTED; |
146 break; | 144 break; |
147 } | 145 } |
148 | 146 |
149 io_buffer = new net::IOBuffer(count); | 147 io_buffer = new net::IOBuffer(count); |
150 address = new IPEndPoint(); | 148 address = new IPEndPoint(); |
151 result = socket_.RecvFrom( | 149 result = socket_.RecvFrom(io_buffer.get(), |
152 io_buffer.get(), | 150 count, |
153 count, | 151 &address->data, |
154 &address->data, | 152 base::Bind(&UDPSocket::OnRecvFromComplete, |
155 base::Bind(&UDPSocket::OnRecvFromComplete, | 153 base::Unretained(this), |
156 base::Unretained(this), | 154 io_buffer, |
157 io_buffer, | 155 address)); |
158 address)); | |
159 } while (false); | 156 } while (false); |
160 | 157 |
161 if (result != net::ERR_IO_PENDING) | 158 if (result != net::ERR_IO_PENDING) |
162 OnRecvFromComplete(io_buffer, address, result); | 159 OnRecvFromComplete(io_buffer, address, result); |
163 } | 160 } |
164 | 161 |
165 void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, | 162 void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, |
166 int byte_count, | 163 int byte_count, |
167 const std::string& address, | 164 const std::string& address, |
168 int port, | 165 int port, |
169 const CompletionCallback& callback) { | 166 const CompletionCallback& callback) { |
170 DCHECK(!callback.is_null()); | 167 DCHECK(!callback.is_null()); |
171 | 168 |
172 if (!send_to_callback_.is_null()) { | 169 if (!send_to_callback_.is_null()) { |
173 // TODO(penghuang): Put requests in a pending queue to support multiple | 170 // TODO(penghuang): Put requests in a pending queue to support multiple |
174 // sendTo calls. | 171 // sendTo calls. |
175 callback.Run(net::ERR_IO_PENDING); | 172 callback.Run(net::ERR_IO_PENDING); |
176 return; | 173 return; |
177 } else { | 174 } else { |
178 send_to_callback_ = callback; | 175 send_to_callback_ = callback; |
179 } | 176 } |
180 | 177 |
181 int result = net::ERR_FAILED; | 178 int result = net::ERR_FAILED; |
182 do { | 179 do { |
183 net::IPEndPoint ip_end_point; | 180 net::IPEndPoint ip_end_point; |
184 if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) { | 181 if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) { |
185 result = net::ERR_ADDRESS_INVALID; | 182 result = net::ERR_ADDRESS_INVALID; |
186 break; | 183 break; |
187 } | 184 } |
188 | 185 |
189 if (!socket_.is_connected()) { | 186 if (!socket_.is_connected()) { |
190 result = net::ERR_SOCKET_NOT_CONNECTED; | 187 result = net::ERR_SOCKET_NOT_CONNECTED; |
191 break; | 188 break; |
192 } | 189 } |
193 | 190 |
194 result = socket_.SendTo( | 191 result = socket_.SendTo( |
195 io_buffer.get(), | 192 io_buffer.get(), |
196 byte_count, | 193 byte_count, |
197 ip_end_point, | 194 ip_end_point, |
198 base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this))); | 195 base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this))); |
199 } while (false); | 196 } while (false); |
200 | 197 |
201 if (result != net::ERR_IO_PENDING) | 198 if (result != net::ERR_IO_PENDING) |
202 OnSendToComplete(result); | 199 OnSendToComplete(result); |
203 } | 200 } |
204 | 201 |
205 bool UDPSocket::IsConnected() { | 202 bool UDPSocket::IsConnected() { return is_connected_; } |
206 return is_connected_; | |
207 } | |
208 | 203 |
209 bool UDPSocket::GetPeerAddress(net::IPEndPoint* address) { | 204 bool UDPSocket::GetPeerAddress(net::IPEndPoint* address) { |
210 return !socket_.GetPeerAddress(address); | 205 return !socket_.GetPeerAddress(address); |
211 } | 206 } |
212 | 207 |
213 bool UDPSocket::GetLocalAddress(net::IPEndPoint* address) { | 208 bool UDPSocket::GetLocalAddress(net::IPEndPoint* address) { |
214 return !socket_.GetLocalAddress(address); | 209 return !socket_.GetLocalAddress(address); |
215 } | 210 } |
216 | 211 |
217 Socket::SocketType UDPSocket::GetSocketType() const { | 212 Socket::SocketType UDPSocket::GetSocketType() const { return Socket::TYPE_UDP; } |
218 return Socket::TYPE_UDP; | |
219 } | |
220 | 213 |
221 void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, | 214 void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, |
222 int result) { | 215 int result) { |
223 DCHECK(!read_callback_.is_null()); | 216 DCHECK(!read_callback_.is_null()); |
224 read_callback_.Run(result, io_buffer); | 217 read_callback_.Run(result, io_buffer); |
225 read_callback_.Reset(); | 218 read_callback_.Reset(); |
226 } | 219 } |
227 | 220 |
228 void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer, | 221 void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer, |
229 scoped_refptr<IPEndPoint> address, | 222 scoped_refptr<IPEndPoint> address, |
230 int result) { | 223 int result) { |
231 DCHECK(!recv_from_callback_.is_null()); | 224 DCHECK(!recv_from_callback_.is_null()); |
232 std::string ip; | 225 std::string ip; |
233 int port = 0; | 226 int port = 0; |
234 if (result > 0 && address.get()) { | 227 if (result > 0 && address.get()) { |
235 IPEndPointToStringAndPort(address->data, &ip, &port); | 228 IPEndPointToStringAndPort(address->data, &ip, &port); |
236 } | 229 } |
237 recv_from_callback_.Run(result, io_buffer, ip, port); | 230 recv_from_callback_.Run(result, io_buffer, ip, port); |
238 recv_from_callback_.Reset(); | 231 recv_from_callback_.Reset(); |
239 } | 232 } |
240 | 233 |
241 void UDPSocket::OnSendToComplete(int result) { | 234 void UDPSocket::OnSendToComplete(int result) { |
242 DCHECK(!send_to_callback_.is_null()); | 235 DCHECK(!send_to_callback_.is_null()); |
243 send_to_callback_.Run(result); | 236 send_to_callback_.Run(result); |
244 send_to_callback_.Reset(); | 237 send_to_callback_.Reset(); |
245 } | 238 } |
246 | 239 |
247 bool UDPSocket::IsBound() { | 240 bool UDPSocket::IsBound() { return socket_.is_connected(); } |
248 return socket_.is_connected(); | |
249 } | |
250 | 241 |
251 int UDPSocket::JoinGroup(const std::string& address) { | 242 int UDPSocket::JoinGroup(const std::string& address) { |
252 net::IPAddressNumber ip; | 243 net::IPAddressNumber ip; |
253 if (!net::ParseIPLiteralToNumber(address, &ip)) | 244 if (!net::ParseIPLiteralToNumber(address, &ip)) |
254 return net::ERR_ADDRESS_INVALID; | 245 return net::ERR_ADDRESS_INVALID; |
255 | 246 |
256 std::string normalized_address = net::IPAddressToString(ip); | 247 std::string normalized_address = net::IPAddressToString(ip); |
257 std::vector<std::string>::iterator find_result = | 248 std::vector<std::string>::iterator find_result = std::find( |
258 std::find(multicast_groups_.begin(), | 249 multicast_groups_.begin(), multicast_groups_.end(), normalized_address); |
259 multicast_groups_.end(), | |
260 normalized_address); | |
261 if (find_result != multicast_groups_.end()) | 250 if (find_result != multicast_groups_.end()) |
262 return net::ERR_ADDRESS_INVALID; | 251 return net::ERR_ADDRESS_INVALID; |
263 | 252 |
264 int rv = socket_.JoinGroup(ip); | 253 int rv = socket_.JoinGroup(ip); |
265 if (rv == 0) | 254 if (rv == 0) |
266 multicast_groups_.push_back(normalized_address); | 255 multicast_groups_.push_back(normalized_address); |
267 return rv; | 256 return rv; |
268 } | 257 } |
269 | 258 |
270 int UDPSocket::LeaveGroup(const std::string& address) { | 259 int UDPSocket::LeaveGroup(const std::string& address) { |
271 net::IPAddressNumber ip; | 260 net::IPAddressNumber ip; |
272 if (!net::ParseIPLiteralToNumber(address, &ip)) | 261 if (!net::ParseIPLiteralToNumber(address, &ip)) |
273 return net::ERR_ADDRESS_INVALID; | 262 return net::ERR_ADDRESS_INVALID; |
274 | 263 |
275 std::string normalized_address = net::IPAddressToString(ip); | 264 std::string normalized_address = net::IPAddressToString(ip); |
276 std::vector<std::string>::iterator find_result = | 265 std::vector<std::string>::iterator find_result = std::find( |
277 std::find(multicast_groups_.begin(), | 266 multicast_groups_.begin(), multicast_groups_.end(), normalized_address); |
278 multicast_groups_.end(), | |
279 normalized_address); | |
280 if (find_result == multicast_groups_.end()) | 267 if (find_result == multicast_groups_.end()) |
281 return net::ERR_ADDRESS_INVALID; | 268 return net::ERR_ADDRESS_INVALID; |
282 | 269 |
283 int rv = socket_.LeaveGroup(ip); | 270 int rv = socket_.LeaveGroup(ip); |
284 if (rv == 0) | 271 if (rv == 0) |
285 multicast_groups_.erase(find_result); | 272 multicast_groups_.erase(find_result); |
286 return rv; | 273 return rv; |
287 } | 274 } |
288 | 275 |
289 int UDPSocket::SetMulticastTimeToLive(int ttl) { | 276 int UDPSocket::SetMulticastTimeToLive(int ttl) { |
290 return socket_.SetMulticastTimeToLive(ttl); | 277 return socket_.SetMulticastTimeToLive(ttl); |
291 } | 278 } |
292 | 279 |
293 int UDPSocket::SetMulticastLoopbackMode(bool loopback) { | 280 int UDPSocket::SetMulticastLoopbackMode(bool loopback) { |
294 return socket_.SetMulticastLoopbackMode(loopback); | 281 return socket_.SetMulticastLoopbackMode(loopback); |
295 } | 282 } |
296 | 283 |
297 const std::vector<std::string>& UDPSocket::GetJoinedGroups() const { | 284 const std::vector<std::string>& UDPSocket::GetJoinedGroups() const { |
298 return multicast_groups_; | 285 return multicast_groups_; |
299 } | 286 } |
300 | 287 |
301 ResumableUDPSocket::ResumableUDPSocket(const std::string& owner_extension_id) | 288 ResumableUDPSocket::ResumableUDPSocket(const std::string& owner_extension_id) |
302 : UDPSocket(owner_extension_id), | 289 : UDPSocket(owner_extension_id), |
303 persistent_(false), | 290 persistent_(false), |
304 buffer_size_(0), | 291 buffer_size_(0), |
305 paused_(false) { | 292 paused_(false) {} |
306 } | |
307 | 293 |
308 bool ResumableUDPSocket::IsPersistent() const { | 294 bool ResumableUDPSocket::IsPersistent() const { return persistent(); } |
309 return persistent(); | |
310 } | |
311 | 295 |
312 } // namespace extensions | 296 } // namespace extensions |
OLD | NEW |