diff options
author | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-18 20:08:10 +0000 |
---|---|---|
committer | mmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-18 20:08:10 +0000 |
commit | 8866f623dfd914c9f4c26ab96f90aecf4a372ef9 (patch) | |
tree | 4f45fa083309b6934e1888c27c9df2344cd391f0 /net | |
parent | def979a39bd25dfb24c80138699ffb359c495757 (diff) | |
download | chromium_src-8866f623dfd914c9f4c26ab96f90aecf4a372ef9.zip chromium_src-8866f623dfd914c9f4c26ab96f90aecf4a372ef9.tar.gz chromium_src-8866f623dfd914c9f4c26ab96f90aecf4a372ef9.tar.bz2 |
Add NetLog support to UDP sockets.
BUG=99508
TEST=UDPSocketTest.Connect
Review URL: http://codereview.chromium.org/8200011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@106109 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/net_log.cc | 14 | ||||
-rw-r--r-- | net/base/net_log.h | 9 | ||||
-rw-r--r-- | net/base/net_log_event_type_list.h | 62 | ||||
-rw-r--r-- | net/base/net_log_source_type_list.h | 3 | ||||
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_win.cc | 2 | ||||
-rw-r--r-- | net/udp/udp_data_transfer_param.cc | 36 | ||||
-rw-r--r-- | net/udp/udp_data_transfer_param.h | 40 | ||||
-rw-r--r-- | net/udp/udp_socket_libevent.cc | 120 | ||||
-rw-r--r-- | net/udp/udp_socket_libevent.h | 12 | ||||
-rw-r--r-- | net/udp/udp_socket_unittest.cc | 71 | ||||
-rw-r--r-- | net/udp/udp_socket_win.cc | 118 | ||||
-rw-r--r-- | net/udp/udp_socket_win.h | 19 |
13 files changed, 416 insertions, 92 deletions
diff --git a/net/base/net_log.cc b/net/base/net_log.cc index 6509801..259786ef 100644 --- a/net/base/net_log.cc +++ b/net/base/net_log.cc @@ -192,9 +192,18 @@ void BoundNetLog::EndEvent( AddEntry(event_type, NetLog::PHASE_END, params); } +void BoundNetLog::AddEventWithNetErrorCode(NetLog::EventType event_type, + int net_error) const { + DCHECK_GT(0, net_error); + DCHECK_NE(ERR_IO_PENDING, net_error); + AddEvent( + event_type, + make_scoped_refptr(new NetLogIntegerParameter("net_error", net_error))); +} + void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type, int net_error) const { - DCHECK_NE(net_error, ERR_IO_PENDING); + DCHECK_NE(ERR_IO_PENDING, net_error); if (net_error >= 0) { EndEvent(event_type, NULL); } else { @@ -205,7 +214,8 @@ void BoundNetLog::EndEventWithNetErrorCode(NetLog::EventType event_type, } void BoundNetLog::AddByteTransferEvent(NetLog::EventType event_type, - int byte_count, char* bytes) const { + int byte_count, + const char* bytes) const { scoped_refptr<NetLog::EventParameters> params; if (IsLoggingBytes()) { params = new NetLogBytesTransferredParameter(byte_count, bytes); diff --git a/net/base/net_log.h b/net/base/net_log.h index 51f6f65..8a5f5ff 100644 --- a/net/base/net_log.h +++ b/net/base/net_log.h @@ -243,6 +243,13 @@ class NET_EXPORT BoundNetLog { void EndEvent(NetLog::EventType event_type, const scoped_refptr<NetLog::EventParameters>& params) const; + // Just like AddEvent, except |net_error| is a net error code. A parameter + // called "net_error" with the indicated value will be recorded for the event. + // |net_error| must be negative, and not ERR_IO_PENDING, as it's not a true + // error. + void AddEventWithNetErrorCode(NetLog::EventType event_type, + int net_error) const; + // Just like EndEvent, except |net_error| is a net error code. If it's // negative, a parameter called "net_error" with a value of |net_error| is // associated with the event. Otherwise, the end event has no parameters. @@ -253,7 +260,7 @@ class NET_EXPORT BoundNetLog { // Logs a byte transfer event to the NetLog. Determines whether to log the // received bytes or not based on the current logging level. void AddByteTransferEvent(NetLog::EventType event_type, - int byte_count, char* bytes) const; + int byte_count, const char* bytes) const; NetLog::LogLevel GetLogLevel() const; diff --git a/net/base/net_log_event_type_list.h b/net/base/net_log_event_type_list.h index 74fbe08..08c554b 100644 --- a/net/base/net_log_event_type_list.h +++ b/net/base/net_log_event_type_list.h @@ -288,6 +288,19 @@ EVENT_TYPE(WAITING_FOR_PROXY_RESOLVER_THREAD) EVENT_TYPE(SUBMITTED_TO_RESOLVER_THREAD) // ------------------------------------------------------------------------ +// Socket (Shared by stream and datagram sockets) +// ------------------------------------------------------------------------ + +// Marks the begin/end of a socket (TCP/SOCKS/SSL/UDP). +// +// The BEGIN phase contains the following parameters: +// +// { +// "source_dependency": <Source identifier for the controlling entity>, +// } +EVENT_TYPE(SOCKET_ALIVE) + +// ------------------------------------------------------------------------ // StreamSocket // ------------------------------------------------------------------------ @@ -300,10 +313,11 @@ EVENT_TYPE(SUBMITTED_TO_RESOLVER_THREAD) // "address_list": <List of network address strings>, // } // -// And the END event will contain the following parameters on failure: +// And the END event will contain the following parameters: // // { -// "net_error": <Net integer error code>, +// "net_error": <Net integer error code, on error>, +// "source_address": <Local source address of the connection, on success>, // } EVENT_TYPE(TCP_CONNECT) @@ -335,9 +349,6 @@ EVENT_TYPE(TCP_CONNECT_ATTEMPT) // } EVENT_TYPE(TCP_ACCEPT) -// Marks the begin/end of a socket (TCP/SOCKS/SSL). -EVENT_TYPE(SOCKET_ALIVE) - // This event is logged to the socket stream whenever the socket is // acquired/released via a ClientSocketHandle. // @@ -476,6 +487,45 @@ EVENT_TYPE(SOCKET_BYTES_RECEIVED) EVENT_TYPE(SSL_SOCKET_BYTES_RECEIVED) // ------------------------------------------------------------------------ +// DatagramSocket +// ------------------------------------------------------------------------ + +// The start/end of a UDP client connecting. +// +// The START event contains these parameters: +// +// { +// "address": <Remote address being connected to>, +// } +// +// And the END event will contain the following parameter: +// +// { +// "net_error": <Net integer error code, on failure>, +// } +EVENT_TYPE(UDP_CONNECT) + +// The specified number of bytes were transferred on the socket. +// The following parameters are attached: +// { +// "address": <Remote address of data transfer. Not present when not +// specified for UDP_BYTES_SENT events>, +// "byte_count": <Number of bytes that were just received>, +// "hex_encoded_bytes": <The exact bytes received, as a hexadecimal string. +// Only present when byte logging is enabled>, +// } +EVENT_TYPE(UDP_BYTES_RECEIVED) +EVENT_TYPE(UDP_BYTES_SENT) + +// Logged when an error occurs while reading or writing to/from a UDP socket. +// The following parameters are attached: +// { +// "net_error": <Net error code>, +// } +EVENT_TYPE(UDP_RECEIVE_ERROR) +EVENT_TYPE(UDP_SEND_ERROR) + +// ------------------------------------------------------------------------ // ClientSocketPoolBase::ConnectJob // ------------------------------------------------------------------------ @@ -1141,9 +1191,9 @@ EVENT_TYPE(THROTTLING_GOT_CUSTOM_RETRY_AFTER) // The END phase contains the following parameters: // // { -// "net_error": <The net error code for the failure>, // "ip_address_list": <The result of the resolution process, // an IPAddressList> +// "net_error": <The net error code for the failure, if any>, // } EVENT_TYPE(DNS_TRANSACTION) diff --git a/net/base/net_log_source_type_list.h b/net/base/net_log_source_type_list.h index de80d14..f54078d 100644 --- a/net/base/net_log_source_type_list.h +++ b/net/base/net_log_source_type_list.h @@ -22,5 +22,6 @@ SOURCE_TYPE(HTTP_STREAM_JOB, 11) SOURCE_TYPE(EXPONENTIAL_BACKOFF_THROTTLING, 12) SOURCE_TYPE(DNS_TRANSACTION, 13) SOURCE_TYPE(ASYNC_HOST_RESOLVER_REQUEST, 14) +SOURCE_TYPE(UDP_SOCKET, 15) -SOURCE_TYPE(COUNT, 15) // Always keep this as the last entry. +SOURCE_TYPE(COUNT, 16) // Always keep this as the last entry. diff --git a/net/net.gyp b/net/net.gyp index cfccfa3..9f059b0 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -631,6 +631,8 @@ 'udp/datagram_socket.h', 'udp/udp_client_socket.cc', 'udp/udp_client_socket.h', + 'udp/udp_data_transfer_param.cc', + 'udp/udp_data_transfer_param.h', 'udp/udp_server_socket.cc', 'udp/udp_server_socket.h', 'udp/udp_socket.h', diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc index 9b63765..ca5ad63 100644 --- a/net/socket/tcp_client_socket_win.cc +++ b/net/socket/tcp_client_socket_win.cc @@ -805,7 +805,7 @@ void TCPClientSocketWin::LogConnectCompletion(int net_error) { sizeof(source_address)); net_log_.EndEvent(NetLog::TYPE_TCP_CONNECT, make_scoped_refptr(new NetLogStringParameter( - "source address", + "source_address", source_address_str))); } diff --git a/net/udp/udp_data_transfer_param.cc b/net/udp/udp_data_transfer_param.cc new file mode 100644 index 0000000..808cd8b --- /dev/null +++ b/net/udp/udp_data_transfer_param.cc @@ -0,0 +1,36 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/string_number_conversions.h" +#include "base/values.h" +#include "net/base/ip_endpoint.h" +#include "net/udp/udp_data_transfer_param.h" + +namespace net { + +UDPDataTransferNetLogParam::UDPDataTransferNetLogParam( + int byte_count, + const char* bytes, + bool log_bytes, + const IPEndPoint* address) + : byte_count_(byte_count), + hex_encoded_bytes_(log_bytes ? base::HexEncode(bytes, byte_count) : "") { + if (address) + address_.reset(new IPEndPoint(*address)); +} + +UDPDataTransferNetLogParam::~UDPDataTransferNetLogParam() { +} + +Value* UDPDataTransferNetLogParam::ToValue() const { + DictionaryValue* dict = new DictionaryValue(); + dict->SetInteger("byte_count", byte_count_); + if (!hex_encoded_bytes_.empty()) + dict->SetString("hex_encoded_bytes", hex_encoded_bytes_); + if (address_.get()) + dict->SetString("address", address_->ToString()); + return dict; +} + +} // namespace net diff --git a/net/udp/udp_data_transfer_param.h b/net/udp/udp_data_transfer_param.h new file mode 100644 index 0000000..1ef86fd --- /dev/null +++ b/net/udp/udp_data_transfer_param.h @@ -0,0 +1,40 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_UDP_UDP_DATA_TRANSFER_PARAM_H_ +#define NET_UDP_UDP_DATA_TRANSFER_PARAM_H_ +#pragma once + +#include <string> + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/net_log.h" + +namespace net { + +class IPEndPoint; + +// NetLog parameter to describe a UDP receive/send event. Each event has a +// byte count, and may optionally have transferred bytes and an IPEndPoint as +// well. +class UDPDataTransferNetLogParam : public NetLog::EventParameters { + public: + // |bytes| are only logged when |log_bytes| is non-NULL. + // |address| may be NULL. + UDPDataTransferNetLogParam(int byte_count, const char* bytes, bool log_bytes, + const IPEndPoint* address); + virtual ~UDPDataTransferNetLogParam(); + + virtual base::Value* ToValue() const OVERRIDE; + + private: + const int byte_count_; + const std::string hex_encoded_bytes_; + scoped_ptr<IPEndPoint> address_; +}; + +} // namespace net + +#endif // NET_BASE_ADDRESS_LIST_NET_LOG_PARAM_H_ diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc index 1e790df..87cd9f6 100644 --- a/net/udp/udp_socket_libevent.cc +++ b/net/udp/udp_socket_libevent.cc @@ -19,6 +19,7 @@ #include "net/base/net_errors.h" #include "net/base/net_log.h" #include "net/base/net_util.h" +#include "net/udp/udp_data_transfer_param.h" #if defined(OS_POSIX) #include <netinet/in.h> #endif @@ -48,7 +49,7 @@ UDPSocketLibevent::UDPSocketLibevent( write_buf_len_(0), read_callback_(NULL), write_callback_(NULL), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { scoped_refptr<NetLog::EventParameters> params; if (source.is_valid()) params = new NetLogSourceParameter("source_dependency", source); @@ -158,7 +159,9 @@ int UDPSocketLibevent::RecvFrom(IOBuffer* buf, socket_, true, MessageLoopForIO::WATCH_READ, &read_socket_watcher_, &read_watcher_)) { PLOG(ERROR) << "WatchFileDescriptor failed on read"; - return MapSystemError(errno); + int result = MapSystemError(errno); + LogRead(result, NULL, 0, NULL); + return result; } read_buf_ = buf; @@ -191,20 +194,17 @@ int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf, DCHECK(callback); // Synchronous operation not supported DCHECK_GT(buf_len, 0); - int nwrite = InternalSendTo(buf, buf_len, address); - if (nwrite >= 0) { - base::StatsCounter write_bytes("udp.write_bytes"); - write_bytes.Add(nwrite); - return nwrite; - } - if (errno != EAGAIN && errno != EWOULDBLOCK) - return MapSystemError(errno); + int result = InternalSendTo(buf, buf_len, address); + if (result != ERR_IO_PENDING) + return result; if (!MessageLoopForIO::current()->WatchFileDescriptor( socket_, true, MessageLoopForIO::WATCH_WRITE, &write_socket_watcher_, &write_watcher_)) { DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; - return MapSystemError(errno); + int result = MapSystemError(errno); + LogWrite(result, NULL, NULL); + return result; } write_buf_ = buf; @@ -218,6 +218,16 @@ int UDPSocketLibevent::SendToOrWrite(IOBuffer* buf, } int UDPSocketLibevent::Connect(const IPEndPoint& address) { + net_log_.BeginEvent( + NetLog::TYPE_UDP_CONNECT, + make_scoped_refptr(new NetLogStringParameter("address", + address.ToString()))); + int rv = InternalConnect(address); + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); + return rv; +} + +int UDPSocketLibevent::InternalConnect(const IPEndPoint& address) { DCHECK(CalledOnValidThread()); DCHECK(!is_connected()); DCHECK(!remote_address_.get()); @@ -307,6 +317,33 @@ void UDPSocketLibevent::DidCompleteRead() { } } +void UDPSocketLibevent::LogRead(int result, + const char* bytes, + socklen_t addr_len, + const sockaddr* addr) const { + if (result < 0) { + net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); + return; + } + + if (net_log_.IsLoggingAllEvents()) { + DCHECK(addr_len > 0); + DCHECK(addr); + + IPEndPoint address; + bool is_address_valid = address.FromSockAddr(addr, addr_len); + net_log_.AddEvent( + NetLog::TYPE_UDP_BYTES_RECEIVED, + make_scoped_refptr( + new UDPDataTransferNetLogParam( + result, bytes, net_log_.IsLoggingBytes(), + is_address_valid ? &address : NULL))); + } + + base::StatsCounter read_bytes("udp.read_bytes"); + read_bytes.Add(result); +} + int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); if (socket_ == kInvalidSocket) @@ -322,12 +359,6 @@ int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { void UDPSocketLibevent::DidCompleteWrite() { int result = InternalSendTo(write_buf_, write_buf_len_, send_to_address_.get()); - if (result >= 0) { - base::StatsCounter write_bytes("udp.write_bytes"); - write_bytes.Add(result); - } else { - result = MapSystemError(errno); - } if (result != ERR_IO_PENDING) { write_buf_ = NULL; @@ -338,6 +369,27 @@ void UDPSocketLibevent::DidCompleteWrite() { } } +void UDPSocketLibevent::LogWrite(int result, + const char* bytes, + const IPEndPoint* address) const { + if (result < 0) { + net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); + return; + } + + if (net_log_.IsLoggingAllEvents()) { + net_log_.AddEvent( + NetLog::TYPE_UDP_BYTES_SENT, + make_scoped_refptr( + new UDPDataTransferNetLogParam(result, bytes, + net_log_.IsLoggingBytes(), + address))); + } + + base::StatsCounter write_bytes("udp.write_bytes"); + write_bytes.Add(result); +} + int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address) { int bytes_transferred; @@ -357,15 +409,13 @@ int UDPSocketLibevent::InternalRecvFrom(IOBuffer* buf, int buf_len, int result; if (bytes_transferred >= 0) { result = bytes_transferred; - base::StatsCounter read_bytes("udp.read_bytes"); - read_bytes.Add(bytes_transferred); - if (address) { - if (!address->FromSockAddr(addr, addr_len)) - result = ERR_FAILED; - } + if (address && !address->FromSockAddr(addr, addr_len)) + result = ERR_FAILED; } else { result = MapSystemError(errno); } + if (result != ERR_IO_PENDING) + LogRead(result, buf->data(), addr_len, addr); return result; } @@ -379,16 +429,24 @@ int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, addr = NULL; addr_len = 0; } else { - if (!address->ToSockAddr(addr, &addr_len)) - return ERR_FAILED; + if (!address->ToSockAddr(addr, &addr_len)) { + int result = ERR_FAILED; + LogWrite(result, NULL, NULL); + return result; + } } - return HANDLE_EINTR(sendto(socket_, - buf->data(), - buf_len, - 0, - addr, - addr_len)); + int result = HANDLE_EINTR(sendto(socket_, + buf->data(), + buf_len, + 0, + addr, + addr_len)); + if (result < 0) + result = MapSystemError(errno); + if (result != ERR_IO_PENDING) + LogWrite(result, buf->data(), address); + return result; } int UDPSocketLibevent::DoBind(const IPEndPoint& address) { diff --git a/net/udp/udp_socket_libevent.h b/net/udp/udp_socket_libevent.h index 6bdf4d4..abc2dd5 100644 --- a/net/udp/udp_socket_libevent.h +++ b/net/udp/udp_socket_libevent.h @@ -10,6 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/threading/non_thread_safe.h" +#include "net/base/address_list_net_log_param.h" #include "net/base/completion_callback.h" #include "net/base/rand_callback.h" #include "net/base/io_buffer.h" @@ -19,8 +20,6 @@ namespace net { -class BoundNetLog; - class UDPSocketLibevent : public base::NonThreadSafe { public: UDPSocketLibevent(DatagramSocket::BindType bind_type, @@ -151,6 +150,14 @@ class UDPSocketLibevent : public base::NonThreadSafe { void DidCompleteRead(); void DidCompleteWrite(); + // Handles stats and logging. |result| is the number of bytes transferred, on + // success, or the net error code on failure. On success, LogRead takes in a + // sockaddr and its length, which are mandatory, while LogWrite takes in an + // optional IPEndPoint. + void LogRead(int result, const char* bytes, socklen_t addr_len, + const sockaddr* addr) const; + void LogWrite(int result, const char* bytes, const IPEndPoint* address) const; + // Returns the OS error code (or 0 on success). int CreateSocket(const IPEndPoint& address); @@ -162,6 +169,7 @@ class UDPSocketLibevent : public base::NonThreadSafe { const IPEndPoint* address, OldCompletionCallback* callback); + int InternalConnect(const IPEndPoint& address); int InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address); int InternalSendTo(IOBuffer* buf, int buf_len, const IPEndPoint* address); diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc index 8a66f34..066b47c 100644 --- a/net/udp/udp_socket_unittest.cc +++ b/net/udp/udp_socket_unittest.cc @@ -12,6 +12,7 @@ #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" +#include "net/base/net_log_unittest.h" #include "net/base/net_test_suite.h" #include "net/base/net_util.h" #include "net/base/sys_addrinfo.h" @@ -131,35 +132,73 @@ TEST_F(UDPSocketTest, Connect) { // Setup the server to listen. IPEndPoint bind_address; CreateUDPAddress("0.0.0.0", kPort, &bind_address); - UDPServerSocket server(NULL, NetLog::Source()); - int rv = server.Listen(bind_address); + CapturingNetLog server_log(CapturingNetLog::kUnbounded); + scoped_ptr<UDPServerSocket> server( + new UDPServerSocket(&server_log, NetLog::Source())); + int rv = server->Listen(bind_address); EXPECT_EQ(OK, rv); // Setup the client. IPEndPoint server_address; CreateUDPAddress("127.0.0.1", kPort, &server_address); - UDPClientSocket client(DatagramSocket::DEFAULT_BIND, - RandIntCallback(), - NULL, - NetLog::Source()); - rv = client.Connect(server_address); + CapturingNetLog client_log(CapturingNetLog::kUnbounded); + scoped_ptr<UDPClientSocket> client( + new UDPClientSocket(DatagramSocket::DEFAULT_BIND, + RandIntCallback(), + &client_log, + NetLog::Source())); + rv = client->Connect(server_address); EXPECT_EQ(OK, rv); // Client sends to the server. - rv = WriteSocket(&client, simple_message); + rv = WriteSocket(client.get(), simple_message); EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); // Server waits for message. - std::string str = RecvFromSocket(&server); + std::string str = RecvFromSocket(server.get()); DCHECK(simple_message == str); // Server echoes reply. - rv = SendToSocket(&server, simple_message); + rv = SendToSocket(server.get(), simple_message); EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); // Client waits for response. - str = ReadSocket(&client); + str = ReadSocket(client.get()); DCHECK(simple_message == str); + + // Delete sockets so they log their final events. + server.reset(); + client.reset(); + + // Check the server's log. + CapturingNetLog::EntryList server_entries; + server_log.GetEntries(&server_entries); + EXPECT_EQ(4u, server_entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + server_entries, 0, NetLog::TYPE_SOCKET_ALIVE)); + EXPECT_TRUE(LogContainsEvent( + server_entries, 1, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE)); + EXPECT_TRUE(LogContainsEvent( + server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE)); + EXPECT_TRUE(LogContainsEndEvent( + server_entries, 3, NetLog::TYPE_SOCKET_ALIVE)); + + // Check the client's log. + CapturingNetLog::EntryList client_entries; + client_log.GetEntries(&client_entries); + EXPECT_EQ(6u, client_entries.size()); + EXPECT_TRUE(LogContainsBeginEvent( + client_entries, 0, NetLog::TYPE_SOCKET_ALIVE)); + EXPECT_TRUE(LogContainsBeginEvent( + client_entries, 1, NetLog::TYPE_UDP_CONNECT)); + EXPECT_TRUE(LogContainsEndEvent( + client_entries, 2, NetLog::TYPE_UDP_CONNECT)); + EXPECT_TRUE(LogContainsEvent( + client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT, NetLog::PHASE_NONE)); + EXPECT_TRUE(LogContainsEvent( + client_entries, 4, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE)); + EXPECT_TRUE(LogContainsEndEvent( + client_entries, 5, NetLog::TYPE_SOCKET_ALIVE)); } // In this test, we verify that random binding logic works, which attempts @@ -321,11 +360,11 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { SCOPED_TRACE(std::string("Connecting from ") + tests[i].local_address + std::string(" to ") + tests[i].remote_address); - net::IPAddressNumber ip_number; - net::ParseIPLiteralToNumber(tests[i].remote_address, &ip_number); - net::IPEndPoint remote_address(ip_number, 80); - net::ParseIPLiteralToNumber(tests[i].local_address, &ip_number); - net::IPEndPoint local_address(ip_number, 80); + IPAddressNumber ip_number; + ParseIPLiteralToNumber(tests[i].remote_address, &ip_number); + IPEndPoint remote_address(ip_number, 80); + ParseIPLiteralToNumber(tests[i].local_address, &ip_number); + IPEndPoint local_address(ip_number, 80); UDPClientSocket client(DatagramSocket::DEFAULT_BIND, RandIntCallback(), diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc index d0242d4..0a58f6c 100644 --- a/net/udp/udp_socket_win.cc +++ b/net/udp/udp_socket_win.cc @@ -11,6 +11,7 @@ #include "base/message_loop.h" #include "base/metrics/stats_counters.h" #include "base/rand_util.h" +#include "net/base/address_list_net_log_param.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" @@ -18,6 +19,7 @@ #include "net/base/net_util.h" #include "net/base/winsock_init.h" #include "net/base/winsock_util.h" +#include "net/udp/udp_data_transfer_param.h" namespace { @@ -51,7 +53,7 @@ UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, recv_from_address_(NULL), read_callback_(NULL), write_callback_(NULL), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_UDP_SOCKET)) { EnsureWinsockInit(); scoped_refptr<NetLog::EventParameters> params; if (source.is_valid()) @@ -181,17 +183,30 @@ int UDPSocketWin::SendToOrWrite(IOBuffer* buf, DCHECK(!write_callback_); DCHECK(callback); // Synchronous operation not supported. DCHECK_GT(buf_len, 0); + DCHECK(!send_to_address_.get()); int nwrite = InternalSendTo(buf, buf_len, address); if (nwrite != ERR_IO_PENDING) return nwrite; + if (address) + send_to_address_.reset(new IPEndPoint(*address)); write_iobuffer_ = buf; write_callback_ = callback; return ERR_IO_PENDING; } int UDPSocketWin::Connect(const IPEndPoint& address) { + net_log_.BeginEvent( + NetLog::TYPE_UDP_CONNECT, + make_scoped_refptr(new NetLogStringParameter("address", + address.ToString()))); + int rv = InternalConnect(address); + net_log_.EndEventWithNetErrorCode(NetLog::TYPE_UDP_CONNECT, rv); + return rv; +} + +int UDPSocketWin::InternalConnect(const IPEndPoint& address) { DCHECK(!is_connected()); DCHECK(!remote_address_.get()); int rv = CreateSocket(address); @@ -281,28 +296,37 @@ void UDPSocketWin::DidCompleteRead() { &num_bytes, FALSE, &flags); WSAResetEvent(read_overlapped_.hEvent); int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); - if (ok) { - if (!ProcessSuccessfulRead(num_bytes, recv_from_address_)) + // Convert address. + if (recv_from_address_ && result >= 0) { + if (!ReceiveAddressToIPEndpoint(recv_from_address_)) result = ERR_FAILED; } + LogRead(result, read_iobuffer_->data()); read_iobuffer_ = NULL; recv_from_address_ = NULL; DoReadCallback(result); } -bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes, IPEndPoint* address) { - base::StatsCounter read_bytes("udp.read_bytes"); - read_bytes.Add(num_bytes); +void UDPSocketWin::LogRead(int result, const char* bytes) const { + if (result < 0) { + net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_RECEIVE_ERROR, result); + return; + } - // Convert address. - if (address) { - struct sockaddr* addr = - reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); - if (!address->FromSockAddr(addr, recv_addr_len_)) - return false; + if (net_log_.IsLoggingAllEvents()) { + // Get address for logging, if |address| is NULL. + IPEndPoint address; + bool is_address_valid = ReceiveAddressToIPEndpoint(&address); + net_log_.AddEvent( + NetLog::TYPE_UDP_BYTES_RECEIVED, + make_scoped_refptr( + new UDPDataTransferNetLogParam( + result, bytes, net_log_.IsLoggingBytes(), + is_address_valid ? &address : NULL))); } - return true; + base::StatsCounter read_bytes("udp.read_bytes"); + read_bytes.Add(result); } void UDPSocketWin::DidCompleteWrite() { @@ -311,15 +335,32 @@ void UDPSocketWin::DidCompleteWrite() { &num_bytes, FALSE, &flags); WSAResetEvent(write_overlapped_.hEvent); int result = ok ? num_bytes : MapSystemError(WSAGetLastError()); - if (ok) - ProcessSuccessfulWrite(num_bytes); + LogWrite(result, write_iobuffer_->data(), send_to_address_.get()); + + send_to_address_.reset(); write_iobuffer_ = NULL; DoWriteCallback(result); } -void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) { +void UDPSocketWin::LogWrite(int result, + const char* bytes, + const IPEndPoint* address) const { + if (result < 0) { + net_log_.AddEventWithNetErrorCode(NetLog::TYPE_UDP_SEND_ERROR, result); + return; + } + + if (net_log_.IsLoggingAllEvents()) { + net_log_.AddEvent( + NetLog::TYPE_UDP_BYTES_SENT, + make_scoped_refptr( + new UDPDataTransferNetLogParam(result, bytes, + net_log_.IsLoggingBytes(), + address))); + } + base::StatsCounter write_bytes("udp.write_bytes"); - write_bytes.Add(num_bytes); + write_bytes.Add(result); } int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, @@ -339,14 +380,22 @@ int UDPSocketWin::InternalRecvFrom(IOBuffer* buf, int buf_len, &recv_addr_len_, &read_overlapped_, NULL); if (rv == 0) { if (ResetEventIfSignaled(read_overlapped_.hEvent)) { - if (!ProcessSuccessfulRead(num, address)) - return ERR_FAILED; - return static_cast<int>(num); + int result = num; + // Convert address. + if (address && result >= 0) { + if (!ReceiveAddressToIPEndpoint(address)) + result = ERR_FAILED; + } + LogRead(result, buf->data()); + return result; } } else { int os_error = WSAGetLastError(); - if (os_error != WSA_IO_PENDING) - return MapSystemError(os_error); + if (os_error != WSA_IO_PENDING) { + int result = MapSystemError(os_error); + LogRead(result, NULL); + return result; + } } read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_); return ERR_IO_PENDING; @@ -363,8 +412,11 @@ int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, addr = NULL; addr_len = 0; } else { - if (!address->ToSockAddr(addr, &addr_len)) - return ERR_FAILED; + if (!address->ToSockAddr(addr, &addr_len)) { + int result = ERR_FAILED; + LogWrite(result, NULL, NULL); + return result; + } } WSABUF write_buffer; @@ -378,13 +430,17 @@ int UDPSocketWin::InternalSendTo(IOBuffer* buf, int buf_len, addr, addr_len, &write_overlapped_, NULL); if (rv == 0) { if (ResetEventIfSignaled(write_overlapped_.hEvent)) { - ProcessSuccessfulWrite(num); - return static_cast<int>(num); + int result = num; + LogWrite(result, buf->data(), address); + return result; } } else { int os_error = WSAGetLastError(); - if (os_error != WSA_IO_PENDING) - return MapSystemError(os_error); + if (os_error != WSA_IO_PENDING) { + int result = MapSystemError(os_error); + LogWrite(result, NULL, NULL); + return result; + } } write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); @@ -415,4 +471,10 @@ int UDPSocketWin::RandomBind(const IPEndPoint& address) { return DoBind(IPEndPoint(ip, 0)); } +bool UDPSocketWin::ReceiveAddressToIPEndpoint(IPEndPoint* address) const { + const struct sockaddr* addr = + reinterpret_cast<const struct sockaddr*>(&recv_addr_storage_); + return address->FromSockAddr(addr, recv_addr_len_); +} + } // namespace net diff --git a/net/udp/udp_socket_win.h b/net/udp/udp_socket_win.h index ca4ecb1..5713d97 100644 --- a/net/udp/udp_socket_win.h +++ b/net/udp/udp_socket_win.h @@ -21,8 +21,6 @@ namespace net { -class BoundNetLog; - class UDPSocketWin : public base::NonThreadSafe { public: UDPSocketWin(DatagramSocket::BindType bind_type, @@ -136,8 +134,12 @@ class UDPSocketWin : public base::NonThreadSafe { void DoWriteCallback(int rv); void DidCompleteRead(); void DidCompleteWrite(); - bool ProcessSuccessfulRead(int num_bytes, IPEndPoint* address); - void ProcessSuccessfulWrite(int num_bytes); + + // Handles stats and logging. |result| is the number of bytes transferred, on + // success, or the net error code on failure. LogRead retrieves the address + // from |recv_addr_storage_|, while LogWrite takes it as an optional argument. + void LogRead(int result, const char* bytes) const; + void LogWrite(int result, const char* bytes, const IPEndPoint* address) const; // Returns the OS error code (or 0 on success). int CreateSocket(const IPEndPoint& address); @@ -150,12 +152,17 @@ class UDPSocketWin : public base::NonThreadSafe { const IPEndPoint* address, OldCompletionCallback* callback); + int InternalConnect(const IPEndPoint& address); int InternalRecvFrom(IOBuffer* buf, int buf_len, IPEndPoint* address); int InternalSendTo(IOBuffer* buf, int buf_len, const IPEndPoint* address); int DoBind(const IPEndPoint& address); int RandomBind(const IPEndPoint& address); + // Attempts to convert the data in |recv_addr_storage_| and |recv_addr_len_| + // to an IPEndPoint and writes it to |address|. Returns true on success. + bool ReceiveAddressToIPEndpoint(IPEndPoint* address) const; + SOCKET socket_; // How to do source port binding, used only when UDPSocket is part of @@ -188,6 +195,10 @@ class UDPSocketWin : public base::NonThreadSafe { socklen_t recv_addr_len_; IPEndPoint* recv_from_address_; + // Cached copy of the current address we're sending to, if any. Used for + // logging. + scoped_ptr<IPEndPoint> send_to_address_; + // The buffer used by InternalWrite() to retry Write requests scoped_refptr<IOBuffer> write_iobuffer_; |