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