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