// Copyright 2014 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 "mojo/services/network/udp_socket_impl.h"

#include <string.h>

#include <algorithm>
#include <limits>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "mojo/services/network/net_adapters.h"
#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 {

namespace {

const int kMaxReadSize = 128 * 1024;
const size_t kMaxWriteSize = 128 * 1024;
const size_t kMaxPendingSendRequestsUpperbound = 128;
const size_t kDefaultMaxPendingSendRequests = 32;

}  // namespace

UDPSocketImpl::PendingSendRequest::PendingSendRequest() {}

UDPSocketImpl::PendingSendRequest::~PendingSendRequest() {}

UDPSocketImpl::UDPSocketImpl()
    : 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) {
}

UDPSocketImpl::~UDPSocketImpl() {
  STLDeleteElements(&pending_send_requests_);
}

void UDPSocketImpl::AllowAddressReuse(
    const Callback<void(NetworkErrorPtr)>& callback) {
  if (IsBoundOrConnected()) {
    callback.Run(MakeNetworkError(net::ERR_FAILED));
    return;
  }

  allow_address_reuse_ = true;
  callback.Run(MakeNetworkError(net::OK));
}

void UDPSocketImpl::Bind(
    NetAddressPtr addr,
    const Callback<void(NetworkErrorPtr, NetAddressPtr)>& callback) {
  int net_result = net::OK;
  bool opened = false;

  do {
    if (IsBoundOrConnected()) {
      net_result = net::ERR_FAILED;
      break;
    }

    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_result = socket_.Open(ip_end_point.GetFamily());
    if (net_result != net::OK)
      break;
    opened = true;

    if (allow_address_reuse_) {
      net_result = socket_.AllowAddressReuse();
      if (net_result != net::OK)
        break;
    }

    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) {
  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 (!IsBoundOrConnected()) {
    callback.Run(MakeNetworkError(net::ERR_FAILED));
    return;
  }

  if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
    size = std::numeric_limits<int32_t>::max();

  int net_result = socket_.SetSendBufferSize(static_cast<int32_t>(size));
  callback.Run(MakeNetworkError(net_result));
}

void UDPSocketImpl::SetReceiveBufferSize(
    uint32_t size,
    const Callback<void(NetworkErrorPtr)>& callback) {
  if (!IsBoundOrConnected()) {
    callback.Run(MakeNetworkError(net::ERR_FAILED));
    return;
  }

  if (size > static_cast<uint32_t>(std::numeric_limits<int32_t>::max()))
    size = std::numeric_limits<int32_t>::max();

  int net_result = socket_.SetReceiveBufferSize(static_cast<int32_t>(size));
  callback.Run(MakeNetworkError(net_result));
}

void UDPSocketImpl::NegotiateMaxPendingSendRequests(
    uint32_t requested_size,
    const Callback<void(uint32_t)>& callback) {
  if (requested_size != 0) {
    max_pending_send_requests_ =
      std::min(kMaxPendingSendRequestsUpperbound,
               static_cast<size_t>(requested_size));
  }
  callback.Run(static_cast<uint32_t>(max_pending_send_requests_));

  if (pending_send_requests_.size() > max_pending_send_requests_) {
    std::deque<PendingSendRequest*> discarded_requests(
        pending_send_requests_.begin() + max_pending_send_requests_,
        pending_send_requests_.end());
    pending_send_requests_.resize(max_pending_send_requests_);
    for (auto& discarded_request : discarded_requests) {
      discarded_request->callback.Run(
          MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES));
      delete discarded_request;
    }
  }
}

void UDPSocketImpl::ReceiveMore(uint32_t datagram_number) {
  if (datagram_number == 0)
    return;
  if (std::numeric_limits<size_t>::max() - remaining_recv_slots_ <
          datagram_number) {
    return;
  }

  remaining_recv_slots_ += datagram_number;

  if (IsBoundOrConnected() && !recvfrom_buffer_.get()) {
    DCHECK_EQ(datagram_number, remaining_recv_slots_);
    DoRecvFrom();
  }
}

void UDPSocketImpl::SendTo(NetAddressPtr dest_addr,
                           Array<uint8_t> data,
                           const Callback<void(NetworkErrorPtr)>& callback) {
  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_) {
      callback.Run(MakeNetworkError(net::ERR_INSUFFICIENT_RESOURCES));
      return;
    }

    PendingSendRequest* request = new PendingSendRequest;
    request->addr = dest_addr.Pass();
    request->data = data.Pass();
    request->callback = callback;
    pending_send_requests_.push_back(request);
    return;
  }

  DCHECK_EQ(0u, pending_send_requests_.size());

  DoSendTo(dest_addr.Pass(), data.Pass(), callback);
}

void UDPSocketImpl::DoRecvFrom() {
  DCHECK(IsBoundOrConnected());
  DCHECK(!recvfrom_buffer_.get());
  DCHECK_GT(remaining_recv_slots_, 0u);

  recvfrom_buffer_ = new net::IOBuffer(kMaxReadSize);

  // 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_.RecvFrom(
      recvfrom_buffer_.get(),
      kMaxReadSize,
      state_ == BOUND ? &recvfrom_address_ : nullptr,
      base::Bind(&UDPSocketImpl::OnRecvFromCompleted, base::Unretained(this)));
  if (net_result != net::ERR_IO_PENDING)
    OnRecvFromCompleted(net_result);
}

void UDPSocketImpl::DoSendTo(NetAddressPtr addr,
                             Array<uint8_t> data,
                             const Callback<void(NetworkErrorPtr)>& callback) {
  DCHECK(IsBoundOrConnected());
  DCHECK(!sendto_buffer_.get());

  if (data.size() > kMaxWriteSize) {
    callback.Run(MakeNetworkError(net::ERR_INVALID_ARGUMENT));
    return;
  }
  sendto_buffer_ = new net::IOBufferWithSize(static_cast<int>(data.size()));
  if (data.size() > 0)
    memcpy(sendto_buffer_->data(), &data.storage()[0], data.size());

  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);
}

void UDPSocketImpl::OnRecvFromCompleted(int net_result) {
  DCHECK(recvfrom_buffer_.get());

  NetAddressPtr net_address;
  Array<uint8_t> array;
  if (net_result >= 0) {
    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);

    array.Swap(&data);
  }
  recvfrom_buffer_ = nullptr;

  client()->OnReceived(MakeNetworkError(net_result), net_address.Pass(),
                       array.Pass());

  DCHECK_GT(remaining_recv_slots_, 0u);
  remaining_recv_slots_--;
  if (remaining_recv_slots_ > 0)
    DoRecvFrom();
}

void UDPSocketImpl::OnSendToCompleted(
    const Callback<void(NetworkErrorPtr)>& callback,
    int net_result) {
  DCHECK(sendto_buffer_.get());

  sendto_buffer_ = nullptr;

  callback.Run(MakeNetworkError(net_result));

  if (pending_send_requests_.empty())
    return;

  scoped_ptr<PendingSendRequest> request(pending_send_requests_.front());
  pending_send_requests_.pop_front();

  DoSendTo(request->addr.Pass(), request->data.Pass(), request->callback);
}

}  // namespace mojo
