diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-11 22:15:09 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-11 22:15:09 +0000 |
commit | 33cdc9b854044864f7494c23a21f78733a961236 (patch) | |
tree | 5cff7b26780bc68451fb3917baea18bdb9f1c95a /net | |
parent | a7fb410b943d13c9f4aed11fe8d2774f990b3220 (diff) | |
download | chromium_src-33cdc9b854044864f7494c23a21f78733a961236.zip chromium_src-33cdc9b854044864f7494c23a21f78733a961236.tar.gz chromium_src-33cdc9b854044864f7494c23a21f78733a961236.tar.bz2 |
Revert 77870 - UDP sockets implementation for windows.
BUG=None
TEST=Unittests
Review URL: http://codereview.chromium.org/6658027
TBR=sergeyu@chromium.org
Review URL: http://codereview.chromium.org/6681014
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77872 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/winsock_util.cc | 96 | ||||
-rw-r--r-- | net/base/winsock_util.h | 31 | ||||
-rw-r--r-- | net/net.gyp | 40 | ||||
-rw-r--r-- | net/socket/tcp_client_socket_win.cc | 87 | ||||
-rw-r--r-- | net/udp/datagram_server_socket.h | 2 | ||||
-rw-r--r-- | net/udp/udp_socket.h | 19 | ||||
-rw-r--r-- | net/udp/udp_socket_libevent.cc | 42 | ||||
-rw-r--r-- | net/udp/udp_socket_libevent.h | 24 | ||||
-rw-r--r-- | net/udp/udp_socket_unittest.cc | 62 | ||||
-rw-r--r-- | net/udp/udp_socket_win.cc | 366 | ||||
-rw-r--r-- | net/udp/udp_socket_win.h | 178 |
11 files changed, 160 insertions, 787 deletions
diff --git a/net/base/winsock_util.cc b/net/base/winsock_util.cc deleted file mode 100644 index dac38be..0000000 --- a/net/base/winsock_util.cc +++ /dev/null @@ -1,96 +0,0 @@ -// 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 "net/base/winsock_util.h" - -#include "base/logging.h" -#include "net/base/net_errors.h" - -namespace net { - -namespace { - -// Prevent the compiler from optimizing away the arguments so they appear -// nicely on the stack in crash dumps. -#pragma warning (disable: 4748) -#pragma optimize( "", off ) - -// Pass the important values as function arguments so that they are available -// in crash dumps. -void CheckEventWait(WSAEVENT hEvent, DWORD wait_rv, DWORD expected) { - if (wait_rv != expected) { - DWORD err = ERROR_SUCCESS; - if (wait_rv == WAIT_FAILED) - err = GetLastError(); - CHECK(false); // Crash. - } -} - -#pragma optimize( "", on ) -#pragma warning (default: 4748) - -} // namespace - -void AssertEventNotSignaled(WSAEVENT hEvent) { - DWORD wait_rv = WaitForSingleObject(hEvent, 0); - CheckEventWait(hEvent, wait_rv, WAIT_TIMEOUT); -} - -bool ResetEventIfSignaled(WSAEVENT hEvent) { - // TODO(wtc): Remove the CHECKs after enough testing. - DWORD wait_rv = WaitForSingleObject(hEvent, 0); - if (wait_rv == WAIT_TIMEOUT) - return false; // The event object is not signaled. - CheckEventWait(hEvent, wait_rv, WAIT_OBJECT_0); - BOOL ok = WSAResetEvent(hEvent); - CHECK(ok); - return true; -} - -// Map winsock error to Chromium error. -int MapWinsockError(int os_error) { - // There are numerous Winsock error codes, but these are the ones we thus far - // find interesting. - switch (os_error) { - case WSAEACCES: - return ERR_ACCESS_DENIED; - case WSAENETDOWN: - return ERR_INTERNET_DISCONNECTED; - case WSAETIMEDOUT: - return ERR_TIMED_OUT; - case WSAECONNRESET: - case WSAENETRESET: // Related to keep-alive - return ERR_CONNECTION_RESET; - case WSAECONNABORTED: - return ERR_CONNECTION_ABORTED; - case WSAECONNREFUSED: - return ERR_CONNECTION_REFUSED; - case WSA_IO_INCOMPLETE: - case WSAEDISCON: - // WSAEDISCON is returned by WSARecv or WSARecvFrom for message-oriented - // sockets (where a return value of zero means a zero-byte message) to - // indicate graceful connection shutdown. We should not ever see this - // error code for TCP sockets, which are byte stream oriented. - LOG(DFATAL) << "Unexpected error " << os_error - << " mapped to net::ERR_UNEXPECTED"; - return ERR_UNEXPECTED; - case WSAEHOSTUNREACH: - case WSAENETUNREACH: - return ERR_ADDRESS_UNREACHABLE; - case WSAEADDRNOTAVAIL: - return ERR_ADDRESS_INVALID; - case WSAENOTCONN: - return ERR_SOCKET_NOT_CONNECTED; - case WSAEAFNOSUUPORT: - return ERR_ADDRESS_UNREACHABLE; - case ERROR_SUCCESS: - return OK; - default: - LOG(WARNING) << "Unknown error " << os_error - << " mapped to net::ERR_FAILED"; - return ERR_FAILED; - } -} - -} // namespace net diff --git a/net/base/winsock_util.h b/net/base/winsock_util.h deleted file mode 100644 index c26e63f..0000000 --- a/net/base/winsock_util.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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_BASE_WINSOCK_UTIL_H_ -#define NET_BASE_WINSOCK_UTIL_H_ -#pragma once - -#include <winsock2.h> - -namespace net { - -// Assert that the (manual-reset) event object is not signaled. -void AssertEventNotSignaled(WSAEVENT hEvent); - -// If the (manual-reset) event object is signaled, resets it and returns true. -// Otherwise, does nothing and returns false. Called after a Winsock function -// succeeds synchronously -// -// Our testing shows that except in rare cases (when running inside QEMU), -// the event object is already signaled at this point, so we call this method -// to avoid a context switch in common cases. This is just a performance -// optimization. The code still works if this function simply returns false. -bool ResetEventIfSignaled(WSAEVENT hEvent); - -// Map winsock error to Chromium error. -int MapWinsockError(int os_error); - -} // namespace net - -#endif // NET_BASE_WINSOCK_UTIL_H_ diff --git a/net/net.gyp b/net/net.gyp index 7fa024a..12b2a95 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -199,8 +199,6 @@ 'base/upload_data_stream.h', 'base/winsock_init.cc', 'base/winsock_init.h', - 'base/winsock_util.cc', - 'base/winsock_util.h', 'base/x509_certificate.cc', 'base/x509_certificate.h', 'base/x509_certificate_mac.cc', @@ -327,7 +325,6 @@ ], 'sources!': [ 'base/winsock_init.cc', - 'base/winsock_util.cc', ], }, ], @@ -677,18 +674,6 @@ 'spdy/spdy_settings_storage.h', 'spdy/spdy_stream.cc', 'spdy/spdy_stream.h', - 'udp/datagram_client_socket.h', - 'udp/datagram_server_socket.h', - 'udp/datagram_socket.h', - 'udp/udp_client_socket.cc', - 'udp/udp_client_socket.h', - 'udp/udp_server_socket.cc', - 'udp/udp_server_socket.h', - 'udp/udp_socket.h', - 'udp/udp_socket_libevent.cc', - 'udp/udp_socket_libevent.h', - 'udp/udp_socket_win.cc', - 'udp/udp_socket_win.h', 'url_request/https_prober.h', 'url_request/https_prober.cc', 'url_request/url_request.cc', @@ -823,7 +808,6 @@ 'sources!': [ 'http/http_auth_handler_ntlm_portable.cc', 'socket/tcp_client_socket_libevent.cc', - 'udp/udp_socket_libevent.cc', ], 'dependencies': [ '../third_party/nss/nss.gyp:nss', @@ -1009,7 +993,6 @@ 'tools/dump_cache/url_utilities.h', 'tools/dump_cache/url_utilities.cc', 'tools/dump_cache/url_utilities_unittest.cc', - 'udp/udp_socket_unittest.cc', 'url_request/url_request_job_tracker_unittest.cc', 'url_request/url_request_throttler_unittest.cc', 'url_request/url_request_unittest.cc', @@ -1448,6 +1431,29 @@ }, ], }], + ['OS=="linux"', { + 'targets': [ + { + 'target_name': 'udp_socket_unittest', + 'type': 'executable', + 'dependencies': [ + 'net', + 'net_test_support', + '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + '../third_party/zlib/zlib.gyp:zlib', + ], + 'sources': [ + 'udp/udp_client_socket.cc', + 'udp/udp_server_socket.cc', + 'udp/udp_socket_libevent.cc', + 'udp/udp_socket_unittest.cc', + ] + }, + ], + }], ['OS=="win"', { 'targets': [ { diff --git a/net/socket/tcp_client_socket_win.cc b/net/socket/tcp_client_socket_win.cc index 6d733fa..9e93bf0 100644 --- a/net/socket/tcp_client_socket_win.cc +++ b/net/socket/tcp_client_socket_win.cc @@ -22,12 +22,97 @@ #include "net/base/network_change_notifier.h" #include "net/base/sys_addrinfo.h" #include "net/base/winsock_init.h" -#include "net/base/winsock_util.h" namespace net { namespace { +// Prevent the compiler from optimizing away the arguments so they appear +// nicely on the stack in crash dumps. +#pragma warning (disable: 4748) +#pragma optimize( "", off ) + +// Pass the important values as function arguments so that they are available +// in crash dumps. +void CheckEventWait(WSAEVENT hEvent, DWORD wait_rv, DWORD expected) { + if (wait_rv != expected) { + DWORD err = ERROR_SUCCESS; + if (wait_rv == WAIT_FAILED) + err = GetLastError(); + CHECK(false); // Crash. + } +} + +#pragma optimize( "", on ) +#pragma warning (default: 4748) + +// Assert that the (manual-reset) event object is not signaled. +void AssertEventNotSignaled(WSAEVENT hEvent) { + DWORD wait_rv = WaitForSingleObject(hEvent, 0); + CheckEventWait(hEvent, wait_rv, WAIT_TIMEOUT); +} + +// If the (manual-reset) event object is signaled, resets it and returns true. +// Otherwise, does nothing and returns false. Called after a Winsock function +// succeeds synchronously +// +// Our testing shows that except in rare cases (when running inside QEMU), +// the event object is already signaled at this point, so we call this method +// to avoid a context switch in common cases. This is just a performance +// optimization. The code still works if this function simply returns false. +bool ResetEventIfSignaled(WSAEVENT hEvent) { + // TODO(wtc): Remove the CHECKs after enough testing. + DWORD wait_rv = WaitForSingleObject(hEvent, 0); + if (wait_rv == WAIT_TIMEOUT) + return false; // The event object is not signaled. + CheckEventWait(hEvent, wait_rv, WAIT_OBJECT_0); + BOOL ok = WSAResetEvent(hEvent); + CHECK(ok); + return true; +} + +//----------------------------------------------------------------------------- + +int MapWinsockError(int os_error) { + // There are numerous Winsock error codes, but these are the ones we thus far + // find interesting. + switch (os_error) { + case WSAEACCES: + return ERR_ACCESS_DENIED; + case WSAENETDOWN: + return ERR_INTERNET_DISCONNECTED; + case WSAETIMEDOUT: + return ERR_TIMED_OUT; + case WSAECONNRESET: + case WSAENETRESET: // Related to keep-alive + return ERR_CONNECTION_RESET; + case WSAECONNABORTED: + return ERR_CONNECTION_ABORTED; + case WSAECONNREFUSED: + return ERR_CONNECTION_REFUSED; + case WSA_IO_INCOMPLETE: + case WSAEDISCON: + // WSAEDISCON is returned by WSARecv or WSARecvFrom for message-oriented + // sockets (where a return value of zero means a zero-byte message) to + // indicate graceful connection shutdown. We should not ever see this + // error code for TCP sockets, which are byte stream oriented. + LOG(DFATAL) << "Unexpected error " << os_error + << " mapped to net::ERR_UNEXPECTED"; + return ERR_UNEXPECTED; + case WSAEHOSTUNREACH: + case WSAENETUNREACH: + return ERR_ADDRESS_UNREACHABLE; + case WSAEADDRNOTAVAIL: + return ERR_ADDRESS_INVALID; + case ERROR_SUCCESS: + return OK; + default: + LOG(WARNING) << "Unknown error " << os_error + << " mapped to net::ERR_FAILED"; + return ERR_FAILED; + } +} + int MapConnectError(int os_error) { switch (os_error) { // connect fails with WSAEACCES when Windows Firewall blocks the diff --git a/net/udp/datagram_server_socket.h b/net/udp/datagram_server_socket.h index 9841d53..30286e5 100644 --- a/net/udp/datagram_server_socket.h +++ b/net/udp/datagram_server_socket.h @@ -6,6 +6,8 @@ #define NET_UDP_DATAGRAM_SERVER_SOCKET_H_ #pragma once +#include <sys/socket.h> + #include "net/base/completion_callback.h" #include "net/udp/datagram_socket.h" diff --git a/net/udp/udp_socket.h b/net/udp/udp_socket.h index 15ba76c..9e5f826 100644 --- a/net/udp/udp_socket.h +++ b/net/udp/udp_socket.h @@ -16,24 +16,7 @@ namespace net { -// UDPSocket -// Accessor API for a UDP socket in either client or server form. -// -// Client form: -// In this case, we're connecting to a specific server, so the client will -// usually use: -// Connect(address) // Connect to a UDP server -// Read/Write // Reads/Writes all go to a single destination -// -// Server form: -// In this case, we want to read/write to many clients which are connecting -// to this server. First the server 'binds' to an addres, then we read from -// clients and write responses to them. -// Example: -// Bind(address/port) // Binds to port for reading from clients -// RecvFrom/SendTo // Each read can come from a different client -// // Writes need to be directed to a specific -// // address. +// A client socket that uses UDP as the transport layer. #if defined(OS_WIN) typedef UDPSocketWin UDPSocket; #elif defined(OS_POSIX) diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc index de24253..7c75ce3 100644 --- a/net/udp/udp_socket_libevent.cc +++ b/net/udp/udp_socket_libevent.cc @@ -63,8 +63,6 @@ int MapPosixError(int os_error) { return ERR_ADDRESS_INVALID; case EMSGSIZE: return ERR_MSG_TOO_BIG; - case ENOTCONN: - return ERR_SOCKET_NOT_CONNECTED; case 0: return OK; default: @@ -101,21 +99,9 @@ UDPSocketLibevent::~UDPSocketLibevent() { } void UDPSocketLibevent::Close() { - DCHECK(CalledOnValidThread()); - - if (read_callback_) - DoReadCallback(ERR_ABORTED); - if (write_callback_) - DoReadCallback(ERR_ABORTED); - if (!is_connected()) return; - bool ok = read_socket_watcher_.StopWatchingFileDescriptor(); - DCHECK(ok); - ok = write_socket_watcher_.StopWatchingFileDescriptor(); - DCHECK(ok); - if (HANDLE_EINTR(close(socket_)) < 0) PLOG(ERROR) << "close"; @@ -175,7 +161,10 @@ int UDPSocketLibevent::Read(IOBuffer* buf, DCHECK(callback); // Synchronous operation not supported DCHECK_GT(buf_len, 0); - int nread = InternalRead(buf, buf_len); + read_buf_ = buf; + read_buf_len_ = buf_len; + + int nread = InternalRead(); if (nread != ERR_IO_PENDING) return nread; @@ -186,8 +175,6 @@ int UDPSocketLibevent::Read(IOBuffer* buf, return MapPosixError(errno); } - read_buf_ = buf; - read_buf_len_ = buf_len; read_callback_ = callback; return ERR_IO_PENDING; } @@ -245,7 +232,7 @@ int UDPSocketLibevent::Connect(const IPEndPoint& address) { DCHECK(!remote_address_.get()); int rv = CreateSocket(address); if (rv < 0) - return rv; + return MapPosixError(rv); struct sockaddr_storage addr_storage; size_t addr_len = sizeof(addr_storage); @@ -255,7 +242,7 @@ int UDPSocketLibevent::Connect(const IPEndPoint& address) { rv = HANDLE_EINTR(connect(socket_, addr, addr_len)); if (rv < 0) - return MapPosixError(errno); + return MapPosixError(rv); remote_address_.reset(new IPEndPoint(address)); return rv; @@ -266,7 +253,7 @@ int UDPSocketLibevent::Bind(const IPEndPoint& address) { DCHECK(!local_address_.get()); int rv = CreateSocket(address); if (rv < 0) - return rv; + return MapPosixError(rv); struct sockaddr_storage addr_storage; size_t addr_len = sizeof(addr_storage); @@ -276,7 +263,7 @@ int UDPSocketLibevent::Bind(const IPEndPoint& address) { rv = bind(socket_, addr, addr_len); if (rv < 0) - return MapPosixError(errno); + return MapPosixError(rv); local_address_.reset(new IPEndPoint(address)); return rv; @@ -305,7 +292,7 @@ void UDPSocketLibevent::DoWriteCallback(int rv) { } void UDPSocketLibevent::DidCompleteRead() { - int result = InternalRead(read_buf_, read_buf_len_); + int result = InternalRead(); if (result != ERR_IO_PENDING) { read_buf_ = NULL; read_buf_len_ = 0; @@ -318,9 +305,9 @@ void UDPSocketLibevent::DidCompleteRead() { int UDPSocketLibevent::CreateSocket(const IPEndPoint& address) { socket_ = socket(address.GetFamily(), SOCK_DGRAM, 0); if (socket_ == kInvalidSocket) - return MapPosixError(errno); + return errno; if (SetNonBlocking(socket_)) { - const int err = MapPosixError(errno); + const int err = errno; Close(); return err; } @@ -344,7 +331,7 @@ void UDPSocketLibevent::DidCompleteWrite() { } } -int UDPSocketLibevent::InternalRead(IOBuffer* buf, int buf_len) { +int UDPSocketLibevent::InternalRead() { int bytes_transferred; int flags = 0; @@ -354,8 +341,8 @@ int UDPSocketLibevent::InternalRead(IOBuffer* buf, int buf_len) { bytes_transferred = HANDLE_EINTR(recvfrom(socket_, - buf->data(), - buf_len, + read_buf_->data(), + read_buf_len_, flags, addr, &addr_len)); @@ -373,7 +360,6 @@ int UDPSocketLibevent::InternalRead(IOBuffer* buf, int buf_len) { } return result; } - int UDPSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) { struct sockaddr_storage addr_storage; size_t addr_len = sizeof(addr_storage); diff --git a/net/udp/udp_socket_libevent.h b/net/udp/udp_socket_libevent.h index 1a9fd6e..ebe01b2 100644 --- a/net/udp/udp_socket_libevent.h +++ b/net/udp/udp_socket_libevent.h @@ -6,6 +6,25 @@ #define NET_UDP_UDP_SOCKET_LIBEVENT_H_ #pragma once +// UDPSocketLibevent +// Accessor API for a UDP socket in either client or server form. +// +// Client form: +// In this case, we're connecting to a specific server, so the client will +// usually use: +// Connect(address) // Connect to a UDP server +// Read/Write // Reads/Writes all go to a single destination +// +// Server form: +// In this case, we want to read/write to many clients which are connecting +// to this server. First the server 'binds' to an addres, then we read from +// clients and write responses to them. +// Example: +// Bind(address/port) // Binds to port for reading from clients +// RecvFrom/SendTo // Each read can come from a different client +// // Writes need to be directed to a specific +// // address. + #include "base/message_loop.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" @@ -14,6 +33,7 @@ #include "net/base/ip_endpoint.h" #include "net/base/net_log.h" #include "net/socket/client_socket.h" +#include "net/udp/datagram_socket.h" namespace net { @@ -93,6 +113,8 @@ class UDPSocketLibevent : public base::NonThreadSafe { // Returns true if the socket is already connected or bound. bool is_connected() const { return socket_ != kInvalidSocket; } + IPEndPoint* local_address() { return local_address_.get(); } + private: static const int kInvalidSocket = -1; @@ -142,7 +164,7 @@ class UDPSocketLibevent : public base::NonThreadSafe { // Returns the OS error code (or 0 on success). int CreateSocket(const IPEndPoint& address); - int InternalRead(IOBuffer* buf, int buf_len); + int InternalRead(); int InternalWrite(IOBuffer* buf, int buf_len); int socket_; diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc index 23caf22..ef43731 100644 --- a/net/udp/udp_socket_unittest.cc +++ b/net/udp/udp_socket_unittest.cc @@ -107,7 +107,7 @@ class UDPSocketTest : public PlatformTest { return bytes_sent; } - protected: + private: static const int kMaxRead = 1024; scoped_refptr<IOBufferWithSize> buffer_; IPEndPoint recv_from_address_; @@ -223,7 +223,7 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { struct TestData { std::string remote_address; std::string local_address; - bool may_fail; + bool is_ipv6; } tests[] = { { "127.0.00.1", "127.0.0.1", false }, { "192.168.1.1", "127.0.0.1", false }, @@ -231,9 +231,6 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { { "2001:db8:0::42", "::1", true }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); i++) { - 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); @@ -242,12 +239,6 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { UDPClientSocket client(NULL, NetLog::Source()); int rv = client.Connect(remote_address); - if (tests[i].may_fail && rv == ERR_ADDRESS_UNREACHABLE) { - // Connect() may return ERR_ADDRESS_UNREACHABLE for IPv6 - // addresses if IPv6 is not configured. - continue; - } - EXPECT_LE(ERR_IO_PENDING, rv); IPEndPoint fetched_local_address; @@ -269,52 +260,21 @@ TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { } TEST_F(UDPSocketTest, ServerGetLocalAddress) { - IPEndPoint bind_address; - CreateUDPAddress("127.0.0.1", 0, &bind_address); - UDPServerSocket server(NULL, NetLog::Source()); - int rv = server.Listen(bind_address); - EXPECT_EQ(OK, rv); - - IPEndPoint local_address; - rv = server.GetLocalAddress(&local_address); - EXPECT_EQ(rv, 0); - - // Verify that port was allocated. - EXPECT_GE(local_address.port(), 0); - EXPECT_EQ(local_address.address(), bind_address.address()); + // TODO(mbelshe): implement me } TEST_F(UDPSocketTest, ServerGetPeerAddress) { - IPEndPoint bind_address; - CreateUDPAddress("127.0.0.1", 0, &bind_address); - UDPServerSocket server(NULL, NetLog::Source()); - int rv = server.Listen(bind_address); - EXPECT_EQ(OK, rv); - - IPEndPoint peer_address; - rv = server.GetPeerAddress(&peer_address); - EXPECT_EQ(rv, ERR_SOCKET_NOT_CONNECTED); + // TODO(mbelshe): implement me } -// Close the socket while read is pending. -TEST_F(UDPSocketTest, CloseWithPendingRead) { - IPEndPoint bind_address; - CreateUDPAddress("127.0.0.1", 0, &bind_address); - UDPServerSocket server(NULL, NetLog::Source()); - int rv = server.Listen(bind_address); - EXPECT_EQ(OK, rv); +} // namespace - TestCompletionCallback callback; - IPEndPoint from; - rv = server.RecvFrom(buffer_, kMaxRead, &from, &callback); - EXPECT_EQ(rv, ERR_IO_PENDING); +} // namespace net - server.Close(); +int main(int argc, char** argv) { + // Record histograms, so we can get histograms data in tests. + base::StatisticsRecorder recorder; + NetTestSuite test_suite(argc, argv); - EXPECT_TRUE(callback.have_result()); - EXPECT_EQ(callback.GetResult(rv), ERR_ABORTED); + return test_suite.Run(); } - -} // namespace - -} // namespace net diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc deleted file mode 100644 index 8a180d2..0000000 --- a/net/udp/udp_socket_win.cc +++ /dev/null @@ -1,366 +0,0 @@ -// 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 "net/udp/udp_socket_win.h" - -#include <mstcpip.h> - -#include "base/eintr_wrapper.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/memory_debug.h" -#include "base/metrics/stats_counters.h" -#include "net/base/io_buffer.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_errors.h" -#include "net/base/net_log.h" -#include "net/base/net_util.h" -#include "net/base/winsock_init.h" -#include "net/base/winsock_util.h" - -namespace net { - -void UDPSocketWin::ReadDelegate::OnObjectSignaled(HANDLE object) { - DCHECK_EQ(object, socket_->read_overlapped_.hEvent); - socket_->DidCompleteRead(); -} - -void UDPSocketWin::WriteDelegate::OnObjectSignaled(HANDLE object) { - DCHECK_EQ(object, socket_->write_overlapped_.hEvent); - socket_->DidCompleteWrite(); -} - -UDPSocketWin::UDPSocketWin(net::NetLog* net_log, - const net::NetLog::Source& source) - : socket_(INVALID_SOCKET), - ALLOW_THIS_IN_INITIALIZER_LIST(read_delegate_(this)), - ALLOW_THIS_IN_INITIALIZER_LIST(write_delegate_(this)), - recv_from_address_(NULL), - read_callback_(NULL), - write_callback_(NULL), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { - EnsureWinsockInit(); - scoped_refptr<NetLog::EventParameters> params; - if (source.is_valid()) - params = new NetLogSourceParameter("source_dependency", source); - net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); - memset(&read_overlapped_, 0, sizeof(read_overlapped_)); - read_overlapped_.hEvent = WSACreateEvent(); - memset(&write_overlapped_, 0, sizeof(write_overlapped_)); - write_overlapped_.hEvent = WSACreateEvent(); -} - -UDPSocketWin::~UDPSocketWin() { - Close(); - net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); -} - -void UDPSocketWin::Close() { - DCHECK(CalledOnValidThread()); - - if (!is_connected()) - return; - - if (read_callback_) - DoReadCallback(ERR_ABORTED); - if (write_callback_) - DoReadCallback(ERR_ABORTED); - - read_watcher_.StopWatching(); - write_watcher_.StopWatching(); - - closesocket(socket_); - socket_ = INVALID_SOCKET; -} - -int UDPSocketWin::GetPeerAddress(IPEndPoint* address) const { - DCHECK(CalledOnValidThread()); - DCHECK(address); - if (!is_connected()) - return ERR_SOCKET_NOT_CONNECTED; - - if (!remote_address_.get()) { - struct sockaddr_storage addr_storage; - int addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (getpeername(socket_, addr, &addr_len)) - return MapWinsockError(WSAGetLastError()); - scoped_ptr<IPEndPoint> address(new IPEndPoint()); - if (!address->FromSockAddr(addr, addr_len)) - return ERR_FAILED; - remote_address_.reset(address.release()); - } - - *address = *remote_address_; - return OK; -} - -int UDPSocketWin::GetLocalAddress(IPEndPoint* address) const { - DCHECK(CalledOnValidThread()); - DCHECK(address); - if (!is_connected()) - return ERR_SOCKET_NOT_CONNECTED; - - if (!local_address_.get()) { - struct sockaddr_storage addr_storage; - socklen_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (getsockname(socket_, addr, &addr_len)) - return MapWinsockError(WSAGetLastError()); - scoped_ptr<IPEndPoint> address(new IPEndPoint()); - if (!address->FromSockAddr(addr, addr_len)) - return ERR_FAILED; - local_address_.reset(address.release()); - } - - *address = *local_address_; - return OK; -} - -int UDPSocketWin::RecvFrom(IOBuffer* buf, - int buf_len, - IPEndPoint* address, - CompletionCallback* callback) { - DCHECK(!recv_from_address_); - recv_from_address_ = address; - return Read(buf, buf_len, callback); -} - -int UDPSocketWin::Read(IOBuffer* buf, - int buf_len, - CompletionCallback* callback) { - DCHECK(CalledOnValidThread()); - DCHECK_NE(INVALID_SOCKET, socket_); - DCHECK(!read_callback_); - DCHECK(callback); // Synchronous operation not supported. - DCHECK_GT(buf_len, 0); - - int nread = InternalRead(buf, buf_len); - if (nread != ERR_IO_PENDING) - return nread; - - read_iobuffer_ = buf; - read_callback_ = callback; - return ERR_IO_PENDING; -} - -int UDPSocketWin::SendTo(IOBuffer* buf, - int buf_len, - const IPEndPoint& address, - CompletionCallback* callback) { - send_to_address_.reset(new IPEndPoint(address)); - return Write(buf, buf_len, callback); -} - -int UDPSocketWin::Write(IOBuffer* buf, - int buf_len, - CompletionCallback* callback) { - DCHECK(CalledOnValidThread()); - DCHECK_NE(INVALID_SOCKET, socket_); - DCHECK(!write_callback_); - DCHECK(callback); // Synchronous operation not supported. - DCHECK_GT(buf_len, 0); - - int nwrite = InternalWrite(buf, buf_len); - if (nwrite != ERR_IO_PENDING) - return nwrite; - - write_iobuffer_ = buf; - write_callback_ = callback; - return ERR_IO_PENDING; -} - -int UDPSocketWin::Connect(const IPEndPoint& address) { - DCHECK(!is_connected()); - DCHECK(!remote_address_.get()); - int rv = CreateSocket(address); - if (rv < 0) - return rv; - - struct sockaddr_storage addr_storage; - size_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (!address.ToSockAddr(addr, &addr_len)) - return ERR_FAILED; - - rv = connect(socket_, addr, addr_len); - if (rv < 0) - return MapWinsockError(WSAGetLastError()); - - remote_address_.reset(new IPEndPoint(address)); - return rv; -} - -int UDPSocketWin::Bind(const IPEndPoint& address) { - DCHECK(!is_connected()); - DCHECK(!local_address_.get()); - int rv = CreateSocket(address); - if (rv < 0) - return rv; - - struct sockaddr_storage addr_storage; - size_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (!address.ToSockAddr(addr, &addr_len)) - return ERR_FAILED; - - rv = bind(socket_, addr, addr_len); - if (rv < 0) - return MapWinsockError(WSAGetLastError()); - - local_address_.reset(new IPEndPoint(address)); - return rv; -} - -int UDPSocketWin::CreateSocket(const IPEndPoint& address) { - socket_ = WSASocket(address.GetFamily(), SOCK_DGRAM, IPPROTO_UDP, NULL, 0, - WSA_FLAG_OVERLAPPED); - if (socket_ == INVALID_SOCKET) - return MapWinsockError(WSAGetLastError()); - return OK; -} - -void UDPSocketWin::DoReadCallback(int rv) { - DCHECK_NE(rv, ERR_IO_PENDING); - DCHECK(read_callback_); - - // since Run may result in Read being called, clear read_callback_ up front. - CompletionCallback* c = read_callback_; - read_callback_ = NULL; - recv_from_address_ = NULL; - c->Run(rv); -} - -void UDPSocketWin::DoWriteCallback(int rv) { - DCHECK_NE(rv, ERR_IO_PENDING); - DCHECK(write_callback_); - - // since Run may result in Write being called, clear write_callback_ up front. - CompletionCallback* c = write_callback_; - write_callback_ = NULL; - send_to_address_.reset(); - c->Run(rv); -} - -void UDPSocketWin::DidCompleteRead() { - DWORD num_bytes, flags; - BOOL ok = WSAGetOverlappedResult(socket_, &read_overlapped_, - &num_bytes, FALSE, &flags); - WSAResetEvent(read_overlapped_.hEvent); - int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); - if (ok) { - if (!ProcessSuccessfulRead(num_bytes)) - result = ERR_FAILED; - } - read_iobuffer_ = NULL; - DoReadCallback(result); -} - -bool UDPSocketWin::ProcessSuccessfulRead(int num_bytes) { - static base::StatsCounter read_bytes("udp.read_bytes"); - read_bytes.Add(num_bytes); - - // Convert address. - if (recv_from_address_) { - struct sockaddr* addr = - reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); - if (!recv_from_address_->FromSockAddr(addr, recv_addr_len_)) - return false; - } - - return true; -} - -void UDPSocketWin::DidCompleteWrite() { - DWORD num_bytes, flags; - BOOL ok = WSAGetOverlappedResult(socket_, &write_overlapped_, - &num_bytes, FALSE, &flags); - WSAResetEvent(write_overlapped_.hEvent); - int result = ok ? num_bytes : MapWinsockError(WSAGetLastError()); - if (ok) - ProcessSuccessfulWrite(num_bytes); - write_iobuffer_ = NULL; - DoWriteCallback(result); -} - -void UDPSocketWin::ProcessSuccessfulWrite(int num_bytes) { - static base::StatsCounter write_bytes("udp.write_bytes"); - write_bytes.Add(num_bytes); -} - -int UDPSocketWin::InternalRead(IOBuffer* buf, int buf_len) { - recv_addr_len_ = sizeof(recv_addr_storage_); - struct sockaddr* addr = - reinterpret_cast<struct sockaddr*>(&recv_addr_storage_); - - WSABUF read_buffer; - read_buffer.buf = buf->data(); - read_buffer.len = buf_len; - - DWORD flags = 0; - DWORD num; - AssertEventNotSignaled(read_overlapped_.hEvent); - int rv = WSARecvFrom(socket_, &read_buffer, 1, &num, &flags, addr, - &recv_addr_len_, &read_overlapped_, NULL); - if (rv == 0) { - if (ResetEventIfSignaled(read_overlapped_.hEvent)) { - // Because of how WSARecv fills memory when used asynchronously, Purify - // isn't able to detect that it's been initialized, so it scans for 0xcd - // in the buffer and reports UMRs (uninitialized memory reads) for those - // individual bytes. We override that in PURIFY builds to avoid the - // false error reports. - // See bug 5297. - base::MemoryDebug::MarkAsInitialized(read_buffer.buf, num); - if (!ProcessSuccessfulRead(num)) - return ERR_FAILED; - return static_cast<int>(num); - } - } else { - int os_error = WSAGetLastError(); - if (os_error != WSA_IO_PENDING) - return MapWinsockError(os_error); - } - read_watcher_.StartWatching(read_overlapped_.hEvent, &read_delegate_); - return ERR_IO_PENDING; -} - -int UDPSocketWin::InternalWrite(IOBuffer* buf, int buf_len) { - struct sockaddr_storage addr_storage; - size_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - - // Convert address. - if (!send_to_address_.get()) { - addr = NULL; - addr_len = 0; - } else { - if (!send_to_address_->ToSockAddr(addr, &addr_len)) - return ERR_FAILED; - } - - WSABUF write_buffer; - write_buffer.buf = buf->data(); - write_buffer.len = buf_len; - - DWORD flags = 0; - DWORD num; - AssertEventNotSignaled(write_overlapped_.hEvent); - int rv = WSASendTo(socket_, &write_buffer, 1, &num, flags, - addr, addr_len, &write_overlapped_, NULL); - if (rv == 0) { - if (ResetEventIfSignaled(write_overlapped_.hEvent)) { - ProcessSuccessfulWrite(num); - return static_cast<int>(num); - } - } else { - int os_error = WSAGetLastError(); - if (os_error != WSA_IO_PENDING) - return MapWinsockError(os_error); - } - - write_watcher_.StartWatching(write_overlapped_.hEvent, &write_delegate_); - return ERR_IO_PENDING; -} - -} // namespace net diff --git a/net/udp/udp_socket_win.h b/net/udp/udp_socket_win.h deleted file mode 100644 index d9e1dee..0000000 --- a/net/udp/udp_socket_win.h +++ /dev/null @@ -1,178 +0,0 @@ -// 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_SOCKET_WIN_H_ -#define NET_UDP_UDP_SOCKET_WIN_H_ -#pragma once - -#include <winsock2.h> - -#include "base/ref_counted.h" -#include "base/scoped_ptr.h" -#include "base/threading/non_thread_safe.h" -#include "base/win/object_watcher.h" -#include "net/base/completion_callback.h" -#include "net/base/ip_endpoint.h" -#include "net/base/io_buffer.h" -#include "net/base/net_log.h" - -namespace net { - -class BoundNetLog; - -class UDPSocketWin : public base::NonThreadSafe { - public: - UDPSocketWin(net::NetLog* net_log, - const net::NetLog::Source& source); - virtual ~UDPSocketWin(); - - // Connect the socket to connect with a certain |address|. - // Returns a net error code. - int Connect(const IPEndPoint& address); - - // Bind the address/port for this socket to |address|. This is generally - // only used on a server. - // Returns a net error code. - int Bind(const IPEndPoint& address); - - // Close the socket. - void Close(); - - // Copy the remote udp address into |address| and return a network error code. - int GetPeerAddress(IPEndPoint* address) const; - - // Copy the local udp address into |address| and return a network error code. - // (similar to getsockname) - int GetLocalAddress(IPEndPoint* address) const; - - // IO: - // Multiple outstanding read requests are not supported. - // Full duplex mode (reading and writing at the same time) is supported - - // Read from the socket. - // Only usable from the client-side of a UDP socket, after the socket - // has been connected. - int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback); - - // Write to the socket. - // Only usable from the client-side of a UDP socket, after the socket - // has been connected. - int Write(IOBuffer* buf, int buf_len, CompletionCallback* callback); - - // Read from a socket and receive sender address information. - // |buf| is the buffer to read data into. - // |buf_len| is the maximum amount of data to read. - // |address| is a buffer provided by the caller for receiving the sender - // address information about the received data. This buffer must be kept - // alive by the caller until the callback is placed. - // |address_length| is a ptr to the length of the |address| buffer. This - // is an input parameter containing the maximum size |address| can hold - // and also an output parameter for the size of |address| upon completion. - // |callback| the callback on completion of the Recv. - // Returns a net error code, or ERR_IO_PENDING if the IO is in progress. - // If ERR_IO_PENDING is returned, the caller must keep |buf|, |address|, - // and |address_length| alive until the callback is called. - int RecvFrom(IOBuffer* buf, - int buf_len, - IPEndPoint* address, - CompletionCallback* callback); - - // Send to a socket with a particular destination. - // |buf| is the buffer to send - // |buf_len| is the number of bytes to send - // |address| is the recipient address. - // |address_length| is the size of the recipient address - // |callback| is the user callback function to call on complete. - // Returns a net error code, or ERR_IO_PENDING if the IO is in progress. - // If ERR_IO_PENDING is returned, the caller must keep |buf| and |address| - // alive until the callback is called. - int SendTo(IOBuffer* buf, - int buf_len, - const IPEndPoint& address, - CompletionCallback* callback); - - // Returns true if the socket is already connected or bound. - bool is_connected() const { return socket_ != INVALID_SOCKET; } - - private: - class ReadDelegate : public base::win::ObjectWatcher::Delegate { - public: - explicit ReadDelegate(UDPSocketWin* socket) : socket_(socket) {} - virtual ~ReadDelegate() {} - - // base::ObjectWatcher::Delegate methods: - virtual void OnObjectSignaled(HANDLE object); - - private: - UDPSocketWin* const socket_; - }; - - class WriteDelegate : public base::win::ObjectWatcher::Delegate { - public: - explicit WriteDelegate(UDPSocketWin* socket) : socket_(socket) {} - virtual ~WriteDelegate() {} - - // base::ObjectWatcher::Delegate methods: - virtual void OnObjectSignaled(HANDLE object); - - private: - UDPSocketWin* const socket_; - }; - - void DoReadCallback(int rv); - void DoWriteCallback(int rv); - void DidCompleteRead(); - void DidCompleteWrite(); - bool ProcessSuccessfulRead(int num_bytes); - void ProcessSuccessfulWrite(int num_bytes); - - // Returns the OS error code (or 0 on success). - int CreateSocket(const IPEndPoint& address); - - int InternalRead(IOBuffer* buf, int buf_len); - int InternalWrite(IOBuffer* buf, int buf_len); - - SOCKET socket_; - - // These are mutable since they're just cached copies to make - // GetPeerAddress/GetLocalAddress smarter. - mutable scoped_ptr<IPEndPoint> local_address_; - mutable scoped_ptr<IPEndPoint> remote_address_; - - // The socket's win wrappers - ReadDelegate read_delegate_; - WriteDelegate write_delegate_; - - // Watchers to watch for events from Read() and Write(). - base::win::ObjectWatcher read_watcher_; - base::win::ObjectWatcher write_watcher_; - - // OVERLAPPED for pending read and write operations. - OVERLAPPED read_overlapped_; - OVERLAPPED write_overlapped_; - - // The buffer used by InternalRead() to retry Read requests - scoped_refptr<IOBuffer> read_iobuffer_; - struct sockaddr_storage recv_addr_storage_; - socklen_t recv_addr_len_; - IPEndPoint* recv_from_address_; - - // The buffer used by InternalWrite() to retry Write requests - scoped_refptr<IOBuffer> write_iobuffer_; - scoped_ptr<IPEndPoint> send_to_address_; - - // External callback; called when read is complete. - CompletionCallback* read_callback_; - - // External callback; called when write is complete. - CompletionCallback* write_callback_; - - BoundNetLog net_log_; - - DISALLOW_COPY_AND_ASSIGN(UDPSocketWin); -}; - -} // namespace net - -#endif // NET_UDP_UDP_SOCKET_WIN_H_ |