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