summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/SConscript4
-rw-r--r--net/base/tcp_client_socket.h71
-rw-r--r--net/base/tcp_client_socket_libevent.cc288
3 files changed, 19 insertions, 344 deletions
diff --git a/net/SConscript b/net/SConscript
index 98d0730..b735894 100644
--- a/net/SConscript
+++ b/net/SConscript
@@ -132,7 +132,6 @@ if env['PLATFORM'] == 'posix':
input_files.extend([
# TODO(tc): gnome-vfs? xdgmime? /etc/mime.types?
'base/platform_mime_util_linux.cc',
- 'base/tcp_client_socket_libevent.cc',
])
if env['PLATFORM'] in ('darwin', 'posix'):
@@ -169,7 +168,6 @@ env_tests.Prepend(
'net', # net must come before base and modp_b64
'bzip2', # bzip2 must come before base
'base',
- 'event',
'googleurl',
'gtest',
'icuuc',
@@ -225,7 +223,6 @@ unittest_files = [
'base/net_util_unittest.cc',
'base/registry_controlled_domain_unittest.cc',
'base/run_all_unittests.cc',
- 'base/tcp_client_socket_unittest.cc',
'base/test_completion_callback_unittest.cc',
'disk_cache/addr_unittest.cc',
'disk_cache/block_files_unittest.cc',
@@ -244,6 +241,7 @@ if env['PLATFORM'] == 'win32':
'base/directory_lister_unittest.cc',
'base/ssl_config_service_unittest.cc',
'base/ssl_client_socket_unittest.cc',
+ 'base/tcp_client_socket_unittest.cc',
'base/wininet_util_unittest.cc',
'disk_cache/backend_unittest.cc',
'http/http_cache_unittest.cc',
diff --git a/net/base/tcp_client_socket.h b/net/base/tcp_client_socket.h
index 32cd59a..06a57fe 100644
--- a/net/base/tcp_client_socket.h
+++ b/net/base/tcp_client_socket.h
@@ -5,19 +5,9 @@
#ifndef NET_BASE_TCP_CLIENT_SOCKET_H_
#define NET_BASE_TCP_CLIENT_SOCKET_H_
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
#include <ws2tcpip.h>
+
#include "base/object_watcher.h"
-#elif defined(OS_POSIX)
-struct event; // From libevent
-#define SOCKET int
-#include "base/message_pump_libevent.h"
-#endif
-
-#include "base/completion_callback.h"
-#include "base/scoped_ptr.h"
#include "net/base/address_list.h"
#include "net/base/client_socket.h"
@@ -28,12 +18,7 @@ namespace net {
// NOTE: The implementation supports half duplex only. Read and Write calls
// must not be in progress at the same time.
class TCPClientSocket : public ClientSocket,
-#if defined(OS_WIN)
- public base::ObjectWatcher::Delegate
-#elif defined(OS_POSIX)
- public base::MessagePumpLibevent::Watcher
-#endif
-{
+ public base::ObjectWatcher::Delegate {
public:
// The IP address(es) and port number to connect to. The TCP socket will try
// each IP address in the list until it succeeds in establishing a
@@ -49,23 +34,31 @@ class TCPClientSocket : public ClientSocket,
virtual bool IsConnected() const;
// Socket methods:
- // Try to transfer buf_len bytes to/from socket.
- // If a result is available now, return it; else call back later with one.
- // Do not call again until a result is returned!
- // If any bytes were transferred, the result is the byte count.
- // On error, result is a negative error code; see net/base/net_error_list.h
- // TODO: what would a zero return value indicate?
- // TODO: support multiple outstanding requests?
virtual int Read(char* buf, int buf_len, CompletionCallback* callback);
virtual int Write(const char* buf, int buf_len, CompletionCallback* callback);
private:
+ int CreateSocket(const struct addrinfo* ai);
+ void DoCallback(int rv);
+ void DidCompleteConnect();
+ void DidCompleteIO();
+
+ // base::ObjectWatcher::Delegate methods:
+ virtual void OnObjectSignaled(HANDLE object);
+
SOCKET socket_;
+ OVERLAPPED overlapped_;
+ WSABUF buffer_;
+
+ base::ObjectWatcher watcher_;
+
+ CompletionCallback* callback_;
// The list of addresses we should try in order to establish a connection.
AddressList addresses_;
- // Where we are in above list, or NULL if all addrinfos have been tried.
+ // The addrinfo that we are attempting to use or NULL if all addrinfos have
+ // been tried.
const struct addrinfo* current_ai_;
enum WaitState {
@@ -75,34 +68,6 @@ class TCPClientSocket : public ClientSocket,
WAITING_WRITE
};
WaitState wait_state_;
-
-#if defined(OS_WIN)
- // base::ObjectWatcher::Delegate methods:
- virtual void OnObjectSignaled(HANDLE object);
-
- OVERLAPPED overlapped_;
- WSABUF buffer_;
-
- base::ObjectWatcher watcher_;
-#elif defined(OS_POSIX)
- // The socket's libevent wrapper
- scoped_ptr<event> event_;
-
- // Called by MessagePumpLibevent when the socket is ready to do I/O
- void OnSocketReady(short flags);
-
- // The buffer used by OnSocketReady to retry Read and Write requests
- char* buf_;
- int buf_len_;
-#endif
-
- // External callback; called when read or write is complete.
- CompletionCallback* callback_;
-
- int CreateSocket(const struct addrinfo* ai);
- void DoCallback(int rv);
- void DidCompleteConnect();
- void DidCompleteIO();
};
} // namespace net
diff --git a/net/base/tcp_client_socket_libevent.cc b/net/base/tcp_client_socket_libevent.cc
deleted file mode 100644
index 7f815c3..0000000
--- a/net/base/tcp_client_socket_libevent.cc
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright (c) 2006-2008 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/tcp_client_socket.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <sys/socket.h>
-
-#include "base/message_loop.h"
-#include "net/base/net_errors.h"
-#include "third_party/libevent/event.h"
-
-
-namespace net {
-
-const int kInvalidSocket = -1;
-
-// Return 0 on success
-// Too small a function to bother putting in a library?
-static int SetNonBlocking(int fd)
-{
- int flags = fcntl(fd, F_GETFL, 0);
- if (-1 == flags)
- flags = 0;
- return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
-}
-
-// Convert values from <errno.h> to values from "net/base/net_errors.h"
-static int MapPosixError(int err) {
- // There are numerous posix error codes, but these are the ones we thus far
- // find interesting.
- // TODO(port): fill this with a real conversion table
- switch (err) {
- case EWOULDBLOCK: return ERR_IO_PENDING;
- default:
- return ERR_FAILED;
- }
-}
-
-//-----------------------------------------------------------------------------
-
-TCPClientSocket::TCPClientSocket(const AddressList& addresses)
- : socket_(kInvalidSocket),
- addresses_(addresses),
- current_ai_(addresses_.head()),
- wait_state_(NOT_WAITING),
- event_(new event) {
-}
-
-TCPClientSocket::~TCPClientSocket() {
- Disconnect();
-}
-
-int TCPClientSocket::Connect(CompletionCallback* callback) {
-
- // If already connected, then just return OK.
- if (socket_ != kInvalidSocket)
- return OK;
-
- DCHECK(wait_state_ == NOT_WAITING);
-
- const addrinfo* ai = current_ai_;
- DCHECK(ai);
-
- int rv = CreateSocket(ai);
- if (rv != OK)
- return rv;
-
- if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) {
- // Connected without waiting!
- return OK;
- }
-
- // Synchronous operation not supported
- DCHECK(callback);
-
- if (errno != EINPROGRESS && errno != EWOULDBLOCK) {
- LOG(ERROR) << "connect failed: " << errno;
- return MapPosixError(errno);
- }
-
- // Initialize event_ and link it to our MessagePump.
- // POLLOUT is set if the connection is established.
- // POLLIN is set if the connection fails,
- // so select for both read and write.
- MessageLoopForIO::current()->WatchSocket(
- socket_, EV_READ|EV_WRITE|EV_PERSIST, event_.get(), this);
-
- wait_state_ = WAITING_CONNECT;
- callback_ = callback;
- return ERR_IO_PENDING;
-}
-
-int TCPClientSocket::ReconnectIgnoringLastError(CompletionCallback* callback) {
- // No ignorable errors!
- return ERR_FAILED;
-}
-
-void TCPClientSocket::Disconnect() {
- if (socket_ == kInvalidSocket)
- return;
-
- MessageLoopForIO::current()->UnwatchSocket(event_.get());
- close(socket_);
- socket_ = kInvalidSocket;
-
- // Reset for next time.
- current_ai_ = addresses_.head();
-}
-
-bool TCPClientSocket::IsConnected() const {
- if (socket_ == kInvalidSocket || wait_state_ == WAITING_CONNECT)
- return false;
-
- // Check if connection is alive.
- char c;
- int rv = recv(socket_, &c, 1, MSG_PEEK);
- if (rv == 0)
- return false;
-
- return true;
-}
-
-int TCPClientSocket::Read(char* buf,
- int buf_len,
- CompletionCallback* callback) {
- DCHECK(socket_ != kInvalidSocket);
- DCHECK(wait_state_ == NOT_WAITING);
- DCHECK(!callback_);
- // Synchronous operation not supported
- DCHECK(callback);
- DCHECK(buf_len > 0);
-
- int nread = read(socket_, buf, buf_len);
- if (nread > 0) {
- return nread;
- }
- if (nread == -1 && errno != EWOULDBLOCK)
- return MapPosixError(errno);
-
- MessageLoopForIO::current()->WatchSocket(
- socket_, EV_READ|EV_PERSIST, event_.get(), this);
-
- buf_ = buf;
- buf_len_ = buf_len;
- wait_state_ = WAITING_READ;
- callback_ = callback;
- return ERR_IO_PENDING;
-}
-
-int TCPClientSocket::Write(const char* buf,
- int buf_len,
- CompletionCallback* callback) {
- DCHECK(socket_ != kInvalidSocket);
- DCHECK(wait_state_ == NOT_WAITING);
- DCHECK(!callback_);
- // Synchronous operation not supported
- DCHECK(callback);
- DCHECK(buf_len > 0);
-
- int nwrite = write(socket_, buf, buf_len);
- if (nwrite > 0) {
- return nwrite;
- }
- if (nwrite == -1 && errno != EWOULDBLOCK)
- return MapPosixError(errno);
-
- MessageLoopForIO::current()->WatchSocket(
- socket_, EV_WRITE|EV_PERSIST, event_.get(), this);
-
- buf_ = const_cast<char*>(buf);
- buf_len_ = buf_len;
- wait_state_ = WAITING_WRITE;
- callback_ = callback;
- return ERR_IO_PENDING;
-}
-
-int TCPClientSocket::CreateSocket(const addrinfo* ai) {
- socket_ = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- if (socket_ == kInvalidSocket)
- return MapPosixError(errno);
-
- // All our socket I/O is nonblocking
- if (SetNonBlocking(socket_))
- return MapPosixError(errno);
-
- return OK;
-}
-
-void TCPClientSocket::DoCallback(int rv) {
- DCHECK(rv != ERR_IO_PENDING);
- DCHECK(callback_);
-
- // since Run may result in Read being called, clear callback_ up front.
- CompletionCallback* c = callback_;
- callback_ = NULL;
- c->Run(rv);
-}
-
-void TCPClientSocket::DidCompleteConnect() {
- int result = ERR_UNEXPECTED;
-
- wait_state_ = NOT_WAITING;
-
- // Check to see if connect succeeded
- int error_code = -1;
- socklen_t len = sizeof(error_code);
- if (getsockopt(socket_, SOL_SOCKET, SO_ERROR,
- reinterpret_cast<char*>(&error_code), &len) < 0) {
- result = MapPosixError(errno);
- } else if (error_code == EINPROGRESS) {
- result = ERR_IO_PENDING;
- // And await next callback. Haven't seen this case yet myself.
- } else if (current_ai_->ai_next && (
- error_code == EADDRNOTAVAIL ||
- error_code == EAFNOSUPPORT ||
- error_code == ECONNREFUSED ||
- error_code == ENETUNREACH ||
- error_code == EHOSTUNREACH ||
- error_code == ETIMEDOUT)) {
- // This address failed, try next one in list.
- const addrinfo* next = current_ai_->ai_next;
- Disconnect();
- current_ai_ = next;
- result = Connect(callback_);
- } else if (error_code) {
- result = MapPosixError(error_code);
- } else {
- result = 0;
- MessageLoopForIO::current()->UnwatchSocket(event_.get());
- }
-
- if (result != ERR_IO_PENDING)
- DoCallback(result);
-}
-
-void TCPClientSocket::DidCompleteIO() {
- int bytes_transferred;
- switch (wait_state_) {
- case WAITING_READ:
- bytes_transferred = read(socket_, buf_, buf_len_);
- break;
- case WAITING_WRITE:
- bytes_transferred = write(socket_, buf_, buf_len_);
- break;
- default:
- NOTREACHED();
- }
-
- int result;
- if (bytes_transferred > 0) {
- result = bytes_transferred;
- } else if (bytes_transferred == 0) {
- // TODO(port): can we tell why it closed, and return a more informative
- // message? And why does the unit test want to see zero?
- //result = ERR_CONNECTION_CLOSED;
- result = 0;
- } else {
- result = MapPosixError(errno);
- }
-
- if (result != ERR_IO_PENDING) {
- wait_state_ = NOT_WAITING;
- MessageLoopForIO::current()->UnwatchSocket(event_.get());
- DoCallback(result);
- }
-}
-
-void TCPClientSocket::OnSocketReady(short flags) {
- switch (wait_state_) {
- case WAITING_CONNECT:
- DidCompleteConnect();
- break;
- case WAITING_READ:
- case WAITING_WRITE:
- DidCompleteIO();
- break;
- default:
- NOTREACHED();
- break;
- }
-}
-
-} // namespace net
-