1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/udp/udp_socket_libevent.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <errno.h>
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <fcntl.h>
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <netdb.h>
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <sys/socket.h>
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/eintr_wrapper.h"
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/logging.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/message_loop.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/metrics/stats_counters.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/io_buffer.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/ip_endpoint.h"
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_errors.h"
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_log.h"
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/net_util.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <netinet/in.h>
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(USE_SYSTEM_LIBEVENT)
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <event.h>
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "third_party/libevent/event.h"
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
32dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenUDPSocketLibevent::UDPSocketLibevent(net::NetLog* net_log,
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     const net::NetLog::Source& source)
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : socket_(kInvalidSocket),
35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      read_watcher_(this),
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      write_watcher_(this),
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      read_buf_len_(0),
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      recv_from_address_(NULL),
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      write_buf_len_(0),
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      read_callback_(NULL),
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      write_callback_(NULL),
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) {
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  scoped_refptr<NetLog::EventParameters> params;
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (source.is_valid())
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    params = new NetLogSourceParameter("source_dependency", source);
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
49dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenUDPSocketLibevent::~UDPSocketLibevent() {
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Close();
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid UDPSocketLibevent::Close() {
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(CalledOnValidThread());
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!is_connected())
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Zero out any pending read/write callback state.
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  read_buf_ = NULL;
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  read_buf_len_ = 0;
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  read_callback_ = NULL;
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  recv_from_address_ = NULL;
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  write_buf_ = NULL;
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  write_buf_len_ = 0;
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  write_callback_ = NULL;
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  send_to_address_.reset();
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(ok);
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ok = write_socket_watcher_.StopWatchingFileDescriptor();
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(ok);
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (HANDLE_EINTR(close(socket_)) < 0)
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PLOG(ERROR) << "close";
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  socket_ = kInvalidSocket;
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::GetPeerAddress(IPEndPoint* address) const {
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(CalledOnValidThread());
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(address);
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!is_connected())
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_SOCKET_NOT_CONNECTED;
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!remote_address_.get()) {
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    struct sockaddr_storage addr_storage;
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    socklen_t addr_len = sizeof(addr_storage);
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (getpeername(socket_, addr, &addr_len))
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return MapSystemError(errno);
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_ptr<IPEndPoint> address(new IPEndPoint());
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!address->FromSockAddr(addr, addr_len))
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return ERR_FAILED;
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    remote_address_.reset(address.release());
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *address = *remote_address_;
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::GetLocalAddress(IPEndPoint* address) const {
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(CalledOnValidThread());
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(address);
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!is_connected())
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return ERR_SOCKET_NOT_CONNECTED;
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!local_address_.get()) {
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    struct sockaddr_storage addr_storage;
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    socklen_t addr_len = sizeof(addr_storage);
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (getsockname(socket_, addr, &addr_len))
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return MapSystemError(errno);
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scoped_ptr<IPEndPoint> address(new IPEndPoint());
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!address->FromSockAddr(addr, addr_len))
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return ERR_FAILED;
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    local_address_.reset(address.release());
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *address = *local_address_;
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint UDPSocketLibevent::Read(IOBuffer* buf,
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            int buf_len,
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            CompletionCallback* callback) {
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return RecvFrom(buf, buf_len, NULL, callback);
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::RecvFrom(IOBuffer* buf,
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                int buf_len,
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                IPEndPoint* address,
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                CompletionCallback* callback) {
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(CalledOnValidThread());
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(kInvalidSocket, socket_);
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!read_callback_);
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!recv_from_address_);
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(callback);  // Synchronous operation not supported
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GT(buf_len, 0);
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int nread = InternalRecvFrom(buf, buf_len, address);
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (nread != ERR_IO_PENDING)
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return nread;
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!MessageLoopForIO::current()->WatchFileDescriptor(
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          socket_, true, MessageLoopForIO::WATCH_READ,
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &read_socket_watcher_, &read_watcher_)) {
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    PLOG(ERROR) << "WatchFileDescriptor failed on read";
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  read_buf_ = buf;
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  read_buf_len_ = buf_len;
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  recv_from_address_ = address;
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  read_callback_ = callback;
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ERR_IO_PENDING;
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::Write(IOBuffer* buf,
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             int buf_len,
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             CompletionCallback* callback) {
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return SendToOrWrite(buf, buf_len, NULL, callback);
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint UDPSocketLibevent::SendTo(IOBuffer* buf,
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              int buf_len,
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              const IPEndPoint& address,
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              CompletionCallback* callback) {
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return SendToOrWrite(buf, buf_len, &address, callback);
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::SendToOrWrite(IOBuffer* buf,
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     int buf_len,
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     const IPEndPoint* address,
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     CompletionCallback* callback) {
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(CalledOnValidThread());
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(kInvalidSocket, socket_);
179dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!write_callback_);
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(callback);  // Synchronous operation not supported
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GT(buf_len, 0);
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int nwrite = InternalSendTo(buf, buf_len, address);
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (nwrite >= 0) {
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter write_bytes("udp.write_bytes");
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    write_bytes.Add(nwrite);
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return nwrite;
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (errno != EAGAIN && errno != EWOULDBLOCK)
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!MessageLoopForIO::current()->WatchFileDescriptor(
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          socket_, true, MessageLoopForIO::WATCH_WRITE,
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          &write_socket_watcher_, &write_watcher_)) {
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  write_buf_ = buf;
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  write_buf_len_ = buf_len;
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!send_to_address_.get());
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (address) {
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    send_to_address_.reset(new IPEndPoint(*address));
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  write_callback_ = callback;
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return ERR_IO_PENDING;
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::Connect(const IPEndPoint& address) {
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!is_connected());
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!remote_address_.get());
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int rv = CreateSocket(address);
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return rv;
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr_storage addr_storage;
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t addr_len = sizeof(addr_storage);
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!address.ToSockAddr(addr, &addr_len))
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_FAILED;
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  rv = HANDLE_EINTR(connect(socket_, addr, addr_len));
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  remote_address_.reset(new IPEndPoint(address));
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::Bind(const IPEndPoint& address) {
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!is_connected());
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!local_address_.get());
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int rv = CreateSocket(address);
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return rv;
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr_storage addr_storage;
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t addr_len = sizeof(addr_storage);
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!address.ToSockAddr(addr, &addr_len))
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return ERR_FAILED;
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  rv = bind(socket_, addr, addr_len);
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (rv < 0)
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  local_address_.reset();
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return rv;
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid UDPSocketLibevent::DoReadCallback(int rv) {
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(rv, ERR_IO_PENDING);
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(read_callback_);
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // since Run may result in Read being called, clear read_callback_ up front.
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CompletionCallback* c = read_callback_;
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  read_callback_ = NULL;
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  c->Run(rv);
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid UDPSocketLibevent::DoWriteCallback(int rv) {
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_NE(rv, ERR_IO_PENDING);
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(write_callback_);
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // since Run may result in Write being called, clear write_callback_ up front.
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CompletionCallback* c = write_callback_;
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  write_callback_ = NULL;
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  c->Run(rv);
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid UDPSocketLibevent::DidCompleteRead() {
272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int result = InternalRecvFrom(read_buf_, read_buf_len_, recv_from_address_);
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result != ERR_IO_PENDING) {
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_buf_ = NULL;
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_buf_len_ = 0;
276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    recv_from_address_ = NULL;
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DCHECK(ok);
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DoReadCallback(result);
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0);
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (socket_ == kInvalidSocket)
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return MapSystemError(errno);
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (SetNonBlocking(socket_)) {
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    const int err = MapSystemError(errno);
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Close();
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return err;
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return OK;
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid UDPSocketLibevent::DidCompleteWrite() {
296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int result = InternalSendTo(write_buf_, write_buf_len_,
297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              send_to_address_.get());
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result >= 0) {
299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter write_bytes("udp.write_bytes");
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    write_bytes.Add(result);
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result = MapSystemError(errno);
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (result != ERR_IO_PENDING) {
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    write_buf_ = NULL;
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    write_buf_len_ = 0;
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    send_to_address_.reset();
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    write_socket_watcher_.StopWatchingFileDescriptor();
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    DoWriteCallback(result);
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len,
315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                        IPEndPoint* address) {
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int bytes_transferred;
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int flags = 0;
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr_storage addr_storage;
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  socklen_t addr_len = sizeof(addr_storage);
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bytes_transferred =
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      HANDLE_EINTR(recvfrom(socket_,
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            buf->data(),
326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            buf_len,
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                            flags,
328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            addr,
329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            &addr_len));
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int result;
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (bytes_transferred >= 0) {
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    result = bytes_transferred;
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    base::StatsCounter read_bytes("udp.read_bytes");
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    read_bytes.Add(bytes_transferred);
335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (address) {
336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!address->FromSockAddr(addr, addr_len))
337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        result = ERR_FAILED;
338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    result = MapSystemError(errno);
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return result;
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len,
346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      const IPEndPoint* address) {
347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr_storage addr_storage;
348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  size_t addr_len = sizeof(addr_storage);
349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!address) {
352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    addr = NULL;
353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    addr_len = 0;
354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!address->ToSockAddr(addr, &addr_len))
356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return ERR_FAILED;
357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return HANDLE_EINTR(sendto(socket_,
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             buf->data(),
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             buf_len,
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             0,
363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             addr,
364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                             addr_len));
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
368