Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(197)

Unified Diff: mojo/services/network/udp_socket_impl.cc

Issue 863023004: Mojo UDP socket: support connected mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/services/network/udp_socket_impl.cc
diff --git a/mojo/services/network/udp_socket_impl.cc b/mojo/services/network/udp_socket_impl.cc
index b4438bec1f07d25b2a45cafd5c8fd2d3b91180e2..524136a32744b49fd542a1c1a468485cc605f2bf 100644
--- a/mojo/services/network/udp_socket_impl.cc
+++ b/mojo/services/network/udp_socket_impl.cc
@@ -16,6 +16,8 @@
#include "mojo/services/network/net_address_type_converters.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/rand_callback.h"
+#include "net/udp/datagram_socket.h"
namespace mojo {
@@ -33,8 +35,10 @@ UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}
UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}
UDPSocketImpl::UDPSocketImpl()
- : socket_(nullptr, net::NetLog::Source()),
- bound_(false),
+ : socket_(net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(),
+ nullptr, net::NetLog::Source()),
+ state_(NOT_BOUND_OR_CONNECTED),
+ allow_address_reuse_(false),
remaining_recv_slots_(0),
max_pending_send_requests_(kDefaultMaxPendingSendRequests) {
}
@@ -45,60 +49,123 @@ UDPSocketImpl::~UDPSocketImpl() {
void UDPSocketImpl::AllowAddressReuse(
const Callback<void(NetworkErrorPtr)>& callback) {
- if (bound_) {
+ if (IsBoundOrConnected()) {
callback.Run(MakeNetworkError(net::ERR_FAILED));
return;
}
- socket_.AllowAddressReuse();
+ allow_address_reuse_ = true;
callback.Run(MakeNetworkError(net::OK));
}
void UDPSocketImpl::Bind(
NetAddressPtr addr,
const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
- if (bound_) {
- callback.Run(MakeNetworkError(net::ERR_FAILED), NetAddressPtr());
- return;
- }
+ int net_result = net::OK;
+ bool opened = false;
- net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
- if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
- callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID), NetAddressPtr());
- return;
- }
+ do {
+ if (IsBoundOrConnected()) {
+ net_result = net::ERR_FAILED;
+ break;
+ }
- int net_result = socket_.Listen(ip_end_point);
- if (net_result != net::OK) {
- callback.Run(MakeNetworkError(net_result), NetAddressPtr());
- return;
- }
+ net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
+ if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
+ net_result = net::ERR_ADDRESS_INVALID;
+ break;
+ }
- net::IPEndPoint bound_ip_end_point;
- NetAddressPtr bound_addr;
- net_result = socket_.GetLocalAddress(&bound_ip_end_point);
- if (net_result == net::OK)
- bound_addr = NetAddress::From(bound_ip_end_point);
+ net_result = socket_.Open(ip_end_point.GetFamily());
+ if (net_result != net::OK)
+ break;
+ opened = true;
- bound_ = true;
- callback.Run(MakeNetworkError(net::OK), bound_addr.Pass());
+ if (allow_address_reuse_) {
+ net_result = socket_.AllowAddressReuse();
+ if (net_result != net::OK)
+ break;
+ }
- if (remaining_recv_slots_ > 0) {
- DCHECK(!recvfrom_buffer_.get());
- DoRecvFrom();
- }
+ net_result = socket_.Bind(ip_end_point);
+ if (net_result != net::OK)
+ break;
+
+ net::IPEndPoint bound_ip_end_point;
+ net_result = socket_.GetLocalAddress(&bound_ip_end_point);
+ if (net_result != net::OK)
+ break;
+
+ state_ = BOUND;
+ callback.Run(MakeNetworkError(net_result),
+ NetAddress::From(bound_ip_end_point));
+
+ if (remaining_recv_slots_ > 0) {
+ DCHECK(!recvfrom_buffer_.get());
+ DoRecvFrom();
+ }
+ return;
+ } while (false);
+
+ DCHECK(net_result != net::OK);
+ if (opened)
+ socket_.Close();
+ callback.Run(MakeNetworkError(net_result), nullptr);
}
void UDPSocketImpl::Connect(
NetAddressPtr remote_addr,
const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
- // TODO(yzshen): Implement it.
+ int net_result = net::OK;
+ bool opened = false;
+
+ do {
+ if (IsBoundOrConnected()) {
+ net_result = net::ERR_FAILED;
+ break;
+ }
+
+ net::IPEndPoint ip_end_point = remote_addr.To<net::IPEndPoint>();
+ if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
+ net_result = net::ERR_ADDRESS_INVALID;
+ break;
+ }
+
+ net_result = socket_.Open(ip_end_point.GetFamily());
+ if (net_result != net::OK)
+ break;
+ opened = true;
+
+ net_result = socket_.Connect(ip_end_point);
+ if (net_result != net::OK)
+ break;
+
+ net::IPEndPoint local_ip_end_point;
+ net_result = socket_.GetLocalAddress(&local_ip_end_point);
+ if (net_result != net::OK)
+ break;
+
+ state_ = CONNECTED;
+ callback.Run(MakeNetworkError(net_result),
+ NetAddress::From(local_ip_end_point));
+
+ if (remaining_recv_slots_ > 0) {
+ DCHECK(!recvfrom_buffer_.get());
+ DoRecvFrom();
+ }
+ return;
+ } while (false);
+
+ DCHECK(net_result != net::OK);
+ if (opened)
+ socket_.Close();
+ callback.Run(MakeNetworkError(net_result), nullptr);
}
void UDPSocketImpl::SetSendBufferSize(
uint32_t size,
const Callback<void(NetworkErrorPtr)>& callback) {
- if (!bound_) {
+ if (!IsBoundOrConnected()) {
callback.Run(MakeNetworkError(net::ERR_FAILED));
return;
}
@@ -113,7 +180,7 @@ void UDPSocketImpl::SetSendBufferSize(
void UDPSocketImpl::SetReceiveBufferSize(
uint32_t size,
const Callback<void(NetworkErrorPtr)>& callback) {
- if (!bound_) {
+ if (!IsBoundOrConnected()) {
callback.Run(MakeNetworkError(net::ERR_FAILED));
return;
}
@@ -158,7 +225,7 @@ void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) {
remaining_recv_slots_ += datagram_number;
- if (bound_ && !recvfrom_buffer_.get()) {
+ if (IsBoundOrConnected() && !recvfrom_buffer_.get()) {
DCHECK_EQ(datagram_number, remaining_recv_slots_);
DoRecvFrom();
}
@@ -167,10 +234,14 @@ void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) {
void UDPSocketImpl::SendTo(NetAddressPtr dest_addr,
Array<uint8_t> data,
const Callback<void(NetworkErrorPtr)>& callback) {
- if (!bound_) {
+ if (!IsBoundOrConnected()) {
callback.Run(MakeNetworkError(net::ERR_FAILED));
return;
}
+ if (state_ == BOUND && !dest_addr) {
+ callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
+ return;
+ }
if (sendto_buffer_.get()) {
if (pending_send_requests_.size() >= max_pending_send_requests_) {
@@ -192,7 +263,7 @@ void UDPSocketImpl::SendTo(NetAddressPtr dest_addr,
}
void UDPSocketImpl::DoRecvFrom() {
- DCHECK(bound_);
+ DCHECK(IsBoundOrConnected());
DCHECK(!recvfrom_buffer_.get());
DCHECK_GT(remaining_recv_slots_, 0u);
@@ -204,7 +275,7 @@ void UDPSocketImpl::DoRecvFrom() {
int net_result = socket_.RecvFrom(
recvfrom_buffer_.get(),
kMaxReadSize,
- &recvfrom_address_,
+ state_ == BOUND ? &recvfrom_address_ : nullptr,
base::Bind(&UDPSocketImpl::OnRecvFromCompleted, base::Unretained(this)));
if (net_result != net::ERR_IO_PENDING)
OnRecvFromCompleted(net_result);
@@ -213,15 +284,9 @@ void UDPSocketImpl::DoRecvFrom() {
void UDPSocketImpl::DoSendTo(NetAddressPtr addr,
Array<uint8_t> data,
const Callback<void(NetworkErrorPtr)>& callback) {
- DCHECK(bound_);
+ DCHECK(IsBoundOrConnected());
DCHECK(!sendto_buffer_.get());
- net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
- if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
- callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID));
- return;
- }
-
if (data.size() > kMaxWriteSize) {
callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
return;
@@ -230,13 +295,27 @@ void UDPSocketImpl::DoSendTo(NetAddressPtr addr,
if (data.size() > 0)
memcpy(sendto_buffer_->data(), &data.storage()[0], data.size());
- // It is safe to use base::Unretained(this) because |socket_| is owned by this
- // object. If this object gets destroyed (and so does |socket_|), the callback
- // won't be called.
- int net_result = socket_.SendTo(sendto_buffer_.get(), sendto_buffer_->size(),
- ip_end_point,
- base::Bind(&UDPSocketImpl::OnSendToCompleted,
- base::Unretained(this), callback));
+ int net_result = net::OK;
+ if (addr) {
+ net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
+ if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
+ callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID));
+ return;
+ }
+
+ // It is safe to use base::Unretained(this) because |socket_| is owned by
+ // this object. If this object gets destroyed (and so does |socket_|), the
+ // callback won't be called.
+ net_result = socket_.SendTo(sendto_buffer_.get(), sendto_buffer_->size(),
+ ip_end_point,
+ base::Bind(&UDPSocketImpl::OnSendToCompleted,
+ base::Unretained(this), callback));
+ } else {
+ DCHECK(state_ == CONNECTED);
+ net_result = socket_.Write(sendto_buffer_.get(), sendto_buffer_->size(),
+ base::Bind(&UDPSocketImpl::OnSendToCompleted,
+ base::Unretained(this), callback));
+ }
if (net_result != net::ERR_IO_PENDING)
OnSendToCompleted(callback, net_result);
}
@@ -247,7 +326,9 @@ void UDPSocketImpl::OnRecvFromCompleted(int net_result) {
NetAddressPtr net_address;
Array<uint8_t> array;
if (net_result >= 0) {
- net_address = NetAddress::From(recvfrom_address_);
+ if (state_ == BOUND)
+ net_address = NetAddress::From(recvfrom_address_);
+
std::vector<uint8_t> data(net_result);
if (net_result > 0)
memcpy(&data[0], recvfrom_buffer_->data(), net_result);

Powered by Google App Engine
This is Rietveld 408576698