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