| Index: chrome/browser/extensions/api/socket/udp_socket.cc
|
| diff --git a/chrome/browser/extensions/api/socket/udp_socket.cc b/chrome/browser/extensions/api/socket/udp_socket.cc
|
| index 45688b43245fc8d44a93b6d61f25d86c2def8f59..b6a2904d50340c5b05581ee014fc2bc5f5eb244d 100644
|
| --- a/chrome/browser/extensions/api/socket/udp_socket.cc
|
| +++ b/chrome/browser/extensions/api/socket/udp_socket.cc
|
| @@ -27,17 +27,25 @@ UDPSocket::~UDPSocket() {
|
| }
|
| }
|
|
|
| -int UDPSocket::Connect(const std::string& address, int port) {
|
| - if (is_connected_)
|
| - return net::ERR_CONNECTION_FAILED;
|
| -
|
| - net::IPEndPoint ip_end_point;
|
| - if (!StringAndPortToIPEndPoint(address, port, &ip_end_point))
|
| - return net::ERR_INVALID_ARGUMENT;
|
| -
|
| - int result = socket_.Connect(ip_end_point);
|
| - is_connected_ = (result == net::OK);
|
| - return result;
|
| +void UDPSocket::Connect(const std::string& address,
|
| + int port,
|
| + const CompletionCallback& callback) {
|
| + int result = net::ERR_CONNECTION_FAILED;
|
| + do {
|
| + if (is_connected_)
|
| + break;
|
| +
|
| + net::IPEndPoint ip_end_point;
|
| + if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
|
| + result = net::ERR_ADDRESS_INVALID;
|
| + break;
|
| + }
|
| +
|
| + result = socket_.Connect(ip_end_point);
|
| + is_connected_ = (result == net::OK);
|
| + } while (false);
|
| +
|
| + callback.Run(result);
|
| }
|
|
|
| int UDPSocket::Bind(const std::string& address, int port) {
|
| @@ -53,56 +61,181 @@ void UDPSocket::Disconnect() {
|
| socket_.Close();
|
| }
|
|
|
| -int UDPSocket::Read(scoped_refptr<net::IOBuffer> io_buffer, int io_buffer_len) {
|
| - if (!socket_.is_connected())
|
| - return net::ERR_SOCKET_NOT_CONNECTED;
|
| +void UDPSocket::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_.is_connected()) {
|
| + result = net::ERR_SOCKET_NOT_CONNECTED;
|
| + break;
|
| + }
|
| +
|
| + io_buffer = new net::IOBuffer(count);
|
| + result = socket_.Read(io_buffer.get(), count,
|
| + base::Bind(&UDPSocket::OnReadComplete, base::Unretained(this),
|
| + io_buffer));
|
| + } while (false);
|
| +
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnReadComplete(io_buffer, result);
|
| }
|
|
|
| -int UDPSocket::Write(scoped_refptr<net::IOBuffer> io_buffer, int byte_count) {
|
| - if (!socket_.is_connected())
|
| - return net::ERR_SOCKET_NOT_CONNECTED;
|
| +void UDPSocket::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_.is_connected()) {
|
| + result = net::ERR_SOCKET_NOT_CONNECTED;
|
| + break;
|
| + }
|
| +
|
| + result = socket_.Write(
|
| + io_buffer.get(), byte_count,
|
| + base::Bind(&UDPSocket::OnWriteComplete, base::Unretained(this)));
|
| + } while (false);
|
|
|
| - return socket_.Write(
|
| - io_buffer.get(), byte_count,
|
| - base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnWriteComplete(result);
|
| }
|
|
|
| -int UDPSocket::RecvFrom(scoped_refptr<net::IOBuffer> io_buffer,
|
| - int io_buffer_len,
|
| - net::IPEndPoint* address) {
|
| - if (!socket_.is_connected())
|
| - return net::ERR_SOCKET_NOT_CONNECTED;
|
| -
|
| - return socket_.RecvFrom(
|
| - io_buffer.get(),
|
| - io_buffer_len,
|
| - address,
|
| - base::Bind(&Socket::OnDataRead, base::Unretained(this), io_buffer,
|
| - address));
|
| +void UDPSocket::RecvFrom(int count,
|
| + const RecvFromCompletionCallback& callback) {
|
| + DCHECK(!callback.is_null());
|
| +
|
| + if (!recv_from_callback_.is_null()) {
|
| + callback.Run(net::ERR_IO_PENDING, NULL, NULL, 0);
|
| + return;
|
| + } else {
|
| + recv_from_callback_ = callback;
|
| + }
|
| +
|
| + int result = net::ERR_FAILED;
|
| + scoped_refptr<net::IOBuffer> io_buffer;
|
| + scoped_refptr<IPEndPoint> address;
|
| + do {
|
| + if (count < 0) {
|
| + result = net::ERR_INVALID_ARGUMENT;
|
| + break;
|
| + }
|
| +
|
| + if (!socket_.is_connected()) {
|
| + result = net::ERR_SOCKET_NOT_CONNECTED;
|
| + break;
|
| + }
|
| +
|
| + io_buffer = new net::IOBuffer(count);
|
| + address = new IPEndPoint();
|
| + result = socket_.RecvFrom(
|
| + io_buffer.get(),
|
| + count,
|
| + &address->data,
|
| + base::Bind(&UDPSocket::OnRecvFromComplete,
|
| + base::Unretained(this),
|
| + io_buffer,
|
| + address));
|
| + } while (false);
|
| +
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnRecvFromComplete(io_buffer, address, result);
|
| }
|
|
|
| -int UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
|
| - int byte_count,
|
| - const std::string& address,
|
| - int port) {
|
| - net::IPEndPoint ip_end_point;
|
| - if (!StringAndPortToIPEndPoint(address, port, &ip_end_point))
|
| - return net::ERR_INVALID_ARGUMENT;
|
| +void UDPSocket::SendTo(scoped_refptr<net::IOBuffer> io_buffer,
|
| + int byte_count,
|
| + const std::string& address,
|
| + int port,
|
| + const CompletionCallback& callback) {
|
| + DCHECK(!callback.is_null());
|
| +
|
| + if (!send_to_callback_.is_null()) {
|
| + // TODO(penghuang): Put requests in a pending queue to support multiple
|
| + // sendTo calls.
|
| + callback.Run(net::ERR_IO_PENDING);
|
| + return;
|
| + } else {
|
| + send_to_callback_ = callback;
|
| + }
|
| +
|
| + int result = net::ERR_FAILED;
|
| + do {
|
| + net::IPEndPoint ip_end_point;
|
| + if (!StringAndPortToIPEndPoint(address, port, &ip_end_point)) {
|
| + result = net::ERR_ADDRESS_INVALID;
|
| + break;
|
| + }
|
| +
|
| + if (!socket_.is_connected()) {
|
| + result = net::ERR_SOCKET_NOT_CONNECTED;
|
| + break;
|
| + }
|
| +
|
| + result = socket_.SendTo(
|
| + io_buffer.get(),
|
| + byte_count,
|
| + ip_end_point,
|
| + base::Bind(&UDPSocket::OnSendToComplete, base::Unretained(this)));
|
| + } while (false);
|
| +
|
| + if (result != net::ERR_IO_PENDING)
|
| + OnSendToComplete(result);
|
| +}
|
|
|
| - if (!socket_.is_connected())
|
| - return net::ERR_SOCKET_NOT_CONNECTED;
|
| +void UDPSocket::OnReadComplete(scoped_refptr<net::IOBuffer> io_buffer,
|
| + int result) {
|
| + DCHECK(!read_callback_.is_null());
|
| + read_callback_.Run(result, io_buffer);
|
| + read_callback_.Reset();
|
| +}
|
| +
|
| +void UDPSocket::OnWriteComplete(int result) {
|
| + DCHECK(!write_callback_.is_null());
|
| + write_callback_.Run(result);
|
| + write_callback_.Reset();
|
| +}
|
| +
|
| +void UDPSocket::OnRecvFromComplete(scoped_refptr<net::IOBuffer> io_buffer,
|
| + scoped_refptr<IPEndPoint> address,
|
| + int result) {
|
| + DCHECK(!recv_from_callback_.is_null());
|
| + std::string ip;
|
| + int port = 0;
|
| + if (result > 0 && address.get()) {
|
| + IPEndPointToStringAndPort(address->data, &ip, &port);
|
| + }
|
| + recv_from_callback_.Run(result, io_buffer, ip, port);
|
| + recv_from_callback_.Reset();
|
| +}
|
|
|
| - return socket_.SendTo(
|
| - io_buffer.get(),
|
| - byte_count,
|
| - ip_end_point,
|
| - base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
|
| +void UDPSocket::OnSendToComplete(int result) {
|
| + DCHECK(!send_to_callback_.is_null());
|
| + send_to_callback_.Run(result);
|
| + send_to_callback_.Reset();
|
| }
|
|
|
| } // namespace extensions
|
|
|