Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/udp/udp_socket_win.h" | |
| 6 | |
| 7 #include <mstcpip.h> | |
| 8 | |
| 9 #include "base/eintr_wrapper.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "base/message_loop.h" | |
| 12 #include "base/memory_debug.h" | |
| 13 #include "base/metrics/stats_counters.h" | |
| 14 #include "net/base/io_buffer.h" | |
| 15 #include "net/base/ip_endpoint.h" | |
| 16 #include "net/base/net_errors.h" | |
| 17 #include "net/base/net_log.h" | |
| 18 #include "net/base/net_util.h" | |
| 19 #include "net/base/winsock_init.h" | |
| 20 | |
| 21 namespace net { | |
| 22 | |
| 23 namespace { | |
| 24 | |
| 25 // Assert that the (manual-reset) event object is not signaled. | |
| 26 void AssertEventNotSignaled(WSAEVENT hEvent) { | |
|
Mike Belshe
2011/03/10 06:53:38
Since this code (AssertEventNotSignaled and Resaet
Sergey Ulanov
2011/03/11 00:54:37
Moved it all to net/base/winsock_util.cc .
| |
| 27 DWORD wait_rv = WaitForSingleObject(hEvent, 0); | |
| 28 if (wait_rv != WAIT_TIMEOUT) { | |
| 29 DWORD err = ERROR_SUCCESS; | |
| 30 if (wait_rv == WAIT_FAILED) | |
| 31 err = GetLastError(); | |
| 32 CHECK(false); // Crash. | |
| 33 // This LOG statement is unreachable since we have already crashed, but it | |
| 34 // should prevent the compiler from optimizing away the |wait_rv| and | |
| 35 // |err| variables so they appear nicely on the stack in crash dumps. | |
| 36 VLOG(1) << "wait_rv=" << wait_rv << ", err=" << err; | |
| 37 } | |
| 38 } | |
| 39 | |
| 40 // If the (manual-reset) event object is signaled, resets it and returns true. | |
| 41 // Otherwise, does nothing and returns false. Called after a Winsock function | |
| 42 // succeeds synchronously | |
| 43 // | |
| 44 // Our testing shows that except in rare cases (when running inside QEMU), | |
| 45 // the event object is already signaled at this point, so we call this method | |
| 46 // to avoid a context switch in common cases. This is just a performance | |
| 47 // optimization. The code still works if this function simply returns false. | |
| 48 bool ResetEventIfSignaled(WSAEVENT hEvent) { | |
| 49 // TODO(wtc): Remove the CHECKs after enough testing. | |
| 50 DWORD wait_rv = WaitForSingleObject(hEvent, 0); | |
| 51 if (wait_rv == WAIT_TIMEOUT) | |
| 52 return false; // The event object is not signaled. | |
| 53 CHECK_EQ(WAIT_OBJECT_0, wait_rv); | |
| 54 BOOL ok = WSAResetEvent(hEvent); | |
| 55 CHECK(ok); | |
| 56 return true; | |
| 57 } | |
| 58 | |
| 59 //----------------------------------------------------------------------------- | |
| 60 | |
| 61 int MapWinsockError(int os_error) { | |
| 62 // There are numerous Winsock error codes, but these are the ones we thus far | |
| 63 // find interesting. | |
| 64 switch (os_error) { | |
| 65 case WSAEACCES: | |
| 66 return ERR_ACCESS_DENIED; | |
| 67 case WSAENETDOWN: | |
| 68 return ERR_INTERNET_DISCONNECTED; | |
| 69 case WSAETIMEDOUT: | |
| 70 return ERR_TIMED_OUT; | |
| 71 case WSAECONNRESET: | |
| 72 case WSAENETRESET: // Related to keep-alive | |
| 73 return ERR_CONNECTION_RESET; | |
| 74 case WSAECONNABORTED: | |
| 75 return ERR_CONNECTION_ABORTED; | |
| 76 case WSAECONNREFUSED: | |
| 77 return ERR_CONNECTION_REFUSED; | |
| 78 case WSA_IO_INCOMPLETE: | |
| 79 case WSAEDISCON: | |
| 80 // WSAEDISCON is returned by WSARecv or WSARecvFrom for message-oriented | |
| 81 // sockets (where a return value of zero means a zero-byte message) to | |
| 82 // indicate graceful connection shutdown. We should not ever see this | |
| 83 // error code for TCP sockets, which are byte stream oriented. | |
| 84 LOG(DFATAL) << "Unexpected error " << os_error | |
| 85 << " mapped to net::ERR_UNEXPECTED"; | |
| 86 return ERR_UNEXPECTED; | |
| 87 case WSAEHOSTUNREACH: | |
| 88 case WSAENETUNREACH: | |
| 89 return ERR_ADDRESS_UNREACHABLE; | |
| 90 case WSAEADDRNOTAVAIL: | |
| 91 return ERR_ADDRESS_INVALID; | |
| 92 case WSAENOTCONN: | |
| 93 return ERR_SOCKET_NOT_CONNECTED; | |
| 94 case ERROR_SUCCESS: | |
| 95 return OK; | |
| 96 default: | |
| 97 LOG(WARNING) << "Unknown error " << os_error | |
| 98 << " mapped to net::ERR_FAILED"; | |
| 99 return ERR_FAILED; | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 } // namespace | |
| 104 | |
| 105 //----------------------------------------------------------------------------- | |
| 106 | |
| 107 void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) { | |
| 108 DCHECK_EQ(object, socket_->read_overlapped_.hEvent); | |
| 109 socket_->DidCompleteRead(); | |
| 110 } | |
| 111 | |
| 112 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { | |
| 113 DCHECK_EQ(object, socket_->write_overlapped_.hEvent); | |
| 114 socket_->DidCompleteWrite(); | |
| 115 } | |
| 116 | |
| 117 UDPSocketWin::UDPSocketWin(net::NetLog* net_log, | |
| 118 const net::NetLog::Source& source) | |
| 119 : socket_(INVALID_SOCKET), | |
| 120 read_buf_len_(0), | |
| 121 recv_from_address_(NULL), | |
| 122 write_buf_len_(0), | |
| 123 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), | |
|
Mike Belshe
2011/03/10 06:53:38
nit: for argument ordering, read_delegate should f
Sergey Ulanov
2011/03/11 00:54:37
Done.
| |
| 124 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), | |
| 125 read_callback_(NULL), | |
| 126 write_callback_(NULL), | |
| 127 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { | |
| 128 EnsureWinsockInit(); | |
| 129 scoped_refptr<NetLog::EventParameters> params; | |
| 130 if (source.is_valid()) | |
| 131 params = new NetLogSourceParameter("source_dependency", source); | |
| 132 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); | |
| 133 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); | |
| 134 read_overlapped_.hEvent = WSACreateEvent(); | |
| 135 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); | |
| 136 write_overlapped_.hEvent = WSACreateEvent(); | |
|
Mike Belshe
2011/03/10 06:53:38
should we also:
memset(&read_buffer_, 0, sizeof(
Sergey Ulanov
2011/03/11 00:54:37
I don't think it is neccessary: WSABUF has only tw
| |
| 137 } | |
| 138 | |
| 139 UDPSocketWin::~UDPSocketWin() { | |
| 140 Close(); | |
| 141 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); | |
| 142 } | |
| 143 | |
| 144 void UDPSocketWin::Close() { | |
| 145 DCHECK(CalledOnValidThread()); | |
| 146 | |
| 147 if (!is_connected()) | |
| 148 return; | |
| 149 | |
| 150 if (read_callback_) | |
| 151 DoReadCallback(ERR_ABORTED); | |
| 152 if (write_callback_) | |
| 153 DoReadCallback(ERR_ABORTED); | |
| 154 | |
| 155 read_watcher_.StopWatching(); | |
| 156 write_watcher_.StopWatching(); | |
| 157 | |
| 158 closesocket(socket_); | |
| 159 socket_ = INVALID_SOCKET; | |
| 160 } | |
| 161 | |
| 162 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { | |
| 163 DCHECK(CalledOnValidThread()); | |
| 164 DCHECK(address); | |
| 165 if (!is_connected()) | |
| 166 return ERR_SOCKET_NOT_CONNECTED; | |
| 167 | |
| 168 if (!remote_address_.get()) { | |
| 169 struct sockaddr_storage addr_storage; | |
| 170 int addr_len = sizeof(addr_storage); | |
| 171 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 172 if (getpeername(socket_, addr, &addr_len)) | |
| 173 return MapWinsockError(WSAGetLastError()); | |
| 174 scoped_ptr<IPEndPoint> address(new IPEndPoint()); | |
| 175 if (!address->FromSockAddr(addr, addr_len)) | |
| 176 return ERR_FAILED; | |
| 177 remote_address_.reset(address.release()); | |
| 178 } | |
| 179 | |
| 180 *address = *remote_address_; | |
| 181 return OK; | |
| 182 } | |
| 183 | |
| 184 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { | |
| 185 DCHECK(CalledOnValidThread()); | |
| 186 DCHECK(address); | |
| 187 if (!is_connected()) | |
| 188 return ERR_SOCKET_NOT_CONNECTED; | |
| 189 | |
| 190 if (!local_address_.get()) { | |
| 191 struct sockaddr_storage addr_storage; | |
| 192 socklen_t addr_len = sizeof(addr_storage); | |
| 193 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 194 if (getsockname(socket_, addr, &addr_len)) | |
| 195 return MapWinsockError(WSAGetLastError()); | |
| 196 scoped_ptr<IPEndPoint> address(new IPEndPoint()); | |
| 197 if (!address->FromSockAddr(addr, addr_len)) | |
| 198 return ERR_FAILED; | |
| 199 local_address_.reset(address.release()); | |
| 200 } | |
| 201 | |
| 202 *address = *local_address_; | |
| 203 return OK; | |
| 204 } | |
| 205 | |
| 206 int UDPSocketWin::RecvFrom(IOBuffer* buf, | |
| 207 int buf_len, | |
| 208 IPEndPoint* address, | |
| 209 CompletionCallback* callback) { | |
| 210 DCHECK(!recv_from_address_); | |
| 211 recv_from_address_ = address; | |
| 212 return Read(buf, buf_len, callback); | |
| 213 } | |
| 214 | |
| 215 int UDPSocketWin::Read(IOBuffer* buf, | |
| 216 int buf_len, | |
| 217 CompletionCallback* callback) { | |
| 218 DCHECK(CalledOnValidThread()); | |
| 219 DCHECK_NE(INVALID_SOCKET, socket_); | |
| 220 DCHECK(!read_callback_); | |
| 221 DCHECK(callback); // Synchronous operation not supported. | |
| 222 DCHECK_GT(buf_len, 0); | |
| 223 | |
| 224 read_buffer_.buf = buf->data(); | |
| 225 read_buffer_.len = buf_len; | |
|
Mike Belshe
2011/03/10 06:53:38
Note: I liked what you did in the libevent.cc cha
Sergey Ulanov
2011/03/11 00:54:37
Added the same arguments in InternalRead() here
| |
| 226 | |
| 227 int nread = InternalRead(); | |
| 228 if (nread != ERR_IO_PENDING) | |
| 229 return nread; | |
| 230 | |
| 231 read_iobuffer_ = buf; | |
| 232 read_callback_ = callback; | |
| 233 return ERR_IO_PENDING; | |
| 234 } | |
| 235 | |
| 236 int UDPSocketWin::SendTo(IOBuffer* buf, | |
| 237 int buf_len, | |
|
Mike Belshe
2011/03/10 06:53:38
nit spacing
Sergey Ulanov
2011/03/11 00:54:37
Done.
| |
| 238 const IPEndPoint& address, | |
| 239 CompletionCallback* callback) { | |
| 240 send_to_address_.reset(new IPEndPoint(address)); | |
| 241 return Write(buf, buf_len, callback); | |
| 242 } | |
| 243 | |
| 244 int UDPSocketWin::Write(IOBuffer* buf, | |
| 245 int buf_len, | |
| 246 CompletionCallback* callback) { | |
| 247 DCHECK(CalledOnValidThread()); | |
| 248 DCHECK_NE(INVALID_SOCKET, socket_); | |
| 249 DCHECK(!write_callback_); | |
| 250 DCHECK(callback); // Synchronous operation not supported. | |
| 251 DCHECK_GT(buf_len, 0); | |
| 252 | |
| 253 write_buffer_.buf = buf->data(); | |
| 254 write_buffer_.len = buf_len; | |
| 255 | |
| 256 int nwrite = InternalWrite(); | |
| 257 if (nwrite != ERR_IO_PENDING) | |
| 258 return nwrite; | |
| 259 | |
| 260 write_iobuffer_ = buf; | |
| 261 write_callback_ = callback; | |
| 262 return ERR_IO_PENDING; | |
| 263 } | |
| 264 | |
| 265 int UDPSocketWin::Connect(const IPEndPoint& address) { | |
| 266 DCHECK(!is_connected()); | |
| 267 DCHECK(!remote_address_.get()); | |
| 268 int rv = CreateSocket(address); | |
| 269 if (rv < 0) | |
| 270 return rv; | |
| 271 | |
| 272 struct sockaddr_storage addr_storage; | |
| 273 size_t addr_len = sizeof(addr_storage); | |
| 274 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 275 if (!address.ToSockAddr(addr, &addr_len)) | |
| 276 return ERR_FAILED; | |
| 277 | |
| 278 rv = connect(socket_, addr, addr_len); | |
| 279 if (rv < 0) | |
| 280 return MapWinsockError(WSAGetLastError()); | |
| 281 | |
| 282 remote_address_.reset(new IPEndPoint(address)); | |
| 283 return rv; | |
| 284 } | |
| 285 | |
| 286 int UDPSocketWin::Bind(const IPEndPoint& address) { | |
| 287 DCHECK(!is_connected()); | |
| 288 DCHECK(!local_address_.get()); | |
| 289 int rv = CreateSocket(address); | |
| 290 if (rv < 0) | |
| 291 return rv; | |
| 292 | |
| 293 struct sockaddr_storage addr_storage; | |
| 294 size_t addr_len = sizeof(addr_storage); | |
| 295 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 296 if (!address.ToSockAddr(addr, &addr_len)) | |
| 297 return ERR_FAILED; | |
| 298 | |
| 299 rv = bind(socket_, addr, addr_len); | |
| 300 if (rv < 0) | |
| 301 return MapWinsockError(WSAGetLastError()); | |
| 302 | |
| 303 local_address_.reset(new IPEndPoint(address)); | |
| 304 return rv; | |
| 305 } | |
| 306 | |
| 307 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { | |
| 308 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); | |
| 309 if (socket_ == INVALID_SOCKET) | |
| 310 return MapWinsockError(WSAGetLastError()); | |
| 311 if (SetNonBlocking(socket_)) { | |
|
Mike Belshe
2011/03/10 06:53:38
I don't think we want this SetNonBlocking call - i
Sergey Ulanov
2011/03/11 00:54:37
Done.
| |
| 312 const int err = MapWinsockError(WSAGetLastError()); | |
| 313 Close(); | |
| 314 return err; | |
| 315 } | |
| 316 return OK; | |
| 317 } | |
| 318 | |
| 319 void UDPSocketWin::DoReadCallback(int rv) { | |
| 320 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 321 DCHECK(read_callback_); | |
| 322 | |
| 323 // since Run may result in Read being called, clear read_callback_ up front. | |
| 324 CompletionCallback* c = read_callback_; | |
| 325 read_callback_ = NULL; | |
| 326 recv_from_address_ = NULL; | |
| 327 c->Run(rv); | |
| 328 } | |
| 329 | |
| 330 void UDPSocketWin::DoWriteCallback(int rv) { | |
| 331 DCHECK_NE(rv, ERR_IO_PENDING); | |
| 332 DCHECK(write_callback_); | |
| 333 | |
| 334 // since Run may result in Write being called, clear write_callback_ up front. | |
| 335 CompletionCallback* c = write_callback_; | |
| 336 write_callback_ = NULL; | |
| 337 send_to_address_.reset(); | |
| 338 c->Run(rv); | |
| 339 } | |
| 340 | |
| 341 void UDPSocketWin::DidCompleteRead() { | |
| 342 DWORD num_bytes, flags; | |
| 343 BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_, | |
| 344 &num_bytes, FALSE, &flags); | |
| 345 WSAResetEvent(read_overlapped_.hEvent); | |
| 346 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); | |
| 347 if (ok) { | |
| 348 if (!ProcessSuccessfulRead(num_bytes)) | |
| 349 result = ERR_FAILED; | |
| 350 } | |
| 351 read_iobuffer_ = NULL; | |
|
Mike Belshe
2011/03/10 06:53:38
I think you should zero out the read_buffer_ in he
Sergey Ulanov
2011/03/11 00:54:37
Oh, I've found this in MSDN:
If this function is
| |
| 352 DoReadCallback(result); | |
| 353 } | |
| 354 | |
| 355 bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes) { | |
| 356 static base::StatsCounter read_bytes("udp.read_bytes"); | |
| 357 read_bytes.Add(num_bytes); | |
| 358 | |
| 359 // Convert address. | |
| 360 if (recv_from_address_) { | |
| 361 struct sockaddr* addr = | |
| 362 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); | |
| 363 if (!recv_from_address_->FromSockAddr(addr, recv_addr_len_)) | |
| 364 return false; | |
| 365 } | |
| 366 | |
| 367 return true; | |
| 368 } | |
| 369 | |
| 370 void UDPSocketWin::DidCompleteWrite() { | |
| 371 DWORD num_bytes, flags; | |
| 372 BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_, | |
| 373 &num_bytes, FALSE, &flags); | |
| 374 WSAResetEvent(write_overlapped_.hEvent); | |
| 375 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); | |
| 376 if (ok) | |
| 377 ProcessSuccessfulWrite(num_bytes); | |
| 378 write_iobuffer_ = NULL; | |
| 379 DoWriteCallback(result); | |
| 380 } | |
| 381 | |
| 382 void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) { | |
| 383 static base::StatsCounter write_bytes("udp.write_bytes"); | |
| 384 write_bytes.Add(num_bytes); | |
| 385 } | |
| 386 | |
| 387 int UDPSocketWin::InternalRead() { | |
|
Mike Belshe
2011/03/10 06:53:38
DCHECK(read_buffer_.buf)
Sergey Ulanov
2011/03/11 00:54:37
Not needed anymore, as I removed read_buffer_
| |
| 388 recv_addr_len_ = sizeof(recv_addr_storage_); | |
| 389 struct sockaddr* addr = | |
| 390 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); | |
| 391 DWORD flags = 0; | |
| 392 DWORD num; | |
| 393 AssertEventNotSignaled(read_overlapped_.hEvent); | |
| 394 int rv = WSARecvFrom(socket_, &read_buffer_, 1, &num, &flags, | |
| 395 addr, &recv_addr_len_, &read_overlapped_, NULL); | |
| 396 if (rv == 0) { | |
| 397 if (ResetEventIfSignaled(read_overlapped_.hEvent)) { | |
| 398 // Because of how WSARecv fills memory when used asynchronously, Purify | |
| 399 // isn't able to detect that it's been initialized, so it scans for 0xcd | |
| 400 // in the buffer and reports UMRs (uninitialized memory reads) for those | |
| 401 // individual bytes. We override that in PURIFY builds to avoid the | |
| 402 // false error reports. | |
| 403 // See bug 5297. | |
| 404 base::MemoryDebug::MarkAsInitialized(read_buffer_.buf, num); | |
| 405 if (!ProcessSuccessfulRead(num)) | |
| 406 return ERR_FAILED; | |
| 407 return static_cast<int>(num); | |
| 408 } | |
| 409 } else { | |
| 410 int os_error = WSAGetLastError(); | |
| 411 if (os_error != WSA_IO_PENDING) | |
| 412 return MapWinsockError(os_error); | |
| 413 } | |
| 414 read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_); | |
| 415 return ERR_IO_PENDING; | |
| 416 } | |
| 417 | |
| 418 int UDPSocketWin::InternalWrite() { | |
|
Mike Belshe
2011/03/10 06:53:38
DCHECK(write_buffer_.buf);
Sergey Ulanov
2011/03/11 00:54:37
same here.
| |
| 419 struct sockaddr_storage addr_storage; | |
| 420 size_t addr_len = sizeof(addr_storage); | |
| 421 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); | |
| 422 | |
| 423 // Convert address. | |
| 424 if (!send_to_address_.get()) { | |
| 425 addr = NULL; | |
| 426 addr_len = 0; | |
| 427 } else { | |
| 428 if (!send_to_address_->ToSockAddr(addr, &addr_len)) | |
| 429 return ERR_FAILED; | |
| 430 } | |
| 431 | |
| 432 DWORD flags = 0; | |
| 433 DWORD num; | |
| 434 AssertEventNotSignaled(write_overlapped_.hEvent); | |
| 435 int rv = WSASendTo(socket_, &write_buffer_, 1, &num, flags, | |
| 436 addr, addr_len, &write_overlapped_, NULL); | |
| 437 if (rv == 0) { | |
| 438 if (ResetEventIfSignaled(write_overlapped_.hEvent)) { | |
| 439 ProcessSuccessfulWrite(num); | |
| 440 return static_cast<int>(num); | |
| 441 } | |
| 442 } else { | |
| 443 int os_error = WSAGetLastError(); | |
| 444 if (os_error != WSA_IO_PENDING) | |
| 445 return MapWinsockError(os_error); | |
| 446 } | |
| 447 | |
| 448 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); | |
| 449 return ERR_IO_PENDING; | |
| 450 } | |
| 451 | |
| 452 } // namespace net | |
| OLD | NEW |