/*
 * Copyright (c) 2016 Cisco and/or its affiliates.
 * 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.
 */

/** @file
    udp builtin server
*/

#include <vnet/udp/udp.h>
#include <vnet/session/session.h>
#include <vnet/session/application_interface.h>

/** per-worker built-in server copy buffers */
u8 **copy_buffers;
static int app_index = ~0;

static int
builtin_session_create_callback (stream_session_t * s)
{
  /* Simple version: declare session ready-to-go... */
  s->session_state = SESSION_STATE_READY;
  return 0;
}

static void
builtin_session_disconnect_callback (stream_session_t * s)
{
  stream_session_disconnect (s);
}

static void
builtin_session_reset_callback (stream_session_t * s)
{
  clib_warning ("Reset session %U", format_stream_session, s, 2);
  stream_session_cleanup (s);
}

static int
builtin_session_connected_callback (u32 app_index, u32 api_context,
				    stream_session_t * s, u8 is_fail)
{
  clib_warning ("called...");
  return -1;
}

static int
builtin_server_rx_callback (stream_session_t * s)
{
  svm_fifo_t *rx_fifo, *tx_fifo;
  u32 this_transfer, max_deq, max_enq;
  int actual_transfer;
  u8 *my_copy_buffer;
  session_fifo_event_t evt;
  unix_shared_memory_queue_t *q;

  my_copy_buffer = copy_buffers[s->thread_index];
  rx_fifo = s->server_rx_fifo;
  tx_fifo = s->server_tx_fifo;

  max_deq = svm_fifo_max_dequeue (rx_fifo);
  max_enq = svm_fifo_max_enqueue (tx_fifo);
  this_transfer = max_enq < max_deq ? max_enq : max_deq;

  vec_validate (my_copy_buffer, this_transfer - 1);
  _vec_len (my_copy_buffer) = this_transfer;

  actual_transfer = svm_fifo_dequeue_nowait (rx_fifo, this_transfer,
					     my_copy_buffer);
  ASSERT (actual_transfer == this_transfer);
  actual_transfer = svm_fifo_enqueue_nowait (tx_fifo, this_transfer,
					     my_copy_buffer);
  ASSERT (actual_transfer == this_transfer);

  copy_buffers[s->thread_index] = my_copy_buffer;

  if (svm_fifo_set_event (tx_fifo))
    {
      /* Fabricate TX event, send to ourselves */
      evt.fifo = tx_fifo;
      evt.event_type = FIFO_EVENT_APP_TX;
      q = session_manager_get_vpp_event_queue (s->thread_index);
      unix_shared_memory_queue_add (q, (u8 *) & evt,
				    0 /* do wait for mutex */ );
    }

  return 0;
}

/* *INDENT-OFF* */
static session_cb_vft_t builtin_server = {
    .session_accept_callback = builtin_session_create_callback,
    .session_connected_callback = builtin_session_connected_callback,
    .session_disconnect_callback = builtin_session_disconnect_callback,
    .builtin_server_rx_callback = builtin_server_rx_callback,
    .session_reset_callback = builtin_session_reset_callback
};
/* *INDENT-ON* */

static int
attach_builtin_uri_server ()
{
  vnet_app_attach_args_t _a, *a = &_a;
  u8 segment_name[128];
  u32 segment_name_length;
  u64 options[16];

  segment_name_length = ARRAY_LEN (segment_name);

  memset (a, 0, sizeof (*a));
  memset (options, 0, sizeof (options));

  a->api_client_index = ~0;
  a->segment_name = segment_name;
  a->segment_name_length = segment_name_length;
  a->session_cb_vft = &builtin_server;

  options[APP_OPTIONS_ACCEPT_COOKIE] = 0x12345678;
  options[APP_OPTIONS_SEGMENT_SIZE] = (2 << 30);	/*$$$$ config / arg */
  options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
  options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = 1024;

  a->options = options;

  if (vnet_application_attach (a))
    return -1;

  app_index = a->app_index;
  return 0;
}

static int
bind_builtin_uri_server (u8 * uri)
{
  vnet_bind_args_t _a, *a = &_a;
  int rv;

  rv = attach_builtin_uri_server ();
  if (rv)
    return rv;

  memset (a, 0, sizeof (*a));
  a->uri = (char *) uri;
  a->app_index = app_index;

  rv = vnet_bind_uri (a);

  return rv;
}

static int
unbind_builtin_uri_server (u8 * uri)
{
  vnet_unbind_args_t _a, *a = &_a;

  a->app_index = app_index;
  a->uri = (char *) uri;

  return vnet_unbind_uri (a);
}

static clib_error_t *
builtin_server_init (vlib_main_t * vm)
{
  vlib_thread_main_t *vtm = vlib_get_thread_main ();
  u32 num_threads;

  num_threads = 1 /* main thread */  + vtm->n_threads;

  vec_validate (copy_buffers, num_threads - 1);
  return 0;
}

VLIB_INIT_FUNCTION (builtin_server_init);

static clib_error_t *
builtin_uri_bind_command_fn (vlib_main_t * vm,
			     unformat_input_t * input,
			     vlib_cli_command_t * cmd)
{
  u8 *uri = 0;
  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "uri %s", &uri))
	;
      else
	break;
    }

  if (uri == 0)
    return clib_error_return (0, "uri to bind not specified...");

  vnet_session_enable_disable (vm, 1 /* turn on UDP, etc. */ );

  rv = bind_builtin_uri_server (uri);

  vec_free (uri);

  switch (rv)
    {
    case 0:
      break;

    default:
      return clib_error_return (0, "bind_uri_server returned %d", rv);
      break;
    }

  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (builtin_uri_bind_command, static) =
{
  .path = "builtin uri bind",
  .short_help = "builtin uri bind",
  .function = builtin_uri_bind_command_fn,
};
/* *INDENT-ON* */

static clib_error_t *
builtin_uri_unbind_command_fn (vlib_main_t * vm,
			       unformat_input_t * input,
			       vlib_cli_command_t * cmd)
{
  u8 *uri = 0;
  int rv;

  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    {
      if (unformat (input, "uri %s", &uri))
	;
      else
	break;
    }

  if (uri == 0)
    return clib_error_return (0, "uri to unbind not specified...");

  rv = unbind_builtin_uri_server (uri);

  vec_free (uri);

  switch (rv)
    {
    case 0:
      break;

    default:
      return clib_error_return (0, "unbind_uri_server returned %d", rv);
      break;
    }

  return 0;
}

/* *INDENT-OFF* */
VLIB_CLI_COMMAND (builtin_uri_unbind_command, static) =
{
  .path = "builtin uri unbind",
  .short_help = "builtin uri unbind",
  .function = builtin_uri_unbind_command_fn,
};
/* *INDENT-ON* */

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