/******************************************************************************
 * file    include/vty.h 
 * author  YuLiang
 * version 1.0.0
 * date    10-Sep-2021
 * brief   This file provides all the headers of the vty functions.
 ******************************************************************************
 * Attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2021 LandPower</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of LandPower nor the names of its contributors may be used to 
 *      endorse or promote products derived from this software without specific
 *      prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************/

#ifndef _VTY_H_
#define _VTY_H_

/* Includes ------------------------------------------------------------------*/
#include <sys/resource.h>

#include "array.h"

/* Define --------------------------------------------------------------------*/
/* Thread types. */
#define THREAD_READ           0
#define THREAD_WRITE          1
#define THREAD_TIMER          2
#define THREAD_EVENT          3
#define THREAD_READY          4
#define THREAD_BACKGROUND     5
#define THREAD_UNUSED         6
#define THREAD_PERFORM        7

/* Struct timeval's tv_usec one second value.  */
#define TIMER_SECOND_MICRO 1000000L

#define RUSAGE_T rusage_t
#define GETRUSAGE(X) thread_getrusage(X)

#define THREAD_ADD_READ(m,f,a,v) thread_add_read(m,f,a,v,#f)
#define THREAD_ADD_WRITE(m,f,a,v) thread_add_write(m,f,a,v,#f)
#define THREAD_ADD_TIMER(m,f,a,v) thread_add_timer(m,f,a,v,#f)
#define THREAD_ADD_TIMER_MSEC(m,f,a,v) thread_add_timer_msec(m,f,a,v,#f)
#define THREAD_ADD_EVENT(m,f,a,v) thread_add_event(m,f,a,v,#f)
#define THREAD_EXECUTE(m,f,a,v) thread_execute(m,f,a,v,#f)

/* Macros. */
#define THREAD_ARG(X) ((X)->arg)
#define THREAD_FD(X)  ((X)->u.fd)
#define THREAD_VAL(X) ((X)->u.val)

#define VTY_BUFSIZ 512
#define VTY_TMP_BUFSIZ 1024
#define VTY_MAXHIST 20
#define TELNET_NAWS_SB_LEN 5

#define VTY_TIMEOUT_VAL 600

/* Vty read buffer size. */
#define VTY_READ_BUFSIZ 512

/* Small macro to determine newline is newline only or linefeed needed. */
#define VTY_NEWLINE  ((vty->type == VTY_TERM || vty->type == VTY_CMD) ? "\r\n" : "\n")

#define CONTROL(X)      ((X) - '@')
#define VTY_NO_ESCAPE       0
#define VTY_PRE_ESCAPE      1
#define VTY_ESCAPE          2

#define VTY_USERNAME_LEN    32
#define VTY_USERNAME_DEFAULT "ld"
#define VTY_PASSWORD_DEFAULT "1"

/* Exported types ------------------------------------------------------------*/
/* buffer数据结构体. 必须保证: 0 <= sp <= cp <= size. */
typedef struct _buf_data
{
    struct _buf_data *next;     /* 数据链表. */
    size_t cp;                  /* 当前可以添加的数据索引. */
    size_t sp;                  /* 等待数据发送的数据索引. */
    unsigned char data[];       /* 数据空间. */
} buf_data_t;

/* Buffer结构体. */
typedef struct _buf
{
    buf_data_t *head;             /* 数据块头. */
    buf_data_t *tail;             /* 数据块尾. */
    size_t size;                  /* 每个数据块的大小. */
} buf_t;

typedef int hash_key_f(void*);
typedef void* hash_alloc_f(void *);
typedef int hash_cmp_f(const void*, const void*);

typedef struct _hash_backet
{
    struct _hash_backet *next;  /* Linked list. */
    unsigned int key;           /* Hash key. */
    void *data;                 /* Data. */
} hash_backet_t;

typedef struct _hash
{
    hash_backet_t **index;      /* Hash backet. */
    unsigned int size;          /* Hash table size. */
    hash_key_f *hash_key;       /* Key make function. */
    hash_cmp_f *hash_cmp;       /* Data compare function. */
    unsigned long count;        /* Backet alloc. */
} hash_t;

typedef unsigned char thread_type;

typedef struct _rusage
{
    struct rusage cpu;
    struct timeval real;
} rusage_t;

typedef struct _time_stats
{
    unsigned long total, max;
} time_stats_t;

typedef struct _cpu_thread_history
{
    int (*func)(void*);
    char *funcname;
    unsigned int total_calls;
    time_stats_t real;
    time_stats_t cpu;
    thread_type types;
} cpu_thread_history_t;



/* Linked list of thread. */
typedef struct _thread_list
{
    struct _thread *head;
    struct _thread *tail;
    int count;
} thread_list_t;

/* Master of the theads. */
typedef struct _thread_master
{
    thread_list_t read;
    thread_list_t write;
    thread_list_t timer;
    thread_list_t event;
    thread_list_t ready;
    thread_list_t unuse;
    thread_list_t background;
    fd_set readfd;
    fd_set writefd;
    fd_set exceptfd;
    unsigned long alloc;
} thread_master_t;

/* Thread itself. */
typedef struct _thread
{
    thread_type type;           /* thread type */
    thread_type add_type;       /* thread type */
    struct _thread *next;       /* next pointer of the thread */   
    struct _thread *prev;       /* previous pointer of the thread */
    thread_master_t *master;    /* pointer to the struct thread_master. */
    int (*func)(struct _thread*);     /* event function */
    void *arg;                  /* event argument */
    union 
    {
        int val;                /* second argument of the event. */
        int fd;                 /* file descriptor in case of read/write. */
        struct timeval sands;   /* rest of time sands value. */
    } u;
    RUSAGE_T ru;                /* Indepth usage info.  */
    cpu_thread_history_t *hist; /* cache pointer to cpu_history */
    char* funcname;
} thread_t;

typedef int thread_func_f(thread_t*);

typedef enum {VTY_TERM, VTY_FILE, VTY_SHELL, VTY_SHELL_SERV, VTY_CMD} VTY_TYPE_E;
typedef enum {VTY_NORMAL, VTY_CLOSE, VTY_MORE, VTY_MORELINE} VTY_STAT_E;

/* Vty events */
typedef enum
{
  VTY_SERV,
  VTY_READ,
  VTY_WRITE,
  VTY_TIMEOUT_RESET,
#if 0
  VTYSH_SERV,
  VTYSH_READ,
  VTYSH_WRITE
#endif /* VTYSH */
} VTY_EVENT_E;

/* 用户结构体 */
typedef struct
{
    char username[VTY_USERNAME_LEN];
    char password[VTY_USERNAME_LEN];
    uint8_t level;                      /* 用户等级 */
} vty_user_t;

/* VTY struct. */
typedef struct
{
    int fd;                     /* File descripter of this vty. */
    VTY_TYPE_E type;            /* Is this vty connect to file or not */
    uint32_t node;              /* Node status of this vty */
    char *address;              /* What address is this vty comming from. */
    uint32_t fail_count;        /* Failure count */
    
    buf_t *out_buf;             /* Output buffer. */
    char *buf;                  /* Command input buffer */
    uint32_t cp;                /* Command cursor point */
    uint32_t length;            /* Command length */
    uint32_t max;               /* Command max length. */
    
    char *hist[VTY_MAXHIST];    /* Histry of command */
    uint32_t hp;                /* History lookup current point */
    uint32_t hindex;            /* History insert end point */
    
    void *index;                /* For current referencing point of interface, route-map, access-list etc... */
    void *index_sub;            /* For multiple level index treatment such as key chain and key. */
    unsigned char escape;       /* For escape character. */
    VTY_STAT_E status;          /* Current vty status. */

    /* IAC handling: was the last character received the
     IAC (interpret-as-command) escape character (and therefore the next
     character will be the command code)?  Refer to Telnet RFC 854. */
    unsigned char iac;
    unsigned char iac_sb_in_progress;   /* IAC SB (option subnegotiation) handling */
    
    /* At the moment, we care only about the NAWS (window size) negotiation,
     and that requires just a 5-character buffer (RFC 1073):
       <NAWS char> <16-bit width> <16-bit height> */
    unsigned char sb_buf[TELNET_NAWS_SB_LEN];
    /* How many subnegotiation characters have we received?  We just drop
     those that do not fit in the buffer. */
    size_t sb_len;

    uint32_t width;             /* Window width/height. */
    uint32_t height;

    int32_t lines;             /* Configure lines. */
    int32_t monitor;            /* Terminal monitor. */

    int config;                 /* In configure mode. */

    /* Read and write thread. */
    thread_t *t_read;
    thread_t *t_write;

    /* Timeout seconds and thread. */
    unsigned long v_timeout;
    thread_t *t_timeout;

    /* Timeout seconds and thread. */
    vty_user_t user;
} vty_t;

/* Exported macro ------------------------------------------------------------*/

/* Extern global variables ---------------------------------------------------*/

/* Extern functions ----------------------------------------------------------*/
extern void *hash_get(hash_t *hash, void *data, hash_alloc_f alloc_func);

extern unsigned long thread_consumed_time(RUSAGE_T *now,RUSAGE_T *start, unsigned long *cputime);
extern thread_master_t *thread_master_create();
extern void thread_call(thread_t *thread);
extern thread_t *thread_add_read(thread_master_t *m, thread_func_f *func, void *arg, int fd, const char* funcname);
extern thread_t *thread_add_write(thread_master_t *m, thread_func_f *func, void *arg, int fd, const char* funcname);
extern thread_t *thread_add_timer(thread_master_t *m, thread_func_f *func, void *arg, long timer, const char* funcname);
extern thread_t *thread_add_timer_msec(thread_master_t *m, thread_func_f *func, void *arg, long timer, const char* funcname);
extern thread_t *thread_add_background(thread_master_t *m, thread_func_f *func, void *arg, long delay, const char *funcname);
extern thread_t *thread_add_event(thread_master_t *m, thread_func_f *func, void *arg, int val, const char* funcname);
extern thread_t *thread_execute(thread_master_t *m, thread_func_f *func, void *arg, int val, const char* funcname);
extern void thread_cancel(thread_t *thread);
extern thread_t *thread_fetch(thread_master_t *m, thread_t *fetch);

extern int vty_out(vty_t *vty, const char *format, ...);
extern vty_t *vty_create();
extern int vty_execute(vty_t *vty);
extern int vty_config_lock(vty_t *vty);
extern int vty_config_unlock(vty_t *vty);
extern void vty_question(vty_t *vty, array_t *cmd_line);
extern void vty_print_word(vty_t *vty, char *strs[]);
extern void vty_free_match_strs(char *match_strs[]);
extern void vty_will_echo(vty_t *vty);
extern void vty_will_suppress_go_ahead(vty_t *vty);
extern void vty_dont_linemode(vty_t *vty);
extern void vty_do_window_size(vty_t *vty);
extern void vty_prompt(vty_t *vty);
extern void vty_close(vty_t *vty);
extern void vty_init(void);
extern void vty_event(VTY_EVENT_E event, int sock, vty_t *vty);
extern void vty_log(const char *level, const char *proto_str, const char *format, char *time_str, va_list va);
extern void vty_print(const char *format, va_list va);
extern void vty_serv_sock_family(const char* addr, unsigned short port, int family);
extern void vty_reset(void);
extern void vty_version_print(vty_t *vty);

#endif
/************************ (C) COPYRIGHT LandPower ***** END OF FILE ****************/
