/*
 * Copyright (c) 2020 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this
 * 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 <vcl/vcl_private.h>

static int
vcl_api_connect_app_socket (vcl_worker_t * wrk)
{
  clib_socket_t *cs = &wrk->app_api_sock;
  clib_error_t *err;
  int rv = 0;

  cs->config = (char *) vcm->cfg.vpp_app_socket_api;
  cs->flags =
    CLIB_SOCKET_F_IS_CLIENT | CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_BLOCKING;

  wrk->vcl_needs_real_epoll = 1;

  if ((err = clib_socket_init (cs)))
    {
      /* don't report the error to avoid flood of error messages during
       * reconnect */
      clib_error_free (err);
      rv = -1;
      goto done;
    }

done:

  wrk->vcl_needs_real_epoll = 0;

  return rv;
}

static int
vcl_api_attach_reply_handler (app_sapi_attach_reply_msg_t * mp, int *fds)
{
  vcl_worker_t *wrk = vcl_worker_get_current ();
  int i, rv, n_fds_used = 0;
  u64 segment_handle;
  u8 *segment_name;

  if (mp->retval)
    {
      VERR ("attach failed: %U", format_session_error, mp->retval);
      goto failed;
    }

  wrk->api_client_handle = mp->api_client_handle;
  /* reattaching via `vcl_api_retry_attach` wants wrk->vpp_wrk_index to be 0 */
  wrk->vpp_wrk_index = 0;
  segment_handle = mp->segment_handle;
  if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
    {
      VERR ("invalid segment handle");
      goto failed;
    }

  if (!mp->n_fds)
    goto failed;

  if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
    if (vcl_segment_attach (vcl_vpp_worker_segment_handle (0), "vpp-mq-seg",
			    SSVM_SEGMENT_MEMFD, fds[n_fds_used++]))
      goto failed;

  if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
    {
      segment_name = format (0, "memfd-%ld%c", segment_handle, 0);
      rv = vcl_segment_attach (segment_handle, (char *) segment_name,
			       SSVM_SEGMENT_MEMFD, fds[n_fds_used++]);
      vec_free (segment_name);
      if (rv != 0)
	goto failed;
    }

  vcl_segment_attach_mq (segment_handle, mp->app_mq, 0, &wrk->app_event_queue);

  if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
    {
      svm_msg_q_set_eventfd (wrk->app_event_queue, fds[n_fds_used++]);
      vcl_mq_epoll_add_evfd (wrk, wrk->app_event_queue);
    }

  vcl_segment_discover_mqs (vcl_vpp_worker_segment_handle (0),
			    fds + n_fds_used, mp->n_fds - n_fds_used);
  vcl_segment_attach_mq (vcl_vpp_worker_segment_handle (0), mp->vpp_ctrl_mq,
			 mp->vpp_ctrl_mq_thread, &wrk->ctrl_mq);
  vcm->ctrl_mq = wrk->ctrl_mq;
  vcm->app_index = mp->app_index;

  return 0;

failed:

  for (i = clib_max (n_fds_used - 1, 0); i < mp->n_fds; i++)
    close (fds[i]);

  return -1;
}

static int
vcl_api_send_attach (clib_socket_t * cs)
{
  app_sapi_msg_t msg = { 0 };
  app_sapi_attach_msg_t *mp = &msg.attach;
  u8 app_is_proxy, tls_engine;
  clib_error_t *err;

  app_is_proxy = (vcm->cfg.app_proxy_transport_tcp ||
		  vcm->cfg.app_proxy_transport_udp);
  tls_engine = CRYPTO_ENGINE_OPENSSL;

  clib_memcpy (&mp->name, vcm->app_name, vec_len (vcm->app_name));
  mp->options[APP_OPTIONS_FLAGS] =
    APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT |
    (vcm->cfg.app_scope_local ? APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE : 0) |
    (vcm->cfg.app_scope_global ? APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE : 0) |
    (app_is_proxy ? APP_OPTIONS_FLAGS_IS_PROXY : 0) |
    (vcm->cfg.use_mq_eventfd ? APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD : 0) |
    (vcm->cfg.huge_page ? APP_OPTIONS_FLAGS_USE_HUGE_PAGE : 0);
  mp->options[APP_OPTIONS_PROXY_TRANSPORT] =
    (u64) ((vcm->cfg.app_proxy_transport_tcp ? 1 << TRANSPORT_PROTO_TCP : 0) |
	   (vcm->cfg.app_proxy_transport_udp ? 1 << TRANSPORT_PROTO_UDP : 0));
  mp->options[APP_OPTIONS_SEGMENT_SIZE] = vcm->cfg.segment_size;
  mp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = vcm->cfg.add_segment_size;
  mp->options[APP_OPTIONS_RX_FIFO_SIZE] = vcm->cfg.rx_fifo_size;
  mp->options[APP_OPTIONS_TX_FIFO_SIZE] = vcm->cfg.tx_fifo_size;
  mp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] =
    vcm->cfg.preallocated_fifo_pairs;
  mp->options[APP_OPTIONS_EVT_QUEUE_SIZE] = vcm->cfg.event_queue_size;
  mp->options[APP_OPTIONS_TLS_ENGINE] = tls_engine;

  msg.type = APP_SAPI_MSG_TYPE_ATTACH;
  err = clib_socket_sendmsg (cs, &msg, sizeof (msg), 0, 0);
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  return 0;
}

int
vcl_sapi_attach (void)
{
  vcl_worker_t *wrk = vcl_worker_get_current ();
  app_sapi_msg_t _rmp, *rmp = &_rmp;
  clib_error_t *err;
  clib_socket_t *cs;
  int fds[32];

  /*
   * Init client socket and send attach
   */
  if (vcl_api_connect_app_socket (wrk))
    return -1;

  cs = &wrk->app_api_sock;
  if (vcl_api_send_attach (cs))
    return -1;

  /*
   * Wait for attach reply
   */
  err = clib_socket_recvmsg (cs, rmp, sizeof (*rmp), fds, ARRAY_LEN (fds));
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  if (rmp->type != APP_SAPI_MSG_TYPE_ATTACH_REPLY)
    return -1;

  return vcl_api_attach_reply_handler (&rmp->attach_reply, fds);
}

static int
vcl_api_add_del_worker_reply_handler (app_sapi_worker_add_del_reply_msg_t *
				      mp, int *fds)
{
  int n_fds = 0, i, rv;
  u64 segment_handle;
  vcl_worker_t *wrk;

  if (mp->retval)
    {
      VDBG (0, "add/del worker failed: %U", format_session_error, mp->retval);
      goto failed;
    }

  if (!mp->is_add)
    goto failed;

  wrk = vcl_worker_get_current ();
  wrk->api_client_handle = mp->api_client_handle;
  wrk->vpp_wrk_index = mp->wrk_index;
  wrk->ctrl_mq = vcm->ctrl_mq;

  segment_handle = mp->segment_handle;
  if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
    {
      clib_warning ("invalid segment handle");
      goto failed;
    }

  if (!mp->n_fds)
    goto failed;

  if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
    if (vcl_segment_attach (vcl_vpp_worker_segment_handle (wrk->wrk_index),
			    "vpp-worker-seg", SSVM_SEGMENT_MEMFD,
			    fds[n_fds++]))
      goto failed;

  if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
    {
      u8 *segment_name = format (0, "memfd-%ld%c", segment_handle, 0);
      rv = vcl_segment_attach (segment_handle, (char *) segment_name,
			       SSVM_SEGMENT_MEMFD, fds[n_fds++]);
      vec_free (segment_name);
      if (rv != 0)
	goto failed;
    }

  vcl_segment_attach_mq (segment_handle, mp->app_event_queue_address, 0,
			 &wrk->app_event_queue);

  if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
    {
      svm_msg_q_set_eventfd (wrk->app_event_queue, fds[n_fds]);
      vcl_mq_epoll_add_evfd (wrk, wrk->app_event_queue);
      n_fds++;
    }

  VDBG (0, "worker %u vpp-worker %u added", wrk->wrk_index,
	wrk->vpp_wrk_index);

  return 0;

failed:
  for (i = clib_max (n_fds - 1, 0); i < mp->n_fds; i++)
    close (fds[i]);

  return -1;
}

int
vcl_sapi_app_worker_add (void)
{
  vcl_worker_t *wrk = vcl_worker_get_current ();
  app_sapi_worker_add_del_msg_t *mp;
  app_sapi_msg_t _rmp, *rmp = &_rmp;
  app_sapi_msg_t msg = { 0 };
  int fds[SESSION_N_FD_TYPE];
  clib_error_t *err;
  clib_socket_t *cs;

  /* Connect to socket api */
  if (vcl_api_connect_app_socket (wrk))
    return -1;

  /*
   * Send add worker
   */
  cs = &wrk->app_api_sock;

  msg.type = APP_SAPI_MSG_TYPE_ADD_DEL_WORKER;
  mp = &msg.worker_add_del;
  mp->app_index = vcm->app_index;
  mp->is_add = 1;

  err = clib_socket_sendmsg (cs, &msg, sizeof (msg), 0, 0);
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  /*
   * Wait for reply and process it
   */
  err = clib_socket_recvmsg (cs, rmp, sizeof (*rmp), fds, ARRAY_LEN (fds));
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  if (rmp->type != APP_SAPI_MSG_TYPE_ADD_DEL_WORKER_REPLY)
    {
      clib_warning ("unexpected reply type %u", rmp->type);
      return -1;
    }

  return vcl_api_add_del_worker_reply_handler (&rmp->worker_add_del_reply,
					       fds);
}

void
vcl_sapi_app_worker_del (vcl_worker_t * wrk)
{
  app_sapi_worker_add_del_msg_t *mp;
  app_sapi_msg_t msg = { 0 };
  clib_error_t *err;
  clib_socket_t *cs;

  cs = &wrk->app_api_sock;

  msg.type = APP_SAPI_MSG_TYPE_ADD_DEL_WORKER;
  mp = &msg.worker_add_del;
  mp->app_index = vcm->app_index;
  mp->wrk_index = wrk->vpp_wrk_index;
  mp->is_add = 0;

  err = clib_socket_sendmsg (cs, &msg, sizeof (msg), 0, 0);
  if (err)
    clib_error_report (err);
  clib_socket_close (cs);
}

void
vcl_sapi_detach (vcl_worker_t * wrk)
{
  clib_socket_t *cs = &wrk->app_api_sock;
  clib_socket_close (cs);
}

int
vcl_sapi_recv_fds (vcl_worker_t * wrk, int *fds, int n_fds)
{
  app_sapi_msg_t _msg, *msg = &_msg;
  clib_socket_t *cs;
  clib_error_t *err;

  cs = &wrk->app_api_sock;

  err = clib_socket_recvmsg (cs, msg, sizeof (*msg), fds, n_fds);
  if (err)
    {
      clib_error_report (err);
      return -1;
    }
  if (msg->type != APP_SAPI_MSG_TYPE_SEND_FDS)
    return -1;

  return 0;
}

int
vcl_sapi_add_cert_key_pair (vppcom_cert_key_pair_t *ckpair)
{
  u32 cert_len = ckpair->cert_len, key_len = ckpair->key_len, certkey_len;
  vcl_worker_t *wrk = vcl_worker_get_current ();
  app_sapi_msg_t _msg = { 0 }, *msg = &_msg;
  app_sapi_cert_key_add_del_msg_t *mp;
  app_sapi_msg_t _rmp, *rmp = &_rmp;
  clib_error_t *err;
  clib_socket_t *cs;
  u8 *certkey = 0;
  int rv = -1;

  msg->type = APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY;
  mp = &msg->cert_key_add_del;
  mp->context = wrk->wrk_index;
  mp->cert_len = cert_len;
  mp->certkey_len = cert_len + key_len;
  mp->is_add = 1;

  certkey_len = cert_len + key_len;
  vec_validate (certkey, certkey_len - 1);
  clib_memcpy_fast (certkey, ckpair->cert, cert_len);
  clib_memcpy_fast (certkey + cert_len, ckpair->key, key_len);

  cs = &wrk->app_api_sock;
  err = clib_socket_sendmsg (cs, msg, sizeof (*msg), 0, 0);
  if (err)
    {
      clib_error_report (err);
      goto done;
    }

  err = clib_socket_sendmsg (cs, certkey, certkey_len, 0, 0);
  if (err)
    {
      clib_error_report (err);
      goto done;
    }

  /*
   * Wait for reply and process it
   */
  err = clib_socket_recvmsg (cs, rmp, sizeof (*rmp), 0, 0);
  if (err)
    {
      clib_error_report (err);
      goto done;
    }

  if (rmp->type != APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY_REPLY)
    {
      clib_warning ("unexpected reply type %u", rmp->type);
      goto done;
    }

  if (!rmp->cert_key_add_del_reply.retval)
    rv = rmp->cert_key_add_del_reply.index;

done:

  return rv;
}

int
vcl_sapi_del_cert_key_pair (u32 ckpair_index)
{
  vcl_worker_t *wrk = vcl_worker_get_current ();
  app_sapi_msg_t _msg = { 0 }, *msg = &_msg;
  app_sapi_cert_key_add_del_msg_t *mp;
  app_sapi_msg_t _rmp, *rmp = &_rmp;
  clib_error_t *err;
  clib_socket_t *cs;

  msg->type = APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY;
  mp = &msg->cert_key_add_del;
  mp->context = wrk->wrk_index;
  mp->index = ckpair_index;

  cs = &wrk->app_api_sock;
  err = clib_socket_sendmsg (cs, msg, sizeof (*msg), 0, 0);
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  /*
   * Wait for reply and process it
   */
  err = clib_socket_recvmsg (cs, rmp, sizeof (*rmp), 0, 0);
  if (err)
    {
      clib_error_report (err);
      return -1;
    }

  if (rmp->type != APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY_REPLY)
    {
      clib_warning ("unexpected reply type %u", rmp->type);
      return -1;
    }

  if (rmp->cert_key_add_del_reply.retval)
    return -1;

  return 0;
}

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
