| 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..8c1b1b7a53fe87fa939d1f35204b489462f6af2d 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_IO_PENDING, NULL);
|
| + 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_IO_PENDING);
|
| + 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
|
|
|