Chromium Code Reviews| Index: chrome/browser/extensions/api/socket/tcp_socket.cc |
| diff --git a/chrome/browser/extensions/api/socket/tcp_socket.cc b/chrome/browser/extensions/api/socket/tcp_socket.cc |
| index cde2685a043646dd2e390ba2928748919a77fd6d..11c6941b9f0246bd26d7696db683dde536336dee 100644 |
| --- a/chrome/browser/extensions/api/socket/tcp_socket.cc |
| +++ b/chrome/browser/extensions/api/socket/tcp_socket.cc |
| @@ -38,23 +38,37 @@ TCPSocket::~TCPSocket() { |
| } |
| } |
| -int TCPSocket::Connect(const std::string& address, int port) { |
| - if (is_connected_) |
| - return net::ERR_CONNECTION_FAILED; |
| - |
| - net::AddressList address_list; |
| - if (!StringAndPortToAddressList(address, port, &address_list)) |
| - return net::ERR_INVALID_ARGUMENT; |
| - |
| - socket_.reset(new net::TCPClientSocket(address_list, NULL, |
| - net::NetLog::Source())); |
| - |
| - int result = socket_->Connect(base::Bind( |
| - &TCPSocket::OnConnect, base::Unretained(this))); |
| - if (result == net::OK) { |
| - is_connected_ = true; |
| +void TCPSocket::Connect(const std::string& address, |
| + int port, |
| + const CompletionCallback& callback) { |
| + DCHECK(!callback.is_null()); |
| + |
| + if (!connect_callback_.is_null()) { |
| + callback.Run(net::ERR_CONNECTION_FAILED); |
| + return; |
| } |
| - return result; |
| + connect_callback_ = callback; |
| + |
| + int result = net::ERR_CONNECTION_FAILED; |
| + do { |
| + if (is_connected_) |
| + break; |
| + |
| + net::AddressList address_list; |
| + if (!StringAndPortToAddressList(address, port, &address_list)) { |
| + result = net::ERR_ADDRESS_INVALID; |
| + break; |
| + } |
| + |
| + socket_.reset(new net::TCPClientSocket(address_list, NULL, |
| + net::NetLog::Source())); |
| + connect_callback_ = callback; |
| + result = socket_->Connect(base::Bind( |
| + &TCPSocket::OnConnectComplete, base::Unretained(this))); |
| + } while (false); |
| + |
| + if (result != net::ERR_IO_PENDING) |
| + OnConnectComplete(result); |
| } |
| void TCPSocket::Disconnect() { |
| @@ -67,42 +81,102 @@ int TCPSocket::Bind(const std::string& address, int port) { |
| return net::ERR_FAILED; |
| } |
| -int TCPSocket::Read(scoped_refptr<net::IOBuffer> io_buffer, int io_buffer_len) { |
| - if (!socket_.get() || !socket_->IsConnected()) |
| - return net::ERR_SOCKET_NOT_CONNECTED; |
| +void TCPSocket::Read(int count, |
| + const ReadCompletionCallback& callback) { |
| + DCHECK(!callback.is_null()); |
| + |
| + if (!read_callback_.is_null()) { |
| + callback.Run(net::ERR_TRY_AGAIN, NULL); |
|
agl
2012/05/04 16:52:17
In net/ there is a convention that functions that
|
| + return; |
| + } else { |
| + read_callback_ = callback; |
| + } |
| - return socket_->Read( |
| - io_buffer.get(), |
| - io_buffer_len, |
| - base::Bind(&Socket::OnDataRead, base::Unretained(this), io_buffer, |
| - static_cast<net::IPEndPoint*>(NULL))); |
| + int result = net::ERR_FAILED; |
| + scoped_refptr<net::IOBuffer> io_buffer; |
| + do { |
| + if (count < 0) { |
| + result = net::ERR_INVALID_ARGUMENT; |
| + break; |
| + } |
| + |
| + if (!socket_.get() || !socket_->IsConnected()) { |
| + result = net::ERR_SOCKET_NOT_CONNECTED; |
| + break; |
| + } |
| + |
| + io_buffer = new net::IOBuffer(count); |
| + result = socket_->Read(io_buffer.get(), count, |
| + base::Bind(&TCPSocket::OnReadComplete, base::Unretained(this), |
| + io_buffer)); |
| + } while (false); |
| + |
| + if (result != net::ERR_IO_PENDING) |
| + OnReadComplete(io_buffer, result); |
| } |
| -int TCPSocket::Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) { |
| - if (!socket_.get() || !socket_->IsConnected()) |
| - return net::ERR_SOCKET_NOT_CONNECTED; |
| +void TCPSocket::Write(scoped_refptr<net::IOBuffer> io_buffer, |
| + int byte_count, |
| + const CompletionCallback& callback) { |
| + DCHECK(!callback.is_null()); |
| + |
| + if (!write_callback_.is_null()) { |
| + // TODO(penghuang): Put requests in a pending queue to support multiple |
| + // write calls. |
| + callback.Run(net::ERR_TRY_AGAIN); |
| + return; |
| + } else { |
| + write_callback_ = callback; |
| + } |
| + |
| + int result = net::ERR_FAILED; |
| + do { |
| + if (!socket_.get() || !socket_->IsConnected()) { |
| + result = net::ERR_SOCKET_NOT_CONNECTED; |
| + break; |
| + } |
| - return socket_->Write( |
| - io_buffer.get(), byte_count, |
| - base::Bind(&Socket::OnWriteComplete, base::Unretained(this))); |
| + result = socket_->Write( |
| + io_buffer.get(), byte_count, |
| + base::Bind(&TCPSocket::OnWriteComplete, base::Unretained(this))); |
| + } while (false); |
| + |
| + if (result != net::ERR_IO_PENDING) |
| + OnWriteComplete(result); |
| } |
| -int TCPSocket::RecvFrom(scoped_refptr<net::IOBuffer> io_buffer, |
| - int io_buffer_len, |
| - net::IPEndPoint* address) { |
| - return net::ERR_FAILED; |
| +void TCPSocket::RecvFrom(int count, |
| + const RecvFromCompletionCallback& callback) { |
| + callback.Run(net::ERR_FAILED, NULL, NULL, 0); |
| } |
| -int TCPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, |
| - int byte_count, |
| - const std::string& address, |
| - int port) { |
| - return net::ERR_FAILED; |
| +void TCPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer, |
| + int byte_count, |
| + const std::string& address, |
| + int port, |
| + const CompletionCallback& callback) { |
| + callback.Run(net::ERR_FAILED); |
| } |
| -void TCPSocket::OnConnect(int result) { |
| +void TCPSocket::OnConnectComplete(int result) { |
| + DCHECK(!connect_callback_.is_null()); |
| + DCHECK(!is_connected_); |
| is_connected_ = result == net::OK; |
| - event_notifier()->OnConnectComplete(result); |
| + connect_callback_.Run(result); |
| + connect_callback_.Reset(); |
| +} |
| + |
| +void TCPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer, |
| + int result) { |
| + DCHECK(!read_callback_.is_null()); |
| + read_callback_.Run(result, io_buffer); |
| + read_callback_.Reset(); |
| +} |
| + |
| +void TCPSocket::OnWriteComplete(int result) { |
| + DCHECK(!write_callback_.is_null()); |
| + write_callback_.Run(result); |
| + write_callback_.Reset(); |
| } |
| } // namespace extensions |