summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-18 20:08:10 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-10-18 20:08:10 +0000
commit8866f623dfd914c9f4c26ab96f90aecf4a372ef9 (patch)
tree4f45fa083309b6934e1888c27c9df2344cd391f0 /net
parentdef979a39bd25dfb24c80138699ffb359c495757 (diff)
downloadchromium_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.cc14
-rw-r--r--net/base/net_log.h9
-rw-r--r--net/base/net_log_event_type_list.h62
-rw-r--r--net/base/net_log_source_type_list.h3
-rw-r--r--net/net.gyp2
-rw-r--r--net/socket/tcp_client_socket_win.cc2
-rw-r--r--net/udp/udp_data_transfer_param.cc36
-rw-r--r--net/udp/udp_data_transfer_param.h40
-rw-r--r--net/udp/udp_socket_libevent.cc120
-rw-r--r--net/udp/udp_socket_libevent.h12
-rw-r--r--net/udp/udp_socket_unittest.cc71
-rw-r--r--net/udp/udp_socket_win.cc118
-rw-r--r--net/udp/udp_socket_win.h19
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_;