// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/udp_socket.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/numerics/checked_math.h"
#include "base/numerics/ranges.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "net/socket/udp_socket.h"

namespace network {

namespace {

const uint32_t kMaxReadSize = 64 * 1024;
// The limit on data length for a UDP packet is 65,507 for IPv4 and 65,535 for
// IPv6.
const uint32_t kMaxPacketSize = kMaxReadSize - 1;

int ClampUDPBufferSize(int requested_buffer_size) {
  constexpr int kMinBufferSize = 0;
  constexpr int kMaxBufferSize = 128 * 1024;
  return base::ClampToRange(requested_buffer_size, kMinBufferSize,
                            kMaxBufferSize);
}

class SocketWrapperImpl : public UDPSocket::SocketWrapper {
 public:
  SocketWrapperImpl(net::DatagramSocket::BindType bind_type,
                    net::NetLog* net_log,
                    const net::NetLogSource& source)
      : socket_(bind_type, net_log, source) {}
  ~SocketWrapperImpl() override {}

  int Connect(const net::IPEndPoint& remote_addr,
              mojom::UDPSocketOptionsPtr options,
              net::IPEndPoint* local_addr_out) override {
    int result = socket_.Open(remote_addr.GetFamily());
    if (result == net::OK)
      result = ConfigureOptions(std::move(options));
    if (result == net::OK)
      result = socket_.Connect(remote_addr);
    if (result == net::OK)
      result = socket_.GetLocalAddress(local_addr_out);

    if (result != net::OK)
      socket_.Close();
    return result;
  }
  int Bind(const net::IPEndPoint& local_addr,
           mojom::UDPSocketOptionsPtr options,
           net::IPEndPoint* local_addr_out) override {
    int result = socket_.Open(local_addr.GetFamily());
    if (result == net::OK)
      result = ConfigureOptions(std::move(options));
    if (result == net::OK)
      result = socket_.Bind(local_addr);
    if (result == net::OK)
      result = socket_.GetLocalAddress(local_addr_out);

    if (result != net::OK)
      socket_.Close();
    return result;
  }
  int SendTo(
      net::IOBuffer* buf,
      int buf_len,
      const net::IPEndPoint& dest_addr,
      net::CompletionOnceCallback callback,
      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
    return socket_.SendTo(buf, buf_len, dest_addr, std::move(callback));
  }
  int SetBroadcast(bool broadcast) override {
    return socket_.SetBroadcast(broadcast);
  }
  int SetSendBufferSize(int send_buffer_size) override {
    return socket_.SetSendBufferSize(ClampUDPBufferSize(send_buffer_size));
  }
  int SetReceiveBufferSize(int receive_buffer_size) override {
    return socket_.SetReceiveBufferSize(
        ClampUDPBufferSize(receive_buffer_size));
  }
  int JoinGroup(const net::IPAddress& group_address) override {
    return socket_.JoinGroup(group_address);
  }
  int LeaveGroup(const net::IPAddress& group_address) override {
    return socket_.LeaveGroup(group_address);
  }
  int Write(
      net::IOBuffer* buf,
      int buf_len,
      net::CompletionOnceCallback callback,
      const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
    return socket_.Write(buf, buf_len, std::move(callback), traffic_annotation);
  }
  int RecvFrom(net::IOBuffer* buf,
               int buf_len,
               net::IPEndPoint* address,
               net::CompletionOnceCallback callback) override {
    return socket_.RecvFrom(buf, buf_len, address, std::move(callback));
  }

 private:
  int ConfigureOptions(mojom::UDPSocketOptionsPtr options) {
    if (!options)
      return net::OK;
    int result = net::OK;
    if (options->allow_address_reuse)
      result = socket_.AllowAddressReuse();
    if (result == net::OK && options->allow_address_sharing_for_multicast)
      result = socket_.AllowAddressSharingForMulticast();
    if (result == net::OK && options->allow_broadcast)
      result = socket_.SetBroadcast(true);
    if (result == net::OK && options->multicast_interface != 0)
      result = socket_.SetMulticastInterface(options->multicast_interface);
    if (result == net::OK && !options->multicast_loopback_mode) {
      result =
          socket_.SetMulticastLoopbackMode(options->multicast_loopback_mode);
    }
    if (result == net::OK && options->multicast_time_to_live != 1) {
      result = socket_.SetMulticastTimeToLive(
          base::saturated_cast<int32_t>(options->multicast_time_to_live));
    }
    if (result == net::OK && options->receive_buffer_size != 0) {
      result = socket_.SetReceiveBufferSize(
          ClampUDPBufferSize(options->receive_buffer_size));
    }
    if (result == net::OK && options->send_buffer_size != 0) {
      result = socket_.SetSendBufferSize(
          ClampUDPBufferSize(options->send_buffer_size));
    }
    return result;
  }

  net::UDPSocket socket_;

  DISALLOW_COPY_AND_ASSIGN(SocketWrapperImpl);
};

}  // namespace

UDPSocket::PendingSendRequest::PendingSendRequest() {}

UDPSocket::PendingSendRequest::~PendingSendRequest() {}

UDPSocket::UDPSocket(mojom::UDPSocketReceiverPtr receiver, net::NetLog* net_log)
    : net_log_(net_log),
      is_bound_(false),
      is_connected_(false),
      receiver_(std::move(receiver)),
      remaining_recv_slots_(0) {}

UDPSocket::~UDPSocket() {}

void UDPSocket::Connect(const net::IPEndPoint& remote_addr,
                        mojom::UDPSocketOptionsPtr options,
                        ConnectCallback callback) {
  if (IsConnectedOrBound()) {
    std::move(callback).Run(net::ERR_SOCKET_IS_CONNECTED, base::nullopt);
    return;
  }
  DCHECK(!wrapped_socket_);
  wrapped_socket_ = CreateSocketWrapper();
  net::IPEndPoint local_addr_out;
  int result = wrapped_socket_->Connect(remote_addr, std::move(options),
                                        &local_addr_out);
  if (result != net::OK) {
    wrapped_socket_.reset();
    std::move(callback).Run(result, base::nullopt);
    return;
  }
  is_connected_ = true;
  std::move(callback).Run(result, local_addr_out);
}

void UDPSocket::Bind(const net::IPEndPoint& local_addr,
                     mojom::UDPSocketOptionsPtr options,
                     BindCallback callback) {
  if (IsConnectedOrBound()) {
    std::move(callback).Run(net::ERR_SOCKET_IS_CONNECTED, base::nullopt);
    return;
  }
  DCHECK(!wrapped_socket_);
  wrapped_socket_ = CreateSocketWrapper();
  net::IPEndPoint local_addr_out;
  int result =
      wrapped_socket_->Bind(local_addr, std::move(options), &local_addr_out);
  if (result != net::OK) {
    wrapped_socket_.reset();
    std::move(callback).Run(result, base::nullopt);
    return;
  }
  is_bound_ = true;
  std::move(callback).Run(result, local_addr_out);
}

void UDPSocket::SetBroadcast(bool broadcast, SetBroadcastCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  int net_result = wrapped_socket_->SetBroadcast(broadcast);
  std::move(callback).Run(net_result);
}

void UDPSocket::SetSendBufferSize(int32_t send_buffer_size,
                                  SetSendBufferSizeCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  int net_result = wrapped_socket_->SetSendBufferSize(send_buffer_size);
  std::move(callback).Run(net_result);
}

void UDPSocket::SetReceiveBufferSize(int32_t receive_buffer_size,
                                     SetSendBufferSizeCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  int net_result = wrapped_socket_->SetReceiveBufferSize(receive_buffer_size);
  std::move(callback).Run(net_result);
}

void UDPSocket::JoinGroup(const net::IPAddress& group_address,
                          JoinGroupCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  int net_result = wrapped_socket_->JoinGroup(group_address);
  std::move(callback).Run(net_result);
}

void UDPSocket::LeaveGroup(const net::IPAddress& group_address,
                           LeaveGroupCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  int net_result = wrapped_socket_->LeaveGroup(group_address);
  std::move(callback).Run(net_result);
}

void UDPSocket::ReceiveMore(uint32_t num_additional_datagrams) {
  ReceiveMoreWithBufferSize(num_additional_datagrams, kMaxReadSize);
}

void UDPSocket::ReceiveMoreWithBufferSize(uint32_t num_additional_datagrams,
                                          uint32_t buffer_size) {
  if (!receiver_)
    return;
  if (!IsConnectedOrBound()) {
    receiver_->OnReceived(net::ERR_UNEXPECTED, base::nullopt, base::nullopt);
    return;
  }
  if (num_additional_datagrams == 0)
    return;
  // Check for overflow.
  if (!base::CheckAdd(remaining_recv_slots_, num_additional_datagrams)
           .AssignIfValid(&remaining_recv_slots_)) {
    return;
  }
  if (!recvfrom_buffer_) {
    DCHECK_EQ(num_additional_datagrams, remaining_recv_slots_);
    DoRecvFrom(std::min(buffer_size, kMaxReadSize));
  }
}

void UDPSocket::SendTo(
    const net::IPEndPoint& dest_addr,
    base::span<const uint8_t> data,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    SendToCallback callback) {
  if (!is_bound_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  DoSendToOrWrite(
      &dest_addr, data,
      static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
      std::move(callback));
}

void UDPSocket::Send(
    base::span<const uint8_t> data,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    SendCallback callback) {
  if (!is_connected_) {
    std::move(callback).Run(net::ERR_UNEXPECTED);
    return;
  }
  DoSendToOrWrite(
      nullptr, data,
      static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
      std::move(callback));
}

void UDPSocket::Close() {
  if (!IsConnectedOrBound()) {
    return;
  }
  is_connected_ = false;
  is_bound_ = false;
  recvfrom_buffer_ = nullptr;
  send_callback_.Reset();
  send_buffer_ = nullptr;
  remaining_recv_slots_ = 0;
  wrapped_socket_.reset();
}

std::unique_ptr<UDPSocket::SocketWrapper> UDPSocket::CreateSocketWrapper()
    const {
  return std::make_unique<SocketWrapperImpl>(net::DatagramSocket::RANDOM_BIND,
                                             nullptr, net::NetLogSource());
}

bool UDPSocket::IsConnectedOrBound() const {
  return is_connected_ || is_bound_;
}

void UDPSocket::DoRecvFrom(uint32_t buffer_size) {
  DCHECK(receiver_);
  DCHECK(!recvfrom_buffer_);
  DCHECK_GT(remaining_recv_slots_, 0u);
  DCHECK_GE(kMaxReadSize, buffer_size);

  recvfrom_buffer_ =
      base::MakeRefCounted<net::IOBuffer>(static_cast<size_t>(buffer_size));

  // base::Unretained(this) is safe because socket is owned by |this|.
  int net_result = wrapped_socket_->RecvFrom(
      recvfrom_buffer_.get(), buffer_size, &recvfrom_address_,
      base::BindRepeating(&UDPSocket::OnRecvFromCompleted,
                          base::Unretained(this), buffer_size));
  if (net_result != net::ERR_IO_PENDING)
    OnRecvFromCompleted(buffer_size, net_result);
}

void UDPSocket::DoSendToOrWrite(
    const net::IPEndPoint* dest_addr,
    const base::span<const uint8_t>& data,
    const net::NetworkTrafficAnnotationTag& traffic_annotation,
    SendToCallback callback) {
  if (pending_send_requests_.size() >= kMaxPendingSendRequests) {
    std::move(callback).Run(net::ERR_INSUFFICIENT_RESOURCES);
    return;
  }

  if (data.size() > kMaxPacketSize) {
    std::move(callback).Run(net::ERR_MSG_TOO_BIG);
    return;
  }

  // |data| points to a range of bytes in the received message and will be
  // freed when this method returns, so copy out the bytes now.
  auto buffer = base::MakeRefCounted<net::IOBufferWithSize>(data.size());
  memcpy(buffer.get()->data(), data.data(), data.size());

  if (send_buffer_.get()) {
    auto request = std::make_unique<PendingSendRequest>();
    if (dest_addr)
      request->addr = std::make_unique<net::IPEndPoint>(*dest_addr);
    request->data = buffer;
    request->traffic_annotation =
        net::MutableNetworkTrafficAnnotationTag(traffic_annotation);
    request->callback = std::move(callback);
    pending_send_requests_.push_back(std::move(request));
    return;
  }

  DoSendToOrWriteBuffer(dest_addr, buffer, traffic_annotation,
                        std::move(callback));
}

void UDPSocket::DoSendToOrWriteBuffer(
    const net::IPEndPoint* dest_addr,
    scoped_refptr<net::IOBufferWithSize> buffer,
    const net::NetworkTrafficAnnotationTag& traffic_annotation,
    SendToCallback callback) {
  DCHECK(!send_buffer_);
  DCHECK(send_callback_.is_null());

  send_buffer_ = buffer;
  send_callback_ = std::move(callback);
  // base::Unretained(this) is safe because socket is owned by |this|.
  int net_result;
  if (dest_addr) {
    net_result = wrapped_socket_->SendTo(
        buffer.get(), buffer->size(), *dest_addr,
        base::BindRepeating(&UDPSocket::OnSendToCompleted,
                            base::Unretained(this)),
        traffic_annotation);
  } else {
    net_result = wrapped_socket_->Write(
        buffer.get(), buffer->size(),
        base::BindRepeating(&UDPSocket::OnSendToCompleted,
                            base::Unretained(this)),
        traffic_annotation);
  }
  if (net_result != net::ERR_IO_PENDING)
    OnSendToCompleted(net_result);
}

void UDPSocket::OnRecvFromCompleted(uint32_t buffer_size, int net_result) {
  DCHECK(recvfrom_buffer_);

  if (net_result >= 0) {
    receiver_->OnReceived(
        net::OK,
        is_bound_ ? base::make_optional(recvfrom_address_) : base::nullopt,
        base::span<const uint8_t>(
            reinterpret_cast<const uint8_t*>(recvfrom_buffer_->data()),
            static_cast<size_t>(net_result)));
  } else {
    receiver_->OnReceived(net_result, base::nullopt, base::nullopt);
  }
  recvfrom_buffer_ = nullptr;
  DCHECK_GT(remaining_recv_slots_, 0u);
  remaining_recv_slots_--;
  if (remaining_recv_slots_ > 0)
    DoRecvFrom(buffer_size);
}

void UDPSocket::OnSendToCompleted(int net_result) {
  DCHECK(send_buffer_.get());
  DCHECK(!send_callback_.is_null());

  if (net_result > net::OK)
    net_result = net::OK;
  send_buffer_ = nullptr;
  std::move(send_callback_).Run(net_result);

  if (pending_send_requests_.empty())
    return;
  std::unique_ptr<PendingSendRequest> request =
      std::move(pending_send_requests_.front());
  pending_send_requests_.pop_front();
  DoSendToOrWriteBuffer(request->addr.get(), request->data,
                        static_cast<net::NetworkTrafficAnnotationTag>(
                            request->traffic_annotation),
                        std::move(request->callback));
}

}  // namespace network
