// Copyright (c) 2012 The Chromium OS 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 "shill/async_connection.h"

#include <base/bind.h>
#include <errno.h>
#include <netinet/in.h>

#include <string>

#include "shill/event_dispatcher.h"
#include "shill/net/ip_address.h"
#include "shill/net/sockets.h"

using base::Bind;
using base::Callback;
using base::Unretained;
using std::string;

namespace shill {

AsyncConnection::AsyncConnection(const string &interface_name,
                                 EventDispatcher *dispatcher,
                                 Sockets *sockets,
                                 const Callback<void(bool, int)> &callback)
    : interface_name_(interface_name),
      dispatcher_(dispatcher),
      sockets_(sockets),
      callback_(callback),
      fd_(-1),
      connect_completion_callback_(
          Bind(&AsyncConnection::OnConnectCompletion, Unretained(this))) { }

AsyncConnection::~AsyncConnection() {
  Stop();
}

bool AsyncConnection::Start(const IPAddress &address, int port) {
  DCHECK_LT(fd_, 0);

  int family = PF_INET;
  if (address.family() == IPAddress::kFamilyIPv6) {
    family = PF_INET6;
  }
  fd_ = sockets_->Socket(family, SOCK_STREAM, 0);
  if (fd_ < 0 ||
      sockets_->SetNonBlocking(fd_) < 0) {
    error_ = sockets_->ErrorString();
    PLOG(ERROR) << "Async socket setup failed";
    Stop();
    return false;
  }

  if (!interface_name_.empty() &&
      sockets_->BindToDevice(fd_, interface_name_) < 0) {
    error_ = sockets_->ErrorString();
    PLOG(ERROR) << "Async socket failed to bind to device";
    Stop();
    return false;
  }

  int ret = ConnectTo(address, port);
  if (ret == 0) {
    callback_.Run(true, fd_);  // Passes ownership
    fd_ = -1;
    return true;
  }

  if (sockets_->Error() != EINPROGRESS) {
    error_ = sockets_->ErrorString();
    PLOG(ERROR) << "Async socket connection failed";
    Stop();
    return false;
  }

  connect_completion_handler_.reset(
      dispatcher_->CreateReadyHandler(fd_,
                                      IOHandler::kModeOutput,
                                      connect_completion_callback_));
  error_ = string();

  return true;
}

void AsyncConnection::Stop() {
  connect_completion_handler_.reset();
  if (fd_ >= 0) {
    sockets_->Close(fd_);
    fd_ = -1;
  }
}

void AsyncConnection::OnConnectCompletion(int fd) {
  CHECK_EQ(fd_, fd);
  bool success = false;
  int returned_fd = -1;

  if (sockets_->GetSocketError(fd_) != 0) {
    error_ = sockets_->ErrorString();
    PLOG(ERROR) << "Async GetSocketError returns failure";
  } else {
    returned_fd = fd_;
    fd_ = -1;
    success = true;
  }
  Stop();

  // Run the callback last, since it may end up freeing this instance.
  callback_.Run(success, returned_fd);  // Passes ownership
}

int AsyncConnection::ConnectTo(const IPAddress &address, int port) {
  struct sockaddr *sock_addr = nullptr;
  socklen_t addr_len = 0;
  struct sockaddr_in iaddr;
  struct sockaddr_in6 iaddr6;
  if (address.family() == IPAddress::kFamilyIPv4) {
    CHECK_EQ(sizeof(iaddr.sin_addr.s_addr), address.GetLength());

    memset(&iaddr, 0, sizeof(iaddr));
    iaddr.sin_family = AF_INET;
    memcpy(&iaddr.sin_addr.s_addr, address.address().GetConstData(),
           sizeof(iaddr.sin_addr.s_addr));
    iaddr.sin_port = htons(port);

    sock_addr = reinterpret_cast<struct sockaddr *>(&iaddr);
    addr_len = sizeof(iaddr);
  } else if (address.family() == IPAddress::kFamilyIPv6) {
    CHECK_EQ(sizeof(iaddr6.sin6_addr.s6_addr), address.GetLength());

    memset(&iaddr6, 0, sizeof(iaddr6));
    iaddr6.sin6_family = AF_INET6;
    memcpy(&iaddr6.sin6_addr.s6_addr, address.address().GetConstData(),
           sizeof(iaddr6.sin6_addr.s6_addr));
    iaddr6.sin6_port = htons(port);

    sock_addr = reinterpret_cast<struct sockaddr *>(&iaddr6);
    addr_len = sizeof(iaddr6);
  } else {
    NOTREACHED();
  }

  return sockets_->Connect(fd_, sock_addr, addr_len);
}

}  // namespace shill
