| 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 |