/*
 * Copyright (c) 2017 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.h: unix file handling
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef included_clib_file_h
#define included_clib_file_h

#include <vppinfra/socket.h>
#include <vppinfra/pool.h>
#include <termios.h>


struct clib_file;
typedef clib_error_t *(clib_file_function_t) (struct clib_file * f);

typedef struct clib_file
{
  /* Unix file descriptor from open/socket. */
  u32 file_descriptor;

  u32 flags;
#define UNIX_FILE_DATA_AVAILABLE_TO_WRITE (1 << 0)
#define UNIX_FILE_EVENT_EDGE_TRIGGERED   (1 << 1)

  /* Data available for function's use. */
  uword private_data;

  /* Functions to be called when read/write data becomes ready. */
  clib_file_function_t *read_function, *write_function, *error_function;
} clib_file_t;

typedef enum
{
  UNIX_FILE_UPDATE_ADD,
  UNIX_FILE_UPDATE_MODIFY,
  UNIX_FILE_UPDATE_DELETE,
} clib_file_update_type_t;

typedef struct
{
  /* Pool of files to poll for input/output. */
  clib_file_t *file_pool;

  void (*file_update) (clib_file_t * file,
		       clib_file_update_type_t update_type);

} clib_file_main_t;

always_inline uword
clib_file_add (clib_file_main_t * um, clib_file_t * template)
{
  clib_file_t *f;
  pool_get (um->file_pool, f);
  f[0] = template[0];
  um->file_update (f, UNIX_FILE_UPDATE_ADD);
  return f - um->file_pool;
}

always_inline void
clib_file_del (clib_file_main_t * um, clib_file_t * f)
{
  um->file_update (f, UNIX_FILE_UPDATE_DELETE);
  close (f->file_descriptor);
  f->file_descriptor = ~0;
  pool_put (um->file_pool, f);
}

always_inline void
clib_file_del_by_index (clib_file_main_t * um, uword index)
{
  clib_file_t *uf;
  uf = pool_elt_at_index (um->file_pool, index);
  clib_file_del (um, uf);
}

always_inline uword
clib_file_set_data_available_to_write (clib_file_main_t * um,
				       u32 clib_file_index,
				       uword is_available)
{
  clib_file_t *uf = pool_elt_at_index (um->file_pool, clib_file_index);
  uword was_available = (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
  if ((was_available != 0) != (is_available != 0))
    {
      uf->flags ^= UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
      um->file_update (uf, UNIX_FILE_UPDATE_MODIFY);
    }
  return was_available != 0;
}

always_inline clib_file_t *
clib_file_get (clib_file_main_t * fm, u32 file_index)
{
  if (pool_is_free_index (fm->file_pool, file_index))
    return 0;
  return pool_elt_at_index (fm->file_pool, file_index);
}

#endif /* included_clib_file_h */

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