PageRenderTime 65ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 1ms

/mojo/services/network/udp_socket_impl.cc

https://gitlab.com/jonnialva90/iridium-browser
C++ | 378 lines | 301 code | 68 blank | 9 comment | 68 complexity | 0fdc9932e184a87536d758813338905f MD5 | raw file
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "mojo/services/network/udp_socket_impl.h"
  5. #include <string.h>
  6. #include <algorithm>
  7. #include <limits>
  8. #include "base/logging.h"
  9. #include "base/memory/scoped_ptr.h"
  10. #include "base/stl_util.h"
  11. #include "mojo/services/network/net_adapters.h"
  12. #include "mojo/services/network/net_address_type_converters.h"
  13. #include "net/base/io_buffer.h"
  14. #include "net/base/net_errors.h"
  15. #include "net/base/rand_callback.h"
  16. #include "net/udp/datagram_socket.h"
  17. namespace mojo {
  18. namespace {
  19. const int kMaxReadSize = 128 * 1024;
  20. const size_t kMaxWriteSize = 128 * 1024;
  21. const size_t kMaxPendingSendRequestsUpperbound = 128;
  22. const size_t kDefaultMaxPendingSendRequests = 32;
  23. } // namespace
  24. UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}
  25. UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}
  26. UDPSocketImpl::UDPSocketImpl(InterfaceRequest<UDPSocket> request,
  27. scoped_ptr<mojo::AppRefCount> app_refcount)
  28. : binding_(this, request.Pass()),
  29. socket_(net::DatagramSocket::DEFAULT_BIND,
  30. net::RandIntCallback(),
  31. nullptr,
  32. net::NetLog::Source()),
  33. state_(NOT_BOUND_OR_CONNECTED),
  34. allow_address_reuse_(false),
  35. remaining_recv_slots_(0),
  36. max_pending_send_requests_(kDefaultMaxPendingSendRequests),
  37. app_refcount_(app_refcount.Pass()) {
  38. }
  39. UDPSocketImpl::~UDPSocketImpl() {
  40. STLDeleteElements(&pending_send_requests_);
  41. }
  42. void UDPSocketImpl::AllowAddressReuse(
  43. const Callback<void(NetworkErrorPtr)>& callback) {
  44. if (IsBoundOrConnected()) {
  45. callback.Run(MakeNetworkError(net::ERR_FAILED));
  46. return;
  47. }
  48. allow_address_reuse_ = true;
  49. callback.Run(MakeNetworkError(net::OK));
  50. }
  51. void UDPSocketImpl::Bind(
  52. NetAddressPtr addr,
  53. const Callback<void(NetworkErrorPtr,
  54. NetAddressPtr,
  55. InterfaceRequest<UDPSocketReceiver>)>& callback) {
  56. int net_result = net::OK;
  57. bool opened = false;
  58. do {
  59. if (IsBoundOrConnected()) {
  60. net_result = net::ERR_FAILED;
  61. break;
  62. }
  63. net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
  64. if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
  65. net_result = net::ERR_ADDRESS_INVALID;
  66. break;
  67. }
  68. net_result = socket_.Open(ip_end_point.GetFamily());
  69. if (net_result != net::OK)
  70. break;
  71. opened = true;
  72. if (allow_address_reuse_) {
  73. net_result = socket_.AllowAddressReuse();
  74. if (net_result != net::OK)
  75. break;
  76. }
  77. net_result = socket_.Bind(ip_end_point);
  78. if (net_result != net::OK)
  79. break;
  80. net::IPEndPoint bound_ip_end_point;
  81. net_result = socket_.GetLocalAddress(&bound_ip_end_point);
  82. if (net_result != net::OK)
  83. break;
  84. state_ = BOUND;
  85. callback.Run(MakeNetworkError(net_result),
  86. NetAddress::From(bound_ip_end_point), GetProxy(&receiver_));
  87. if (remaining_recv_slots_ > 0) {
  88. DCHECK(!recvfrom_buffer_.get());
  89. DoRecvFrom();
  90. }
  91. return;
  92. } while (false);
  93. DCHECK(net_result != net::OK);
  94. if (opened)
  95. socket_.Close();
  96. callback.Run(MakeNetworkError(net_result), nullptr, nullptr);
  97. }
  98. void UDPSocketImpl::Connect(
  99. NetAddressPtr remote_addr,
  100. const Callback<void(NetworkErrorPtr,
  101. NetAddressPtr,
  102. InterfaceRequest<UDPSocketReceiver>)>& callback) {
  103. int net_result = net::OK;
  104. bool opened = false;
  105. do {
  106. if (IsBoundOrConnected()) {
  107. net_result = net::ERR_FAILED;
  108. break;
  109. }
  110. net::IPEndPoint ip_end_point = remote_addr.To<net::IPEndPoint>();
  111. if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
  112. net_result = net::ERR_ADDRESS_INVALID;
  113. break;
  114. }
  115. net_result = socket_.Open(ip_end_point.GetFamily());
  116. if (net_result != net::OK)
  117. break;
  118. opened = true;
  119. net_result = socket_.Connect(ip_end_point);
  120. if (net_result != net::OK)
  121. break;
  122. net::IPEndPoint local_ip_end_point;
  123. net_result = socket_.GetLocalAddress(&local_ip_end_point);
  124. if (net_result != net::OK)
  125. break;
  126. state_ = CONNECTED;
  127. callback.Run(MakeNetworkError(net_result),
  128. NetAddress::From(local_ip_end_point), GetProxy(&receiver_));
  129. if (remaining_recv_slots_ > 0) {
  130. DCHECK(!recvfrom_buffer_.get());
  131. DoRecvFrom();
  132. }
  133. return;
  134. } while (false);
  135. DCHECK(net_result != net::OK);
  136. if (opened)
  137. socket_.Close();
  138. callback.Run(MakeNetworkError(net_result), nullptr, nullptr);
  139. }
  140. void UDPSocketImpl::SetSendBufferSize(
  141. uint32_t size,
  142. const Callback<void(NetworkErrorPtr)>& callback) {
  143. if (!IsBoundOrConnected()) {
  144. callback.Run(MakeNetworkError(net::ERR_FAILED));
  145. return;
  146. }
  147. if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
  148. size = std::numeric_limits<int32_t>::max();
  149. int net_result = socket_.SetSendBufferSize(static_cast<int32_t>(size));
  150. callback.Run(MakeNetworkError(net_result));
  151. }
  152. void UDPSocketImpl::SetReceiveBufferSize(
  153. uint32_t size,
  154. const Callback<void(NetworkErrorPtr)>& callback) {
  155. if (!IsBoundOrConnected()) {
  156. callback.Run(MakeNetworkError(net::ERR_FAILED));
  157. return;
  158. }
  159. if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
  160. size = std::numeric_limits<int32_t>::max();
  161. int net_result = socket_.SetReceiveBufferSize(static_cast<int32_t>(size));
  162. callback.Run(MakeNetworkError(net_result));
  163. }
  164. void UDPSocketImpl::NegotiateMaxPendingSendRequests(
  165. uint32_t requested_size,
  166. const Callback<void(uint32_t)>& callback) {
  167. if (requested_size != 0) {
  168. max_pending_send_requests_ =
  169. std::min(kMaxPendingSendRequestsUpperbound,
  170. static_cast<size_t>(requested_size));
  171. }
  172. callback.Run(static_cast<uint32_t>(max_pending_send_requests_));
  173. if (pending_send_requests_.size() > max_pending_send_requests_) {
  174. std::deque<PendingSendRequest*> discarded_requests(
  175. pending_send_requests_.begin() + max_pending_send_requests_,
  176. pending_send_requests_.end());
  177. pending_send_requests_.resize(max_pending_send_requests_);
  178. for (auto& discarded_request : discarded_requests) {
  179. discarded_request->callback.Run(
  180. MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES));
  181. delete discarded_request;
  182. }
  183. }
  184. }
  185. void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) {
  186. if (!receiver_)
  187. return;
  188. if (datagram_number == 0)
  189. return;
  190. if (std::numeric_limits<size_t>::max() - remaining_recv_slots_ <
  191. datagram_number) {
  192. return;
  193. }
  194. remaining_recv_slots_ += datagram_number;
  195. if (IsBoundOrConnected() && !recvfrom_buffer_.get()) {
  196. DCHECK_EQ(datagram_number, remaining_recv_slots_);
  197. DoRecvFrom();
  198. }
  199. }
  200. void UDPSocketImpl::SendTo(NetAddressPtr dest_addr,
  201. Array<uint8_t> data,
  202. const Callback<void(NetworkErrorPtr)>& callback) {
  203. if (!IsBoundOrConnected()) {
  204. callback.Run(MakeNetworkError(net::ERR_FAILED));
  205. return;
  206. }
  207. if (state_ == BOUND && !dest_addr) {
  208. callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
  209. return;
  210. }
  211. if (sendto_buffer_.get()) {
  212. if (pending_send_requests_.size() >= max_pending_send_requests_) {
  213. callback.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES));
  214. return;
  215. }
  216. PendingSendRequest* request = new PendingSendRequest;
  217. request->addr = dest_addr.Pass();
  218. request->data = data.Pass();
  219. request->callback = callback;
  220. pending_send_requests_.push_back(request);
  221. return;
  222. }
  223. DCHECK_EQ(0u, pending_send_requests_.size());
  224. DoSendTo(dest_addr.Pass(), data.Pass(), callback);
  225. }
  226. void UDPSocketImpl::DoRecvFrom() {
  227. DCHECK(IsBoundOrConnected());
  228. DCHECK(receiver_);
  229. DCHECK(!recvfrom_buffer_.get());
  230. DCHECK_GT(remaining_recv_slots_, 0u);
  231. recvfrom_buffer_ = new net::IOBuffer(kMaxReadSize);
  232. // It is safe to use base::Unretained(this) because |socket_| is owned by this
  233. // object. If this object gets destroyed (and so does |socket_|), the callback
  234. // won't be called.
  235. int net_result = socket_.RecvFrom(
  236. recvfrom_buffer_.get(),
  237. kMaxReadSize,
  238. state_ == BOUND ? &recvfrom_address_ : nullptr,
  239. base::Bind(&UDPSocketImpl::OnRecvFromCompleted, base::Unretained(this)));
  240. if (net_result != net::ERR_IO_PENDING)
  241. OnRecvFromCompleted(net_result);
  242. }
  243. void UDPSocketImpl::DoSendTo(NetAddressPtr addr,
  244. Array<uint8_t> data,
  245. const Callback<void(NetworkErrorPtr)>& callback) {
  246. DCHECK(IsBoundOrConnected());
  247. DCHECK(!sendto_buffer_.get());
  248. if (data.size() > kMaxWriteSize) {
  249. callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
  250. return;
  251. }
  252. sendto_buffer_ = new net::IOBufferWithSize(static_cast<int>(data.size()));
  253. if (data.size() > 0)
  254. memcpy(sendto_buffer_->data(), &data.storage()[0], data.size());
  255. int net_result = net::OK;
  256. if (addr) {
  257. net::IPEndPoint ip_end_point = addr.To<net::IPEndPoint>();
  258. if (ip_end_point.GetFamily() == net::ADDRESS_FAMILY_UNSPECIFIED) {
  259. callback.Run(MakeNetworkError(net::ERR_ADDRESS_INVALID));
  260. return;
  261. }
  262. // It is safe to use base::Unretained(this) because |socket_| is owned by
  263. // this object. If this object gets destroyed (and so does |socket_|), the
  264. // callback won't be called.
  265. net_result = socket_.SendTo(sendto_buffer_.get(), sendto_buffer_->size(),
  266. ip_end_point,
  267. base::Bind(&UDPSocketImpl::OnSendToCompleted,
  268. base::Unretained(this), callback));
  269. } else {
  270. DCHECK(state_ == CONNECTED);
  271. net_result = socket_.Write(sendto_buffer_.get(), sendto_buffer_->size(),
  272. base::Bind(&UDPSocketImpl::OnSendToCompleted,
  273. base::Unretained(this), callback));
  274. }
  275. if (net_result != net::ERR_IO_PENDING)
  276. OnSendToCompleted(callback, net_result);
  277. }
  278. void UDPSocketImpl::OnRecvFromCompleted(int net_result) {
  279. DCHECK(recvfrom_buffer_.get());
  280. NetAddressPtr net_address;
  281. Array<uint8_t> array;
  282. if (net_result >= 0) {
  283. if (state_ == BOUND)
  284. net_address = NetAddress::From(recvfrom_address_);
  285. std::vector<uint8_t> data(net_result);
  286. if (net_result > 0)
  287. memcpy(&data[0], recvfrom_buffer_->data(), net_result);
  288. array.Swap(&data);
  289. }
  290. recvfrom_buffer_ = nullptr;
  291. receiver_->OnReceived(MakeNetworkError(net_result), net_address.Pass(),
  292. array.Pass());
  293. DCHECK_GT(remaining_recv_slots_, 0u);
  294. remaining_recv_slots_--;
  295. if (remaining_recv_slots_ > 0)
  296. DoRecvFrom();
  297. }
  298. void UDPSocketImpl::OnSendToCompleted(
  299. const Callback<void(NetworkErrorPtr)>& callback,
  300. int net_result) {
  301. DCHECK(sendto_buffer_.get());
  302. sendto_buffer_ = nullptr;
  303. callback.Run(MakeNetworkError(net_result));
  304. if (pending_send_requests_.empty())
  305. return;
  306. scoped_ptr<PendingSendRequest> request(pending_send_requests_.front());
  307. pending_send_requests_.pop_front();
  308. DoSendTo(request->addr.Pass(), request->data.Pass(), request->callback);
  309. }
  310. } // namespace mojo