net_udp_socket.cc 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Copyright 2020 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 "components/openscreen_platform/net_udp_socket.h"
  5. #include <algorithm>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "components/openscreen_platform/network_util.h"
  9. #include "net/base/net_errors.h"
  10. namespace openscreen {
  11. // static
  12. ErrorOr<std::unique_ptr<UdpSocket>> UdpSocket::Create(
  13. TaskRunner* task_runner,
  14. Client* client,
  15. const IPEndpoint& local_endpoint) {
  16. return ErrorOr<std::unique_ptr<UdpSocket>>(
  17. std::make_unique<openscreen_platform::NetUdpSocket>(client,
  18. local_endpoint));
  19. }
  20. } // namespace openscreen
  21. namespace openscreen_platform {
  22. NetUdpSocket::NetUdpSocket(openscreen::UdpSocket::Client* client,
  23. const openscreen::IPEndpoint& local_endpoint)
  24. : client_(client),
  25. local_endpoint_(local_endpoint),
  26. udp_socket_(net::DatagramSocket::DEFAULT_BIND,
  27. nullptr /* net_log */,
  28. net::NetLogSource()),
  29. read_buffer_(base::MakeRefCounted<net::IOBuffer>(
  30. openscreen::UdpPacket::kUdpMaxPacketSize)) {
  31. DVLOG(1) << __func__;
  32. DCHECK(client_);
  33. }
  34. NetUdpSocket::~NetUdpSocket() = default;
  35. void NetUdpSocket::SendErrorToClient(openscreen::Error::Code openscreen_error,
  36. int net_error) {
  37. DVLOG(1) << __func__;
  38. client_->OnError(
  39. this, openscreen::Error(openscreen_error, net::ErrorToString(net_error)));
  40. }
  41. void NetUdpSocket::DoRead() {
  42. DVLOG(3) << __func__;
  43. while (HandleRecvFromResult(udp_socket_.RecvFrom(
  44. read_buffer_.get(), openscreen::UdpPacket::kUdpMaxPacketSize,
  45. &from_address_,
  46. base::BindOnce(&NetUdpSocket::OnRecvFromCompleted,
  47. base::Unretained(this))))) {
  48. }
  49. }
  50. bool NetUdpSocket::HandleRecvFromResult(int result) {
  51. DVLOG(3) << __func__;
  52. if (result == net::ERR_IO_PENDING) {
  53. return false;
  54. }
  55. if (result < 0) {
  56. client_->OnRead(
  57. this, openscreen::Error(openscreen::Error::Code::kSocketReadFailure,
  58. net::ErrorToString(result)));
  59. return false;
  60. }
  61. DCHECK_GT(result, 0);
  62. openscreen::UdpPacket packet(read_buffer_->data(),
  63. read_buffer_->data() + result);
  64. packet.set_socket(this);
  65. packet.set_source(openscreen_platform::ToOpenScreenEndPoint(from_address_));
  66. client_->OnRead(this, std::move(packet));
  67. return true;
  68. }
  69. void NetUdpSocket::OnRecvFromCompleted(int result) {
  70. DVLOG(3) << __func__;
  71. if (HandleRecvFromResult(result)) {
  72. DoRead();
  73. }
  74. }
  75. void NetUdpSocket::OnSendToCompleted(int result) {
  76. DVLOG(3) << __func__;
  77. send_pending_ = false;
  78. if (result < 0) {
  79. client_->OnSendError(
  80. this, openscreen::Error(openscreen::Error::Code::kSocketSendFailure,
  81. net::ErrorToString(result)));
  82. }
  83. }
  84. bool NetUdpSocket::IsIPv4() const {
  85. DVLOG(2) << __func__;
  86. return local_endpoint_.address.IsV4();
  87. }
  88. bool NetUdpSocket::IsIPv6() const {
  89. DVLOG(2) << __func__;
  90. return local_endpoint_.address.IsV6();
  91. }
  92. openscreen::IPEndpoint NetUdpSocket::GetLocalEndpoint() const {
  93. DVLOG(2) << __func__;
  94. return local_endpoint_;
  95. }
  96. void NetUdpSocket::Bind() {
  97. DVLOG(1) << __func__;
  98. net::IPEndPoint endpoint =
  99. openscreen_platform::ToNetEndPoint(local_endpoint_);
  100. int result = udp_socket_.Open(endpoint.GetFamily());
  101. if (result != net::OK) {
  102. SendErrorToClient(openscreen::Error::Code::kSocketBindFailure, result);
  103. return;
  104. }
  105. result = udp_socket_.Bind(endpoint);
  106. net::IPEndPoint local_endpoint;
  107. if (result == net::OK) {
  108. result = udp_socket_.GetLocalAddress(&local_endpoint);
  109. }
  110. if (result != net::OK) {
  111. SendErrorToClient(openscreen::Error::Code::kSocketBindFailure, result);
  112. return;
  113. }
  114. local_endpoint_ = openscreen_platform::ToOpenScreenEndPoint(local_endpoint);
  115. client_->OnBound(this);
  116. DoRead();
  117. }
  118. void NetUdpSocket::SetMulticastOutboundInterface(
  119. openscreen::NetworkInterfaceIndex ifindex) {
  120. DVLOG(1) << __func__;
  121. const int result = udp_socket_.SetMulticastInterface(ifindex);
  122. if (result != net::OK) {
  123. SendErrorToClient(openscreen::Error::Code::kSocketOptionSettingFailure,
  124. result);
  125. }
  126. }
  127. void NetUdpSocket::JoinMulticastGroup(
  128. const openscreen::IPAddress& address,
  129. openscreen::NetworkInterfaceIndex ifindex) {
  130. DVLOG(1) << __func__;
  131. const int result = udp_socket_.SetMulticastInterface(ifindex);
  132. if (result == net::OK) {
  133. udp_socket_.JoinGroup(openscreen_platform::ToNetAddress(address));
  134. } else {
  135. SendErrorToClient(openscreen::Error::Code::kSocketOptionSettingFailure,
  136. result);
  137. }
  138. }
  139. void NetUdpSocket::SendMessage(const void* data,
  140. size_t length,
  141. const openscreen::IPEndpoint& dest) {
  142. DVLOG(3) << __func__;
  143. if (send_pending_) {
  144. client_->OnSendError(this,
  145. openscreen::Error(openscreen::Error::Code::kAgain));
  146. return;
  147. }
  148. auto buffer = base::MakeRefCounted<net::IOBuffer>(length);
  149. memcpy(buffer->data(), data, length);
  150. const int result = udp_socket_.SendTo(
  151. buffer.get(), length, openscreen_platform::ToNetEndPoint(dest),
  152. base::BindOnce(&NetUdpSocket::OnSendToCompleted, base::Unretained(this)));
  153. send_pending_ = true;
  154. if (result != net::ERR_IO_PENDING) {
  155. OnSendToCompleted(result);
  156. }
  157. }
  158. void NetUdpSocket::SetDscp(openscreen::UdpSocket::DscpMode state) {
  159. NOTIMPLEMENTED_LOG_ONCE();
  160. }
  161. } // namespace openscreen_platform