diff options
author | justinlin@chromium.org <justinlin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-17 06:59:40 +0000 |
---|---|---|
committer | justinlin@chromium.org <justinlin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-17 06:59:40 +0000 |
commit | 68f2a23a4c269a19e6305598ae097ec652b3313a (patch) | |
tree | 6d5d571e5e252baf38bea75b90cffda84a58eb54 | |
parent | 77c3fcde3f4fce9d1dca8a9b917d4e0a08c1ae2a (diff) | |
download | chromium_src-68f2a23a4c269a19e6305598ae097ec652b3313a.zip chromium_src-68f2a23a4c269a19e6305598ae097ec652b3313a.tar.gz chromium_src-68f2a23a4c269a19e6305598ae097ec652b3313a.tar.bz2 |
Allow server sockets to rebind to same port if there is nothing actively listening on that port.
BUG=
Review URL: https://chromiumcodereview.appspot.com/10907154
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157087 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc | 3 | ||||
-rw-r--r-- | net/socket/server_socket.h | 4 | ||||
-rw-r--r-- | net/socket/tcp_server_socket_libevent.cc | 25 | ||||
-rw-r--r-- | net/socket/tcp_server_socket_libevent.h | 4 | ||||
-rw-r--r-- | net/socket/tcp_server_socket_win.cc | 27 | ||||
-rw-r--r-- | net/socket/tcp_server_socket_win.h | 10 |
6 files changed, 68 insertions, 5 deletions
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc index 87f3ab4..ce77102 100644 --- a/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc +++ b/content/browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc @@ -46,6 +46,9 @@ class FakeServerSocket : public net::ServerSocket { } // net::ServerSocket implementation. + virtual void AllowAddressReuse() { + } + virtual int Listen(const net::IPEndPoint& address, int backlog) OVERRIDE { local_address_ = address; listening_ = true; diff --git a/net/socket/server_socket.h b/net/socket/server_socket.h index 11151ee..a48ebec 100644 --- a/net/socket/server_socket.h +++ b/net/socket/server_socket.h @@ -19,6 +19,10 @@ class NET_EXPORT ServerSocket { ServerSocket() { } virtual ~ServerSocket() { } + // Allows the socket to share the local address to which the socket will be + // bound with other processes. Should be called before Listen(). + virtual void AllowAddressReuse() = 0; + // Bind the socket and start listening. Destroy the socket to stop // listening. virtual int Listen(const net::IPEndPoint& address, int backlog) = 0; diff --git a/net/socket/tcp_server_socket_libevent.cc b/net/socket/tcp_server_socket_libevent.cc index ef8d1b1..879ec8e 100644 --- a/net/socket/tcp_server_socket_libevent.cc +++ b/net/socket/tcp_server_socket_libevent.cc @@ -35,6 +35,7 @@ TCPServerSocketLibevent::TCPServerSocketLibevent( const net::NetLog::Source& source) : socket_(kInvalidSocket), accept_socket_(NULL), + reuse_address_(false), net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, source.ToEventParametersCallback()); @@ -46,6 +47,13 @@ TCPServerSocketLibevent::~TCPServerSocketLibevent() { net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); } +void TCPServerSocketLibevent::AllowAddressReuse() { + DCHECK(CalledOnValidThread()); + DCHECK_EQ(socket_, kInvalidSocket); + + reuse_address_ = true; +} + int TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) { DCHECK(CalledOnValidThread()); DCHECK_GT(backlog, 0); @@ -63,11 +71,15 @@ int TCPServerSocketLibevent::Listen(const IPEndPoint& address, int backlog) { return result; } + int result = SetSocketOptions(); + if (result != OK) + return result; + SockaddrStorage storage; if (!address.ToSockAddr(storage.addr, &storage.addr_len)) return ERR_INVALID_ARGUMENT; - int result = bind(socket_, storage.addr, storage.addr_len); + result = bind(socket_, storage.addr, storage.addr_len); if (result < 0) { PLOG(ERROR) << "bind() returned an error"; result = MapSystemError(errno); @@ -125,6 +137,17 @@ int TCPServerSocketLibevent::Accept( return result; } +int TCPServerSocketLibevent::SetSocketOptions() { + int true_value = 1; + if (reuse_address_) { + int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, + sizeof(true_value)); + if (rv < 0) + return MapSystemError(errno); + } + return OK; +} + int TCPServerSocketLibevent::AcceptInternal( scoped_ptr<StreamSocket>* socket) { SockaddrStorage storage; diff --git a/net/socket/tcp_server_socket_libevent.h b/net/socket/tcp_server_socket_libevent.h index 946cc50..3b8d71e 100644 --- a/net/socket/tcp_server_socket_libevent.h +++ b/net/socket/tcp_server_socket_libevent.h @@ -26,6 +26,7 @@ class NET_EXPORT_PRIVATE TCPServerSocketLibevent virtual ~TCPServerSocketLibevent(); // net::ServerSocket implementation. + virtual void AllowAddressReuse() OVERRIDE; virtual int Listen(const net::IPEndPoint& address, int backlog) OVERRIDE; virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE; virtual int Accept(scoped_ptr<StreamSocket>* socket, @@ -36,6 +37,7 @@ class NET_EXPORT_PRIVATE TCPServerSocketLibevent virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE; private: + int SetSocketOptions(); int AcceptInternal(scoped_ptr<StreamSocket>* socket); void Close(); @@ -46,6 +48,8 @@ class NET_EXPORT_PRIVATE TCPServerSocketLibevent scoped_ptr<StreamSocket>* accept_socket_; CompletionCallback accept_callback_; + bool reuse_address_; + BoundNetLog net_log_; }; diff --git a/net/socket/tcp_server_socket_win.cc b/net/socket/tcp_server_socket_win.cc index eb15ffb..817e73a 100644 --- a/net/socket/tcp_server_socket_win.cc +++ b/net/socket/tcp_server_socket_win.cc @@ -21,6 +21,7 @@ TCPServerSocketWin::TCPServerSocketWin(net::NetLog* net_log, : socket_(INVALID_SOCKET), socket_event_(WSA_INVALID_EVENT), accept_socket_(NULL), + reuse_address_(false), net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, source.ToEventParametersCallback()); @@ -32,6 +33,14 @@ TCPServerSocketWin::~TCPServerSocketWin() { net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE); } +void TCPServerSocketWin::AllowAddressReuse() { + DCHECK(CalledOnValidThread()); + DCHECK_EQ(socket_, INVALID_SOCKET); + DCHECK_EQ(socket_event_, WSA_INVALID_EVENT); + + reuse_address_ = true; +} + int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) { DCHECK(CalledOnValidThread()); DCHECK_GT(backlog, 0); @@ -56,11 +65,15 @@ int TCPServerSocketWin::Listen(const IPEndPoint& address, int backlog) { return result; } + int result = SetSocketOptions(); + if (result != OK) + return result; + SockaddrStorage storage; if (!address.ToSockAddr(storage.addr, &storage.addr_len)) return ERR_INVALID_ARGUMENT; - int result = bind(socket_, storage.addr, storage.addr_len); + result = bind(socket_, storage.addr, storage.addr_len); if (result < 0) { PLOG(ERROR) << "bind() returned an error"; result = MapSystemError(WSAGetLastError()); @@ -115,6 +128,18 @@ int TCPServerSocketWin::Accept( return result; } +int TCPServerSocketWin::SetSocketOptions() { + BOOL true_value = 1; + if (reuse_address_) { + int rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast<const char*>(&true_value), + sizeof(true_value)); + if (rv < 0) + return MapSystemError(errno); + } + return OK; +} + int TCPServerSocketWin::AcceptInternal(scoped_ptr<StreamSocket>* socket) { SockaddrStorage storage; int new_socket = accept(socket_, storage.addr, &storage.addr_len); diff --git a/net/socket/tcp_server_socket_win.h b/net/socket/tcp_server_socket_win.h index a7ab78c..fab8bf0 100644 --- a/net/socket/tcp_server_socket_win.h +++ b/net/socket/tcp_server_socket_win.h @@ -29,15 +29,17 @@ class NET_EXPORT_PRIVATE TCPServerSocketWin ~TCPServerSocketWin(); // net::ServerSocket implementation. - virtual int Listen(const net::IPEndPoint& address, int backlog); - virtual int GetLocalAddress(IPEndPoint* address) const; + virtual void AllowAddressReuse() OVERRIDE; + virtual int Listen(const net::IPEndPoint& address, int backlog) OVERRIDE; + virtual int GetLocalAddress(IPEndPoint* address) const OVERRIDE; virtual int Accept(scoped_ptr<StreamSocket>* socket, - const CompletionCallback& callback); + const CompletionCallback& callback) OVERRIDE; // base::ObjectWatcher::Delegate implementation. virtual void OnObjectSignaled(HANDLE object); private: + int SetSocketOptions(); int AcceptInternal(scoped_ptr<StreamSocket>* socket); void Close(); @@ -49,6 +51,8 @@ class NET_EXPORT_PRIVATE TCPServerSocketWin scoped_ptr<StreamSocket>* accept_socket_; CompletionCallback accept_callback_; + bool reuse_address_; + BoundNetLog net_log_; }; |