/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/async_udp_socket.h"

#include <cstddef>
#include <memory>
#include <optional>
#include <utility>

#include "absl/base/nullability.h"
#include "api/environment/environment.h"
#include "api/sequence_checker.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/network/received_packet.h"
#include "rtc_base/network/sent_packet.h"
#include "rtc_base/socket.h"
#include "rtc_base/socket_address.h"
#include "rtc_base/socket_factory.h"

namespace webrtc {

absl_nullable std::unique_ptr<AsyncUDPSocket> AsyncUDPSocket::Create(
    const Environment& env,
    const SocketAddress& bind_address,
    SocketFactory& factory) {
  std::unique_ptr<Socket> socket =
      factory.Create(bind_address.family(), SOCK_DGRAM);
  if (socket == nullptr) {
    return nullptr;
  }
  if (socket->Bind(bind_address) < 0) {
    RTC_LOG(LS_ERROR) << "Bind() failed with error " << socket->GetError();
    return nullptr;
  }
  return std::make_unique<AsyncUDPSocket>(env, std::move(socket));
}

AsyncUDPSocket::AsyncUDPSocket(const Environment& env,
                               absl_nonnull std::unique_ptr<Socket> socket)
    : env_(env),
      sequence_checker_(SequenceChecker::kDetached),
      socket_(std::move(socket)) {
  // The socket should start out readable but not writable.
  socket_->SubscribeReadEvent(this,
                              [this](Socket* socket) { OnReadEvent(socket); });
  socket_->SubscribeWriteEvent(
      this, [this](Socket* socket) { OnWriteEvent(socket); });
  // need to forward that also for UDP case (DTLS) once the SSL handshake is
  // finished

  socket_->SubscribeConnectEvent(
      this, [this](Socket* socket) { OnConnectEvent(socket); });
}

SocketAddress AsyncUDPSocket::GetLocalAddress() const {
  return socket_->GetLocalAddress();
}

SocketAddress AsyncUDPSocket::GetRemoteAddress() const {
  return socket_->GetRemoteAddress();
}

int AsyncUDPSocket::Send(const void* pv,
                         size_t cb,
                         const AsyncSocketPacketOptions& options) {
  SentPacketInfo sent_packet(options.packet_id,
                             env_.clock().TimeInMilliseconds(),
                             options.info_signaled_after_sent);
  CopySocketInformationToPacketInfo(cb, *this, &sent_packet.info);
  int ret = socket_->Send(pv, cb);
  NotifySentPacket(this, sent_packet);
  return ret;
}

int AsyncUDPSocket::SendTo(const void* pv,
                           size_t cb,
                           const SocketAddress& addr,
                           const AsyncSocketPacketOptions& options) {
  SentPacketInfo sent_packet(options.packet_id,
                             env_.clock().TimeInMilliseconds(),
                             options.info_signaled_after_sent);
  CopySocketInformationToPacketInfo(cb, *this, &sent_packet.info);
  if (has_set_ect1_options_ != options.ect_1) {
    // It is unclear what is most efficient, setting options on every sent
    // packet or when changed. Potentially, can separate send sockets be used?
    // This is the easier implementation.
    if (socket_->SetOption(Socket::Option::OPT_SEND_ECN,
                           options.ect_1 ? 1 : 0) == 0) {
      has_set_ect1_options_ = options.ect_1;
    }
  }
  int ret = socket_->SendTo(pv, cb, addr);
  NotifySentPacket(this, sent_packet);
  return ret;
}

int AsyncUDPSocket::Close() {
  return socket_->Close();
}

AsyncUDPSocket::State AsyncUDPSocket::GetState() const {
  return STATE_BOUND;
}

int AsyncUDPSocket::GetOption(Socket::Option opt, int* value) {
  return socket_->GetOption(opt, value);
}

int AsyncUDPSocket::SetOption(Socket::Option opt, int value) {
  return socket_->SetOption(opt, value);
}

int AsyncUDPSocket::GetError() const {
  return socket_->GetError();
}

void AsyncUDPSocket::SetError(int error) {
  return socket_->SetError(error);
}

void AsyncUDPSocket::OnConnectEvent(Socket* socket) {
  NotifyConnect(this);
}

void AsyncUDPSocket::OnReadEvent(Socket* socket) {
  RTC_DCHECK(socket_.get() == socket);
  RTC_DCHECK_RUN_ON(&sequence_checker_);

  Socket::ReceiveBuffer receive_buffer(buffer_);
  int len = socket_->RecvFrom(receive_buffer);
  if (len < 0) {
    // An error here typically means we got an ICMP error in response to our
    // send datagram, indicating the remote address was unreachable.
    // When doing ICE, this kind of thing will often happen.
    // TODO: Do something better like forwarding the error to the user.
    SocketAddress local_addr = socket_->GetLocalAddress();
    RTC_LOG(LS_INFO) << "AsyncUDPSocket[" << local_addr.ToSensitiveString()
                     << "] receive failed with error " << socket_->GetError();
    return;
  }
  if (len == 0) {
    // Spurios wakeup.
    return;
  }

  if (!receive_buffer.arrival_time) {
    // Timestamp from socket is not available.
    receive_buffer.arrival_time = env_.clock().CurrentTime();
  } else {
    Timestamp current_time = env_.clock().CurrentTime();
    if (!socket_time_offset_ ||
        *receive_buffer.arrival_time + *socket_time_offset_ > current_time) {
      // Estimate timestamp offset from first packet arrival time.
      // This may be wrong if packets have been buffered in the socket before we
      // read the first packet and `socket_time_offset_` may then have to be set
      // again to ensure no arrival times are set in the future.
      socket_time_offset_ = current_time - *receive_buffer.arrival_time;
    }
    *receive_buffer.arrival_time += *socket_time_offset_;
    RTC_DCHECK_LE(*receive_buffer.arrival_time, current_time);
  }
  NotifyPacketReceived(
      ReceivedIpPacket(receive_buffer.payload, receive_buffer.source_address,
                       receive_buffer.arrival_time, receive_buffer.ecn));
}

void AsyncUDPSocket::OnWriteEvent(Socket* socket) {
  NotifyReadyToSend(this);
}

}  // namespace webrtc
