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 #include "net/base/winsock_util.h" |
| 21 |
| 22 namespace net { |
| 23 |
| 24 void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) { |
| 25 DCHECK_EQ(object, socket_->read_overlapped_.hEvent); |
| 26 socket_->DidCompleteRead(); |
| 27 } |
| 28 |
| 29 void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { |
| 30 DCHECK_EQ(object, socket_->write_overlapped_.hEvent); |
| 31 socket_->DidCompleteWrite(); |
| 32 } |
| 33 |
| 34 UDPSocketWin::UDPSocketWin(net::NetLog* net_log, |
| 35 const net::NetLog::Source& source) |
| 36 : socket_(INVALID_SOCKET), |
| 37 ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), |
| 38 ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), |
| 39 recv_from_address_(NULL), |
| 40 read_callback_(NULL), |
| 41 write_callback_(NULL), |
| 42 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { |
| 43 EnsureWinsockInit(); |
| 44 scoped_refptr<NetLog::EventParameters> params; |
| 45 if (source.is_valid()) |
| 46 params = new NetLogSourceParameter("source_dependency", source); |
| 47 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); |
| 48 memset(&read_overlapped_, 0, sizeof(read_overlapped_)); |
| 49 read_overlapped_.hEvent = WSACreateEvent(); |
| 50 memset(&write_overlapped_, 0, sizeof(write_overlapped_)); |
| 51 write_overlapped_.hEvent = WSACreateEvent(); |
| 52 } |
| 53 |
| 54 UDPSocketWin::~UDPSocketWin() { |
| 55 Close(); |
| 56 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); |
| 57 } |
| 58 |
| 59 void UDPSocketWin::Close() { |
| 60 DCHECK(CalledOnValidThread()); |
| 61 |
| 62 if (!is_connected()) |
| 63 return; |
| 64 |
| 65 if (read_callback_) |
| 66 DoReadCallback(ERR_ABORTED); |
| 67 if (write_callback_) |
| 68 DoReadCallback(ERR_ABORTED); |
| 69 |
| 70 read_watcher_.StopWatching(); |
| 71 write_watcher_.StopWatching(); |
| 72 |
| 73 closesocket(socket_); |
| 74 socket_ = INVALID_SOCKET; |
| 75 } |
| 76 |
| 77 int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { |
| 78 DCHECK(CalledOnValidThread()); |
| 79 DCHECK(address); |
| 80 if (!is_connected()) |
| 81 return ERR_SOCKET_NOT_CONNECTED; |
| 82 |
| 83 if (!remote_address_.get()) { |
| 84 struct sockaddr_storage addr_storage; |
| 85 int addr_len = sizeof(addr_storage); |
| 86 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
| 87 if (getpeername(socket_, addr, &addr_len)) |
| 88 return MapWinsockError(WSAGetLastError()); |
| 89 scoped_ptr<IPEndPoint> address(new IPEndPoint()); |
| 90 if (!address->FromSockAddr(addr, addr_len)) |
| 91 return ERR_FAILED; |
| 92 remote_address_.reset(address.release()); |
| 93 } |
| 94 |
| 95 *address = *remote_address_; |
| 96 return OK; |
| 97 } |
| 98 |
| 99 int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { |
| 100 DCHECK(CalledOnValidThread()); |
| 101 DCHECK(address); |
| 102 if (!is_connected()) |
| 103 return ERR_SOCKET_NOT_CONNECTED; |
| 104 |
| 105 if (!local_address_.get()) { |
| 106 struct sockaddr_storage addr_storage; |
| 107 socklen_t addr_len = sizeof(addr_storage); |
| 108 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
| 109 if (getsockname(socket_, addr, &addr_len)) |
| 110 return MapWinsockError(WSAGetLastError()); |
| 111 scoped_ptr<IPEndPoint> address(new IPEndPoint()); |
| 112 if (!address->FromSockAddr(addr, addr_len)) |
| 113 return ERR_FAILED; |
| 114 local_address_.reset(address.release()); |
| 115 } |
| 116 |
| 117 *address = *local_address_; |
| 118 return OK; |
| 119 } |
| 120 |
| 121 int UDPSocketWin::RecvFrom(IOBuffer* buf, |
| 122 int buf_len, |
| 123 IPEndPoint* address, |
| 124 CompletionCallback* callback) { |
| 125 DCHECK(!recv_from_address_); |
| 126 recv_from_address_ = address; |
| 127 return Read(buf, buf_len, callback); |
| 128 } |
| 129 |
| 130 int UDPSocketWin::Read(IOBuffer* buf, |
| 131 int buf_len, |
| 132 CompletionCallback* callback) { |
| 133 DCHECK(CalledOnValidThread()); |
| 134 DCHECK_NE(INVALID_SOCKET, socket_); |
| 135 DCHECK(!read_callback_); |
| 136 DCHECK(callback); // Synchronous operation not supported. |
| 137 DCHECK_GT(buf_len, 0); |
| 138 |
| 139 int nread = InternalRead(buf, buf_len); |
| 140 if (nread != ERR_IO_PENDING) |
| 141 return nread; |
| 142 |
| 143 read_iobuffer_ = buf; |
| 144 read_callback_ = callback; |
| 145 return ERR_IO_PENDING; |
| 146 } |
| 147 |
| 148 int UDPSocketWin::SendTo(IOBuffer* buf, |
| 149 int buf_len, |
| 150 const IPEndPoint& address, |
| 151 CompletionCallback* callback) { |
| 152 send_to_address_.reset(new IPEndPoint(address)); |
| 153 return Write(buf, buf_len, callback); |
| 154 } |
| 155 |
| 156 int UDPSocketWin::Write(IOBuffer* buf, |
| 157 int buf_len, |
| 158 CompletionCallback* callback) { |
| 159 DCHECK(CalledOnValidThread()); |
| 160 DCHECK_NE(INVALID_SOCKET, socket_); |
| 161 DCHECK(!write_callback_); |
| 162 DCHECK(callback); // Synchronous operation not supported. |
| 163 DCHECK_GT(buf_len, 0); |
| 164 |
| 165 int nwrite = InternalWrite(buf, buf_len); |
| 166 if (nwrite != ERR_IO_PENDING) |
| 167 return nwrite; |
| 168 |
| 169 write_iobuffer_ = buf; |
| 170 write_callback_ = callback; |
| 171 return ERR_IO_PENDING; |
| 172 } |
| 173 |
| 174 int UDPSocketWin::Connect(const IPEndPoint& address) { |
| 175 DCHECK(!is_connected()); |
| 176 DCHECK(!remote_address_.get()); |
| 177 int rv = CreateSocket(address); |
| 178 if (rv < 0) |
| 179 return rv; |
| 180 |
| 181 struct sockaddr_storage addr_storage; |
| 182 size_t addr_len = sizeof(addr_storage); |
| 183 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
| 184 if (!address.ToSockAddr(addr, &addr_len)) |
| 185 return ERR_FAILED; |
| 186 |
| 187 rv = connect(socket_, addr, addr_len); |
| 188 if (rv < 0) |
| 189 return MapWinsockError(WSAGetLastError()); |
| 190 |
| 191 remote_address_.reset(new IPEndPoint(address)); |
| 192 return rv; |
| 193 } |
| 194 |
| 195 int UDPSocketWin::Bind(const IPEndPoint& address) { |
| 196 DCHECK(!is_connected()); |
| 197 DCHECK(!local_address_.get()); |
| 198 int rv = CreateSocket(address); |
| 199 if (rv < 0) |
| 200 return rv; |
| 201 |
| 202 struct sockaddr_storage addr_storage; |
| 203 size_t addr_len = sizeof(addr_storage); |
| 204 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
| 205 if (!address.ToSockAddr(addr, &addr_len)) |
| 206 return ERR_FAILED; |
| 207 |
| 208 rv = bind(socket_, addr, addr_len); |
| 209 if (rv < 0) |
| 210 return MapWinsockError(WSAGetLastError()); |
| 211 |
| 212 local_address_.reset(new IPEndPoint(address)); |
| 213 return rv; |
| 214 } |
| 215 |
| 216 int UDPSocketWin::CreateSocket(const IPEndPoint& address) { |
| 217 socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, |
| 218 WSA_FLAG_OVERLAPPED); |
| 219 if (socket_ == INVALID_SOCKET) |
| 220 return MapWinsockError(WSAGetLastError()); |
| 221 return OK; |
| 222 } |
| 223 |
| 224 void UDPSocketWin::DoReadCallback(int rv) { |
| 225 DCHECK_NE(rv, ERR_IO_PENDING); |
| 226 DCHECK(read_callback_); |
| 227 |
| 228 // since Run may result in Read being called, clear read_callback_ up front. |
| 229 CompletionCallback* c = read_callback_; |
| 230 read_callback_ = NULL; |
| 231 recv_from_address_ = NULL; |
| 232 c->Run(rv); |
| 233 } |
| 234 |
| 235 void UDPSocketWin::DoWriteCallback(int rv) { |
| 236 DCHECK_NE(rv, ERR_IO_PENDING); |
| 237 DCHECK(write_callback_); |
| 238 |
| 239 // since Run may result in Write being called, clear write_callback_ up front. |
| 240 CompletionCallback* c = write_callback_; |
| 241 write_callback_ = NULL; |
| 242 send_to_address_.reset(); |
| 243 c->Run(rv); |
| 244 } |
| 245 |
| 246 void UDPSocketWin::DidCompleteRead() { |
| 247 DWORD num_bytes, flags; |
| 248 BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_, |
| 249 &num_bytes, FALSE, &flags); |
| 250 WSAResetEvent(read_overlapped_.hEvent); |
| 251 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); |
| 252 if (ok) { |
| 253 if (!ProcessSuccessfulRead(num_bytes)) |
| 254 result = ERR_FAILED; |
| 255 } |
| 256 read_iobuffer_ = NULL; |
| 257 DoReadCallback(result); |
| 258 } |
| 259 |
| 260 bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes) { |
| 261 static base::StatsCounter read_bytes("udp.read_bytes"); |
| 262 read_bytes.Add(num_bytes); |
| 263 |
| 264 // Convert address. |
| 265 if (recv_from_address_) { |
| 266 struct sockaddr* addr = |
| 267 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); |
| 268 if (!recv_from_address_->FromSockAddr(addr, recv_addr_len_)) |
| 269 return false; |
| 270 } |
| 271 |
| 272 return true; |
| 273 } |
| 274 |
| 275 void UDPSocketWin::DidCompleteWrite() { |
| 276 DWORD num_bytes, flags; |
| 277 BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_, |
| 278 &num_bytes, FALSE, &flags); |
| 279 WSAResetEvent(write_overlapped_.hEvent); |
| 280 int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); |
| 281 if (ok) |
| 282 ProcessSuccessfulWrite(num_bytes); |
| 283 write_iobuffer_ = NULL; |
| 284 DoWriteCallback(result); |
| 285 } |
| 286 |
| 287 void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) { |
| 288 static base::StatsCounter write_bytes("udp.write_bytes"); |
| 289 write_bytes.Add(num_bytes); |
| 290 } |
| 291 |
| 292 int UDPSocketWin::InternalRead(IOBuffer* buf, int buf_len) { |
| 293 recv_addr_len_ = sizeof(recv_addr_storage_); |
| 294 struct sockaddr* addr = |
| 295 reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); |
| 296 |
| 297 WSABUF read_buffer; |
| 298 read_buffer.buf = buf->data(); |
| 299 read_buffer.len = buf_len; |
| 300 |
| 301 DWORD flags = 0; |
| 302 DWORD num; |
| 303 AssertEventNotSignaled(read_overlapped_.hEvent); |
| 304 int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, addr, |
| 305 &recv_addr_len_, &read_overlapped_, NULL); |
| 306 if (rv == 0) { |
| 307 if (ResetEventIfSignaled(read_overlapped_.hEvent)) { |
| 308 // Because of how WSARecv fills memory when used asynchronously, Purify |
| 309 // isn't able to detect that it's been initialized, so it scans for 0xcd |
| 310 // in the buffer and reports UMRs (uninitialized memory reads) for those |
| 311 // individual bytes. We override that in PURIFY builds to avoid the |
| 312 // false error reports. |
| 313 // See bug 5297. |
| 314 base::MemoryDebug::MarkAsInitialized(read_buffer.buf, num); |
| 315 if (!ProcessSuccessfulRead(num)) |
| 316 return ERR_FAILED; |
| 317 return static_cast<int>(num); |
| 318 } |
| 319 } else { |
| 320 int os_error = WSAGetLastError(); |
| 321 if (os_error != WSA_IO_PENDING) |
| 322 return MapWinsockError(os_error); |
| 323 } |
| 324 read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_); |
| 325 return ERR_IO_PENDING; |
| 326 } |
| 327 |
| 328 int UDPSocketWin::InternalWrite(IOBuffer* buf, int buf_len) { |
| 329 struct sockaddr_storage addr_storage; |
| 330 size_t addr_len = sizeof(addr_storage); |
| 331 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); |
| 332 |
| 333 // Convert address. |
| 334 if (!send_to_address_.get()) { |
| 335 addr = NULL; |
| 336 addr_len = 0; |
| 337 } else { |
| 338 if (!send_to_address_->ToSockAddr(addr, &addr_len)) |
| 339 return ERR_FAILED; |
| 340 } |
| 341 |
| 342 WSABUF write_buffer; |
| 343 write_buffer.buf = buf->data(); |
| 344 write_buffer.len = buf_len; |
| 345 |
| 346 DWORD flags = 0; |
| 347 DWORD num; |
| 348 AssertEventNotSignaled(write_overlapped_.hEvent); |
| 349 int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, |
| 350 addr, addr_len, &write_overlapped_, NULL); |
| 351 if (rv == 0) { |
| 352 if (ResetEventIfSignaled(write_overlapped_.hEvent)) { |
| 353 ProcessSuccessfulWrite(num); |
| 354 return static_cast<int>(num); |
| 355 } |
| 356 } else { |
| 357 int os_error = WSAGetLastError(); |
| 358 if (os_error != WSA_IO_PENDING) |
| 359 return MapWinsockError(os_error); |
| 360 } |
| 361 |
| 362 write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); |
| 363 return ERR_IO_PENDING; |
| 364 } |
| 365 |
| 366 } // namespace net |
OLD | NEW |