/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/port.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/log.h>

#include "src/core/lib/iomgr/error.h"
#include "src/core/lib/iomgr/iomgr_custom.h"
#include "src/core/lib/iomgr/sockaddr_utils.h"
#include "src/core/lib/iomgr/tcp_client.h"
#include "src/core/lib/iomgr/tcp_custom.h"
#include "src/core/lib/iomgr/timer.h"

extern grpc_core::TraceFlag grpc_tcp_trace;
extern grpc_socket_vtable* grpc_custom_socket_vtable;

struct grpc_custom_tcp_connect {
  grpc_custom_socket* socket;
  grpc_timer alarm;
  grpc_closure on_alarm;
  grpc_closure* closure;
  grpc_endpoint** endpoint;
  int refs;
  char* addr_name;
  grpc_resource_quota* resource_quota;
};

static void custom_tcp_connect_cleanup(grpc_custom_tcp_connect* connect) {
  grpc_custom_socket* socket = connect->socket;
  grpc_resource_quota_unref_internal(connect->resource_quota);
  gpr_free(connect->addr_name);
  gpr_free(connect);
  socket->refs--;
  if (socket->refs == 0) {
    grpc_custom_socket_vtable->destroy(socket);
    gpr_free(socket);
  }
}

static void custom_close_callback(grpc_custom_socket* socket) {}

static void on_alarm(void* acp, grpc_error* error) {
  int done;
  grpc_custom_socket* socket = (grpc_custom_socket*)acp;
  grpc_custom_tcp_connect* connect = socket->connector;
  if (grpc_tcp_trace.enabled()) {
    const char* str = grpc_error_string(error);
    gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s",
            connect->addr_name, str);
  }
  if (error == GRPC_ERROR_NONE) {
    /* error == NONE implies that the timer ran out, and wasn't cancelled. If
       it was cancelled, then the handler that cancelled it also should close
       the handle, if applicable */
    grpc_custom_socket_vtable->close(socket, custom_close_callback);
  }
  done = (--connect->refs == 0);
  if (done) {
    custom_tcp_connect_cleanup(connect);
  }
}

static void custom_connect_callback_internal(grpc_custom_socket* socket,
                                             grpc_error* error) {
  grpc_custom_tcp_connect* connect = socket->connector;
  int done;
  grpc_closure* closure = connect->closure;
  grpc_timer_cancel(&connect->alarm);
  if (error == GRPC_ERROR_NONE) {
    *connect->endpoint = custom_tcp_endpoint_create(
        socket, connect->resource_quota, connect->addr_name);
  }
  done = (--connect->refs == 0);
  if (done) {
    grpc_core::ExecCtx::Get()->Flush();
    custom_tcp_connect_cleanup(connect);
  }
  GRPC_CLOSURE_SCHED(closure, error);
}

static void custom_connect_callback(grpc_custom_socket* socket,
                                    grpc_error* error) {
  if (grpc_core::ExecCtx::Get() == nullptr) {
    /* If we are being run on a thread which does not have an exec_ctx created
     * yet, we should create one. */
    grpc_core::ExecCtx exec_ctx;
    custom_connect_callback_internal(socket, error);
  } else {
    custom_connect_callback_internal(socket, error);
  }
}

static void tcp_connect(grpc_closure* closure, grpc_endpoint** ep,
                        grpc_pollset_set* interested_parties,
                        const grpc_channel_args* channel_args,
                        const grpc_resolved_address* resolved_addr,
                        grpc_millis deadline) {
  GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
  (void)channel_args;
  (void)interested_parties;
  grpc_custom_tcp_connect* connect;
  grpc_resource_quota* resource_quota = grpc_resource_quota_create(nullptr);
  if (channel_args != nullptr) {
    for (size_t i = 0; i < channel_args->num_args; i++) {
      if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_RESOURCE_QUOTA)) {
        grpc_resource_quota_unref_internal(resource_quota);
        resource_quota = grpc_resource_quota_ref_internal(
            (grpc_resource_quota*)channel_args->args[i].value.pointer.p);
      }
    }
  }
  grpc_custom_socket* socket =
      (grpc_custom_socket*)gpr_malloc(sizeof(grpc_custom_socket));
  socket->refs = 2;
  grpc_custom_socket_vtable->init(socket, GRPC_AF_UNSPEC);
  connect =
      (grpc_custom_tcp_connect*)gpr_malloc(sizeof(grpc_custom_tcp_connect));
  connect->closure = closure;
  connect->endpoint = ep;
  connect->addr_name = grpc_sockaddr_to_uri(resolved_addr);
  connect->resource_quota = resource_quota;
  connect->socket = socket;
  socket->connector = connect;
  socket->endpoint = nullptr;
  socket->listener = nullptr;
  connect->refs = 2;

  if (grpc_tcp_trace.enabled()) {
    gpr_log(GPR_INFO, "CLIENT_CONNECT: %p %s: asynchronously connecting",
            socket, connect->addr_name);
  }

  GRPC_CLOSURE_INIT(&connect->on_alarm, on_alarm, socket,
                    grpc_schedule_on_exec_ctx);
  grpc_timer_init(&connect->alarm, deadline, &connect->on_alarm);
  grpc_custom_socket_vtable->connect(
      socket, (const grpc_sockaddr*)resolved_addr->addr, resolved_addr->len,
      custom_connect_callback);
}

grpc_tcp_client_vtable custom_tcp_client_vtable = {tcp_connect};
