OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "net/udp/udp_socket_libevent.h" | 5 #include "net/udp/udp_socket_libevent.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <netdb.h> | 9 #include <netdb.h> |
10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 case ECONNREFUSED: | 56 case ECONNREFUSED: |
57 return ERR_CONNECTION_REFUSED; | 57 return ERR_CONNECTION_REFUSED; |
58 case EHOSTUNREACH: | 58 case EHOSTUNREACH: |
59 case EHOSTDOWN: | 59 case EHOSTDOWN: |
60 case ENETUNREACH: | 60 case ENETUNREACH: |
61 return ERR_ADDRESS_UNREACHABLE; | 61 return ERR_ADDRESS_UNREACHABLE; |
62 case EADDRNOTAVAIL: | 62 case EADDRNOTAVAIL: |
63 return ERR_ADDRESS_INVALID; | 63 return ERR_ADDRESS_INVALID; |
64 case EMSGSIZE: | 64 case EMSGSIZE: |
65 return ERR_MSG_TOO_BIG; | 65 return ERR_MSG_TOO_BIG; |
| 66 case ENOTCONN: |
| 67 return ERR_SOCKET_NOT_CONNECTED; |
66 case 0: | 68 case 0: |
67 return OK; | 69 return OK; |
68 default: | 70 default: |
69 LOG(WARNING) << "Unknown error " << os_error | 71 LOG(WARNING) << "Unknown error " << os_error |
70 << " mapped to net::ERR_FAILED"; | 72 << " mapped to net::ERR_FAILED"; |
71 return ERR_FAILED; | 73 return ERR_FAILED; |
72 } | 74 } |
73 } | 75 } |
74 | 76 |
75 } // namespace | 77 } // namespace |
(...skipping 16 matching lines...) Expand all Loading... |
92 params = new NetLogSourceParameter("source_dependency", source); | 94 params = new NetLogSourceParameter("source_dependency", source); |
93 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); | 95 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); |
94 } | 96 } |
95 | 97 |
96 UDPSocketLibevent::~UDPSocketLibevent() { | 98 UDPSocketLibevent::~UDPSocketLibevent() { |
97 Close(); | 99 Close(); |
98 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); | 100 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); |
99 } | 101 } |
100 | 102 |
101 void UDPSocketLibevent::Close() { | 103 void UDPSocketLibevent::Close() { |
| 104 DCHECK(CalledOnValidThread()); |
| 105 |
| 106 if (read_callback_) |
| 107 DoReadCallback(ERR_ABORTED); |
| 108 if (write_callback_) |
| 109 DoReadCallback(ERR_ABORTED); |
| 110 |
102 if (!is_connected()) | 111 if (!is_connected()) |
103 return; | 112 return; |
104 | 113 |
| 114 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
| 115 DCHECK(ok); |
| 116 ok = write_socket_watcher_.StopWatchingFileDescriptor(); |
| 117 DCHECK(ok); |
| 118 |
105 if (HANDLE_EINTR(close(socket_)) < 0) | 119 if (HANDLE_EINTR(close(socket_)) < 0) |
106 PLOG(ERROR) << "close"; | 120 PLOG(ERROR) << "close"; |
107 | 121 |
108 socket_ = kInvalidSocket; | 122 socket_ = kInvalidSocket; |
109 } | 123 } |
110 | 124 |
111 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { | 125 int UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const { |
112 DCHECK(CalledOnValidThread()); | 126 DCHECK(CalledOnValidThread()); |
113 DCHECK(address); | 127 DCHECK(address); |
114 if (!is_connected()) | 128 if (!is_connected()) |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 168 |
155 int UDPSocketLibevent::Read(IOBuffer* buf, | 169 int UDPSocketLibevent::Read(IOBuffer* buf, |
156 int buf_len, | 170 int buf_len, |
157 CompletionCallback* callback) { | 171 CompletionCallback* callback) { |
158 DCHECK(CalledOnValidThread()); | 172 DCHECK(CalledOnValidThread()); |
159 DCHECK_NE(kInvalidSocket, socket_); | 173 DCHECK_NE(kInvalidSocket, socket_); |
160 DCHECK(!read_callback_); | 174 DCHECK(!read_callback_); |
161 DCHECK(callback); // Synchronous operation not supported | 175 DCHECK(callback); // Synchronous operation not supported |
162 DCHECK_GT(buf_len, 0); | 176 DCHECK_GT(buf_len, 0); |
163 | 177 |
164 read_buf_ = buf; | 178 int nread = InternalRead(buf, buf_len); |
165 read_buf_len_ = buf_len; | |
166 | |
167 int nread = InternalRead(); | |
168 if (nread != ERR_IO_PENDING) | 179 if (nread != ERR_IO_PENDING) |
169 return nread; | 180 return nread; |
170 | 181 |
171 if (!MessageLoopForIO::current()->WatchFileDescriptor( | 182 if (!MessageLoopForIO::current()->WatchFileDescriptor( |
172 socket_, true, MessageLoopForIO::WATCH_READ, | 183 socket_, true, MessageLoopForIO::WATCH_READ, |
173 &read_socket_watcher_, &read_watcher_)) { | 184 &read_socket_watcher_, &read_watcher_)) { |
174 PLOG(ERROR) << "WatchFileDescriptor failed on read"; | 185 PLOG(ERROR) << "WatchFileDescriptor failed on read"; |
175 return MapPosixError(errno); | 186 return MapPosixError(errno); |
176 } | 187 } |
177 | 188 |
| 189 read_buf_ = buf; |
| 190 read_buf_len_ = buf_len; |
178 read_callback_ = callback; | 191 read_callback_ = callback; |
179 return ERR_IO_PENDING; | 192 return ERR_IO_PENDING; |
180 } | 193 } |
181 | 194 |
182 int UDPSocketLibevent::RecvFrom(IOBuffer* buf, | 195 int UDPSocketLibevent::RecvFrom(IOBuffer* buf, |
183 int buf_len, | 196 int buf_len, |
184 IPEndPoint* address, | 197 IPEndPoint* address, |
185 CompletionCallback* callback) { | 198 CompletionCallback* callback) { |
186 DCHECK(!recv_from_address_); | 199 DCHECK(!recv_from_address_); |
187 recv_from_address_ = address; | 200 recv_from_address_ = address; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 write_buf_len_ = buf_len; | 238 write_buf_len_ = buf_len; |
226 write_callback_ = callback; | 239 write_callback_ = callback; |
227 return ERR_IO_PENDING; | 240 return ERR_IO_PENDING; |
228 } | 241 } |
229 | 242 |
230 int UDPSocketLibevent::Connect(const IPEndPoint& address) { | 243 int UDPSocketLibevent::Connect(const IPEndPoint& address) { |
231 DCHECK(!is_connected()); | 244 DCHECK(!is_connected()); |
232 DCHECK(!remote_address_.get()); | 245 DCHECK(!remote_address_.get()); |
233 int rv = CreateSocket(address); | 246 int rv = CreateSocket(address); |
234 if (rv < 0) | 247 if (rv < 0) |
235 return MapPosixError(rv); | 248 return rv; |
236 | 249 |
237 struct sockaddr_storage addr_storage; | 250 struct sockaddr_storage addr_storage; |
238 size_t addr_len = sizeof(addr_storage); | 251 size_t addr_len = sizeof(addr_storage); |
239 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 252 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
240 if (!address.ToSockAddr(addr, &addr_len)) | 253 if (!address.ToSockAddr(addr, &addr_len)) |
241 return ERR_FAILED; | 254 return ERR_FAILED; |
242 | 255 |
243 rv = HANDLE_EINTR(connect(socket_, addr, addr_len)); | 256 rv = HANDLE_EINTR(connect(socket_, addr, addr_len)); |
244 if (rv < 0) | 257 if (rv < 0) |
245 return MapPosixError(rv); | 258 return MapPosixError(errno); |
246 | 259 |
247 remote_address_.reset(new IPEndPoint(address)); | 260 remote_address_.reset(new IPEndPoint(address)); |
248 return rv; | 261 return rv; |
249 } | 262 } |
250 | 263 |
251 int UDPSocketLibevent::Bind(const IPEndPoint& address) { | 264 int UDPSocketLibevent::Bind(const IPEndPoint& address) { |
252 DCHECK(!is_connected()); | 265 DCHECK(!is_connected()); |
253 DCHECK(!local_address_.get()); | 266 DCHECK(!local_address_.get()); |
254 int rv = CreateSocket(address); | 267 int rv = CreateSocket(address); |
255 if (rv < 0) | 268 if (rv < 0) |
256 return MapPosixError(rv); | 269 return rv; |
257 | 270 |
258 struct sockaddr_storage addr_storage; | 271 struct sockaddr_storage addr_storage; |
259 size_t addr_len = sizeof(addr_storage); | 272 size_t addr_len = sizeof(addr_storage); |
260 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 273 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
261 if (!address.ToSockAddr(addr, &addr_len)) | 274 if (!address.ToSockAddr(addr, &addr_len)) |
262 return ERR_FAILED; | 275 return ERR_FAILED; |
263 | 276 |
264 rv = bind(socket_, addr, addr_len); | 277 rv = bind(socket_, addr, addr_len); |
265 if (rv < 0) | 278 if (rv < 0) |
266 return MapPosixError(rv); | 279 return MapPosixError(errno); |
267 | 280 |
268 local_address_.reset(new IPEndPoint(address)); | 281 local_address_.reset(new IPEndPoint(address)); |
269 return rv; | 282 return rv; |
270 } | 283 } |
271 | 284 |
272 void UDPSocketLibevent::DoReadCallback(int rv) { | 285 void UDPSocketLibevent::DoReadCallback(int rv) { |
273 DCHECK_NE(rv, ERR_IO_PENDING); | 286 DCHECK_NE(rv, ERR_IO_PENDING); |
274 DCHECK(read_callback_); | 287 DCHECK(read_callback_); |
275 | 288 |
276 // since Run may result in Read being called, clear read_callback_ up front. | 289 // since Run may result in Read being called, clear read_callback_ up front. |
277 CompletionCallback* c = read_callback_; | 290 CompletionCallback* c = read_callback_; |
278 read_callback_ = NULL; | 291 read_callback_ = NULL; |
279 recv_from_address_ = NULL; | 292 recv_from_address_ = NULL; |
280 c->Run(rv); | 293 c->Run(rv); |
281 } | 294 } |
282 | 295 |
283 void UDPSocketLibevent::DoWriteCallback(int rv) { | 296 void UDPSocketLibevent::DoWriteCallback(int rv) { |
284 DCHECK_NE(rv, ERR_IO_PENDING); | 297 DCHECK_NE(rv, ERR_IO_PENDING); |
285 DCHECK(write_callback_); | 298 DCHECK(write_callback_); |
286 | 299 |
287 // since Run may result in Write being called, clear write_callback_ up front. | 300 // since Run may result in Write being called, clear write_callback_ up front. |
288 CompletionCallback* c = write_callback_; | 301 CompletionCallback* c = write_callback_; |
289 write_callback_ = NULL; | 302 write_callback_ = NULL; |
290 send_to_address_.reset(); | 303 send_to_address_.reset(); |
291 c->Run(rv); | 304 c->Run(rv); |
292 } | 305 } |
293 | 306 |
294 void UDPSocketLibevent::DidCompleteRead() { | 307 void UDPSocketLibevent::DidCompleteRead() { |
295 int result = InternalRead(); | 308 int result = InternalRead(read_buf_, read_buf_len_); |
296 if (result != ERR_IO_PENDING) { | 309 if (result != ERR_IO_PENDING) { |
297 read_buf_ = NULL; | 310 read_buf_ = NULL; |
298 read_buf_len_ = 0; | 311 read_buf_len_ = 0; |
299 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); | 312 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); |
300 DCHECK(ok); | 313 DCHECK(ok); |
301 DoReadCallback(result); | 314 DoReadCallback(result); |
302 } | 315 } |
303 } | 316 } |
304 | 317 |
305 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { | 318 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { |
306 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); | 319 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); |
307 if (socket_ == kInvalidSocket) | 320 if (socket_ == kInvalidSocket) |
308 return errno; | 321 return MapPosixError(errno); |
309 if (SetNonBlocking(socket_)) { | 322 if (SetNonBlocking(socket_)) { |
310 const int err = errno; | 323 const int err = MapPosixError(errno); |
311 Close(); | 324 Close(); |
312 return err; | 325 return err; |
313 } | 326 } |
314 return OK; | 327 return OK; |
315 } | 328 } |
316 | 329 |
317 void UDPSocketLibevent::DidCompleteWrite() { | 330 void UDPSocketLibevent::DidCompleteWrite() { |
318 int result = InternalWrite(write_buf_, write_buf_len_); | 331 int result = InternalWrite(write_buf_, write_buf_len_); |
319 if (result >= 0) { | 332 if (result >= 0) { |
320 static base::StatsCounter write_bytes("udp.write_bytes"); | 333 static base::StatsCounter write_bytes("udp.write_bytes"); |
321 write_bytes.Add(result); | 334 write_bytes.Add(result); |
322 } else { | 335 } else { |
323 result = MapPosixError(errno); | 336 result = MapPosixError(errno); |
324 } | 337 } |
325 | 338 |
326 if (result != ERR_IO_PENDING) { | 339 if (result != ERR_IO_PENDING) { |
327 write_buf_ = NULL; | 340 write_buf_ = NULL; |
328 write_buf_len_ = 0; | 341 write_buf_len_ = 0; |
329 write_socket_watcher_.StopWatchingFileDescriptor(); | 342 write_socket_watcher_.StopWatchingFileDescriptor(); |
330 DoWriteCallback(result); | 343 DoWriteCallback(result); |
331 } | 344 } |
332 } | 345 } |
333 | 346 |
334 int UDPSocketLibevent::InternalRead() { | 347 int UDPSocketLibevent::InternalRead(IOBuffer* buf, int buf_len) { |
335 int bytes_transferred; | 348 int bytes_transferred; |
336 int flags = 0; | 349 int flags = 0; |
337 | 350 |
338 struct sockaddr_storage addr_storage; | 351 struct sockaddr_storage addr_storage; |
339 socklen_t addr_len = sizeof(addr_storage); | 352 socklen_t addr_len = sizeof(addr_storage); |
340 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 353 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
341 | 354 |
342 bytes_transferred = | 355 bytes_transferred = |
343 HANDLE_EINTR(recvfrom(socket_, | 356 HANDLE_EINTR(recvfrom(socket_, |
344 read_buf_->data(), | 357 buf->data(), |
345 read_buf_len_, | 358 buf_len, |
346 flags, | 359 flags, |
347 addr, | 360 addr, |
348 &addr_len)); | 361 &addr_len)); |
349 int result; | 362 int result; |
350 if (bytes_transferred >= 0) { | 363 if (bytes_transferred >= 0) { |
351 result = bytes_transferred; | 364 result = bytes_transferred; |
352 static base::StatsCounter read_bytes("udp.read_bytes"); | 365 static base::StatsCounter read_bytes("udp.read_bytes"); |
353 read_bytes.Add(bytes_transferred); | 366 read_bytes.Add(bytes_transferred); |
354 if (recv_from_address_) { | 367 if (recv_from_address_) { |
355 if (!recv_from_address_->FromSockAddr(addr, addr_len)) | 368 if (!recv_from_address_->FromSockAddr(addr, addr_len)) |
356 result = ERR_FAILED; | 369 result = ERR_FAILED; |
357 } | 370 } |
358 } else { | 371 } else { |
359 result = MapPosixError(errno); | 372 result = MapPosixError(errno); |
360 } | 373 } |
361 return result; | 374 return result; |
362 } | 375 } |
| 376 |
363 int UDPSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { | 377 int UDPSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { |
364 struct sockaddr_storage addr_storage; | 378 struct sockaddr_storage addr_storage; |
365 size_t addr_len = sizeof(addr_storage); | 379 size_t addr_len = sizeof(addr_storage); |
366 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | 380 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
367 | 381 |
368 if (!send_to_address_.get()) { | 382 if (!send_to_address_.get()) { |
369 addr = NULL; | 383 addr = NULL; |
370 addr_len = 0; | 384 addr_len = 0; |
371 } else { | 385 } else { |
372 if (!send_to_address_->ToSockAddr(addr, &addr_len)) | 386 if (!send_to_address_->ToSockAddr(addr, &addr_len)) |
373 return ERR_FAILED; | 387 return ERR_FAILED; |
374 } | 388 } |
375 | 389 |
376 return HANDLE_EINTR(sendto(socket_, | 390 return HANDLE_EINTR(sendto(socket_, |
377 buf->data(), | 391 buf->data(), |
378 buf_len, | 392 buf_len, |
379 0, | 393 0, |
380 addr, | 394 addr, |
381 addr_len)); | 395 addr_len)); |
382 } | 396 } |
383 | 397 |
384 } // namespace net | 398 } // namespace net |
OLD | NEW |