Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: net/udp/udp_socket_libevent.cc

Issue 8200011: Add NetLog support to UDP sockets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/udp/udp_socket_libevent.h" 5 #include "net/udp/udp_socket_libevent.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netdb.h> 9 #include <netdb.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 11
12 #include "base/eintr_wrapper.h" 12 #include "base/eintr_wrapper.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop.h" 14 #include "base/message_loop.h"
15 #include "base/metrics/stats_counters.h" 15 #include "base/metrics/stats_counters.h"
16 #include "base/rand_util.h" 16 #include "base/rand_util.h"
17 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h" 18 #include "net/base/ip_endpoint.h"
19 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h" 20 #include "net/base/net_log.h"
21 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
22 #include "net/udp/udp_data_transfer_param.h"
22 #if defined(OS_POSIX) 23 #if defined(OS_POSIX)
23 #include <netinet/in.h> 24 #include <netinet/in.h>
24 #endif 25 #endif
25 26
26 namespace { 27 namespace {
27 28
28 static const int kBindRetries = 10; 29 static const int kBindRetries = 10;
29 static const int kPortStart = 1024; 30 static const int kPortStart = 1024;
30 static const int kPortEnd = 65535; 31 static const int kPortEnd = 65535;
31 32
32 } // namespace net 33 } // namespace net
33 34
34 namespace net { 35 namespace net {
35 36
36 UDPSocketLibevent::UDPSocketLibevent( 37 UDPSocketLibevent::UDPSocketLibevent(
37 DatagramSocket::BindType bind_type, 38 DatagramSocket::BindType bind_type,
38 const RandIntCallback& rand_int_cb, 39 const RandIntCallback& rand_int_cb,
39 net::NetLog* net_log, 40 net::NetLog* net_log,
40 const net::NetLog::Source& source) 41 const net::NetLog::Source& source)
41 : socket_(kInvalidSocket), 42 : socket_(kInvalidSocket),
42 bind_type_(bind_type), 43 bind_type_(bind_type),
43 rand_int_cb_(rand_int_cb), 44 rand_int_cb_(rand_int_cb),
44 read_watcher_(this), 45 read_watcher_(this),
45 write_watcher_(this), 46 write_watcher_(this),
46 read_buf_len_(0), 47 read_buf_len_(0),
47 recv_from_address_(NULL), 48 recv_from_address_(NULL),
48 write_buf_len_(0), 49 write_buf_len_(0),
49 read_callback_(NULL), 50 read_callback_(NULL),
50 write_callback_(NULL), 51 write_callback_(NULL),
51 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 52 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) {
52 scoped_refptr<NetLog::EventParameters> params; 53 scoped_refptr<NetLog::EventParameters> params;
53 if (source.is_valid()) 54 if (source.is_valid())
54 params = new NetLogSourceParameter("source_dependency", source); 55 params = new NetLogSourceParameter("source_dependency", source);
55 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 56 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
56 if (bind_type == DatagramSocket::RANDOM_BIND) 57 if (bind_type == DatagramSocket::RANDOM_BIND)
57 DCHECK(!rand_int_cb.is_null()); 58 DCHECK(!rand_int_cb.is_null());
58 } 59 }
59 60
60 UDPSocketLibevent::~UDPSocketLibevent() { 61 UDPSocketLibevent::~UDPSocketLibevent() {
61 Close(); 62 Close();
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 DCHECK_GT(buf_len, 0); 152 DCHECK_GT(buf_len, 0);
152 153
153 int nread = InternalRecvFrom(buf, buf_len, address); 154 int nread = InternalRecvFrom(buf, buf_len, address);
154 if (nread != ERR_IO_PENDING) 155 if (nread != ERR_IO_PENDING)
155 return nread; 156 return nread;
156 157
157 if (!MessageLoopForIO::current()->WatchFileDescriptor( 158 if (!MessageLoopForIO::current()->WatchFileDescriptor(
158 socket_, true, MessageLoopForIO::WATCH_READ, 159 socket_, true, MessageLoopForIO::WATCH_READ,
159 &read_socket_watcher_, &read_watcher_)) { 160 &read_socket_watcher_, &read_watcher_)) {
160 PLOG(ERROR) << "WatchFileDescriptor failed on read"; 161 PLOG(ERROR) << "WatchFileDescriptor failed on read";
161 return MapSystemError(errno); 162 return LogRead(MapSystemError(errno), NULL, 0, NULL);
Sergey Ulanov 2011/10/18 01:29:25 LogRead() always logs |result|. Maybe change this
mmenke 2011/10/18 15:16:58 Done.
162 } 163 }
163 164
164 read_buf_ = buf; 165 read_buf_ = buf;
165 read_buf_len_ = buf_len; 166 read_buf_len_ = buf_len;
166 recv_from_address_ = address; 167 recv_from_address_ = address;
167 read_callback_ = callback; 168 read_callback_ = callback;
168 return ERR_IO_PENDING; 169 return ERR_IO_PENDING;
169 } 170 }
170 171
171 int UDPSocketLibevent::Write(IOBuffer* buf, 172 int UDPSocketLibevent::Write(IOBuffer* buf,
(...skipping 12 matching lines...) Expand all
184 int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf, 185 int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf,
185 int buf_len, 186 int buf_len,
186 const IPEndPoint* address, 187 const IPEndPoint* address,
187 OldCompletionCallback* callback) { 188 OldCompletionCallback* callback) {
188 DCHECK(CalledOnValidThread()); 189 DCHECK(CalledOnValidThread());
189 DCHECK_NE(kInvalidSocket, socket_); 190 DCHECK_NE(kInvalidSocket, socket_);
190 DCHECK(!write_callback_); 191 DCHECK(!write_callback_);
191 DCHECK(callback); // Synchronous operation not supported 192 DCHECK(callback); // Synchronous operation not supported
192 DCHECK_GT(buf_len, 0); 193 DCHECK_GT(buf_len, 0);
193 194
194 int nwrite = InternalSendTo(buf, buf_len, address); 195 int result = InternalSendTo(buf, buf_len, address);
195 if (nwrite >= 0) { 196 if (result != ERR_IO_PENDING)
196 base::StatsCounter write_bytes("udp.write_bytes"); 197 return result;
197 write_bytes.Add(nwrite);
198 return nwrite;
199 }
200 if (errno != EAGAIN && errno != EWOULDBLOCK)
201 return MapSystemError(errno);
202 198
203 if (!MessageLoopForIO::current()->WatchFileDescriptor( 199 if (!MessageLoopForIO::current()->WatchFileDescriptor(
204 socket_, true, MessageLoopForIO::WATCH_WRITE, 200 socket_, true, MessageLoopForIO::WATCH_WRITE,
205 &write_socket_watcher_, &write_watcher_)) { 201 &write_socket_watcher_, &write_watcher_)) {
206 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 202 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
207 return MapSystemError(errno); 203 return LogWrite(MapSystemError(errno), NULL, NULL);
208 } 204 }
209 205
210 write_buf_ = buf; 206 write_buf_ = buf;
211 write_buf_len_ = buf_len; 207 write_buf_len_ = buf_len;
212 DCHECK(!send_to_address_.get()); 208 DCHECK(!send_to_address_.get());
213 if (address) { 209 if (address) {
214 send_to_address_.reset(new IPEndPoint(*address)); 210 send_to_address_.reset(new IPEndPoint(*address));
215 } 211 }
216 write_callback_ = callback; 212 write_callback_ = callback;
217 return ERR_IO_PENDING; 213 return ERR_IO_PENDING;
218 } 214 }
219 215
220 int UDPSocketLibevent::Connect(const IPEndPoint& address) { 216 int UDPSocketLibevent::Connect(const IPEndPoint& address) {
217 net_log_.BeginEvent(
218 NetLog::TYPE_UDP_CONNECT,
219 make_scoped_refptr(new NetLogStringParameter("address",
220 address.ToString())));
221 int rv = InternalConnect(address);
222 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv);
223 return rv;
224 }
225
226 int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) {
221 DCHECK(!is_connected()); 227 DCHECK(!is_connected());
222 DCHECK(!remote_address_.get()); 228 DCHECK(!remote_address_.get());
223 int rv = CreateSocket(address); 229 int rv = CreateSocket(address);
224 if (rv < 0) 230 if (rv < 0)
225 return rv; 231 return rv;
226 232
227 if (bind_type_ == DatagramSocket::RANDOM_BIND) 233 if (bind_type_ == DatagramSocket::RANDOM_BIND)
228 rv = RandomBind(address); 234 rv = RandomBind(address);
229 // else connect() does the DatagramSocket::DEFAULT_BIND 235 // else connect() does the DatagramSocket::DEFAULT_BIND
230 236
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 if (result != ERR_IO_PENDING) { 288 if (result != ERR_IO_PENDING) {
283 read_buf_ = NULL; 289 read_buf_ = NULL;
284 read_buf_len_ = 0; 290 read_buf_len_ = 0;
285 recv_from_address_ = NULL; 291 recv_from_address_ = NULL;
286 bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); 292 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
287 DCHECK(ok); 293 DCHECK(ok);
288 DoReadCallback(result); 294 DoReadCallback(result);
289 } 295 }
290 } 296 }
291 297
298 int UDPSocketLibevent::LogRead(int result,
299 const char* bytes,
300 socklen_t addr_len,
301 const sockaddr* addr) const {
302 if (result < 0) {
303 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result);
304 return result;
305 }
306
307 if (net_log_.IsLoggingAllEvents()) {
308 DCHECK(addr_len > 0);
309 DCHECK(addr);
310
311 IPEndPoint address;
312 bool is_address_valid = address.FromSockAddr(addr, addr_len);
313 net_log_.AddEvent(
314 NetLog::TYPE_UDP_BYTES_RECEIVED,
315 make_scoped_refptr(
316 new UDPDataTransferNetLogParam(
317 result, bytes, net_log_.IsLoggingBytes(),
318 is_address_valid ? &address : NULL)));
319 }
320
321 base::StatsCounter read_bytes("udp.read_bytes");
322 read_bytes.Add(result);
323 return result;
324 }
325
292 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { 326 int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) {
293 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); 327 socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0);
294 if (socket_ == kInvalidSocket) 328 if (socket_ == kInvalidSocket)
295 return MapSystemError(errno); 329 return MapSystemError(errno);
296 if (SetNonBlocking(socket_)) { 330 if (SetNonBlocking(socket_)) {
297 const int err = MapSystemError(errno); 331 const int err = MapSystemError(errno);
298 Close(); 332 Close();
299 return err; 333 return err;
300 } 334 }
301 return OK; 335 return OK;
302 } 336 }
303 337
304 void UDPSocketLibevent::DidCompleteWrite() { 338 void UDPSocketLibevent::DidCompleteWrite() {
305 int result = InternalSendTo(write_buf_, write_buf_len_, 339 int result = InternalSendTo(write_buf_, write_buf_len_,
306 send_to_address_.get()); 340 send_to_address_.get());
307 if (result >= 0) {
308 base::StatsCounter write_bytes("udp.write_bytes");
309 write_bytes.Add(result);
310 } else {
311 result = MapSystemError(errno);
312 }
313 341
314 if (result != ERR_IO_PENDING) { 342 if (result != ERR_IO_PENDING) {
315 write_buf_ = NULL; 343 write_buf_ = NULL;
316 write_buf_len_ = 0; 344 write_buf_len_ = 0;
317 send_to_address_.reset(); 345 send_to_address_.reset();
318 write_socket_watcher_.StopWatchingFileDescriptor(); 346 write_socket_watcher_.StopWatchingFileDescriptor();
319 DoWriteCallback(result); 347 DoWriteCallback(result);
320 } 348 }
321 } 349 }
322 350
351 int UDPSocketLibevent::LogWrite(int result,
352 const char* bytes,
353 const IPEndPoint* address) const {
354 if (result < 0) {
355 net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result);
356 return result;
357 }
358
359 if (net_log_.IsLoggingAllEvents()) {
360 net_log_.AddEvent(
361 NetLog::TYPE_UDP_BYTES_SENT,
362 make_scoped_refptr(
363 new UDPDataTransferNetLogParam(result, bytes,
364 net_log_.IsLoggingBytes(),
365 address)));
366 }
367
368 base::StatsCounter write_bytes("udp.write_bytes");
369 write_bytes.Add(result);
370 return result;
371 }
372
323 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, 373 int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len,
324 IPEndPoint* address) { 374 IPEndPoint* address) {
325 int bytes_transferred; 375 int bytes_transferred;
326 int flags = 0; 376 int flags = 0;
327 377
328 struct sockaddr_storage addr_storage; 378 struct sockaddr_storage addr_storage;
329 socklen_t addr_len = sizeof(addr_storage); 379 socklen_t addr_len = sizeof(addr_storage);
330 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 380 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
331 381
332 bytes_transferred = 382 bytes_transferred =
333 HANDLE_EINTR(recvfrom(socket_, 383 HANDLE_EINTR(recvfrom(socket_,
334 buf->data(), 384 buf->data(),
335 buf_len, 385 buf_len,
336 flags, 386 flags,
337 addr, 387 addr,
338 &addr_len)); 388 &addr_len));
339 int result; 389 int result;
340 if (bytes_transferred >= 0) { 390 if (bytes_transferred >= 0) {
341 result = bytes_transferred; 391 result = bytes_transferred;
342 base::StatsCounter read_bytes("udp.read_bytes"); 392 if (!address->FromSockAddr(addr, addr_len))
343 read_bytes.Add(bytes_transferred); 393 result = ERR_FAILED;
344 if (address) {
345 if (!address->FromSockAddr(addr, addr_len))
346 result = ERR_FAILED;
347 }
348 } else { 394 } else {
349 result = MapSystemError(errno); 395 result = MapSystemError(errno);
350 } 396 }
397 if (result != ERR_IO_PENDING) {
Sergey Ulanov 2011/10/18 01:29:25 nit: remove braces
mmenke 2011/10/18 15:16:58 Done.
398 LogRead(result, buf->data(), addr_len, addr);
399 }
351 return result; 400 return result;
352 } 401 }
353 402
354 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, 403 int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len,
355 const IPEndPoint* address) { 404 const IPEndPoint* address) {
356 struct sockaddr_storage addr_storage; 405 struct sockaddr_storage addr_storage;
357 size_t addr_len = sizeof(addr_storage); 406 size_t addr_len = sizeof(addr_storage);
358 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 407 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
359 408
360 if (!address) { 409 if (!address) {
361 addr = NULL; 410 addr = NULL;
362 addr_len = 0; 411 addr_len = 0;
363 } else { 412 } else {
364 if (!address->ToSockAddr(addr, &addr_len)) 413 if (!address->ToSockAddr(addr, &addr_len))
365 return ERR_FAILED; 414 return LogWrite(ERR_FAILED, NULL, NULL);
366 } 415 }
367 416
368 return HANDLE_EINTR(sendto(socket_, 417 int result = HANDLE_EINTR(sendto(socket_,
369 buf->data(), 418 buf->data(),
370 buf_len, 419 buf_len,
371 0, 420 0,
372 addr, 421 addr,
373 addr_len)); 422 addr_len));
423 if (result < 0)
424 result = MapSystemError(errno);
425 if (result != ERR_IO_PENDING)
426 LogWrite(result, buf->data(), address);
427 return result;
374 } 428 }
375 429
376 int UDPSocketLibevent::DoBind(const IPEndPoint& address) { 430 int UDPSocketLibevent::DoBind(const IPEndPoint& address) {
377 struct sockaddr_storage addr_storage; 431 struct sockaddr_storage addr_storage;
378 size_t addr_len = sizeof(addr_storage); 432 size_t addr_len = sizeof(addr_storage);
379 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 433 struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage);
380 if (!address.ToSockAddr(addr, &addr_len)) 434 if (!address.ToSockAddr(addr, &addr_len))
381 return ERR_UNEXPECTED; 435 return ERR_UNEXPECTED;
382 int rv = bind(socket_, addr, addr_len); 436 int rv = bind(socket_, addr, addr_len);
383 return rv < 0 ? MapSystemError(errno) : rv; 437 return rv < 0 ? MapSystemError(errno) : rv;
384 } 438 }
385 439
386 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { 440 int UDPSocketLibevent::RandomBind(const IPEndPoint& address) {
387 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); 441 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
388 442
389 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. 443 // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s.
390 IPAddressNumber ip(address.address().size()); 444 IPAddressNumber ip(address.address().size());
391 445
392 for (int i = 0; i < kBindRetries; ++i) { 446 for (int i = 0; i < kBindRetries; ++i) {
393 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); 447 int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd)));
394 if (rv == OK || rv != ERR_ADDRESS_IN_USE) 448 if (rv == OK || rv != ERR_ADDRESS_IN_USE)
395 return rv; 449 return rv;
396 } 450 }
397 return DoBind(IPEndPoint(ip, 0)); 451 return DoBind(IPEndPoint(ip, 0));
398 } 452 }
399 453
400 } // namespace net 454 } // namespace net
OLDNEW
« no previous file with comments | « net/udp/udp_socket_libevent.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698