/***************************************************************************//**
  @file ltrsrv_eth.c
  @author Borisov Alexey <borisov@lcard.ru>
  @date   16.02.2012

  Файл содержит определения констант, типов и функций, которые используются как в
  ltrsrv_client.c, так и в ltrsrv_client_cmd.c, но при этом скрыты от других
  частей программы ltr-server
  *****************************************************************************/


#ifndef LTRSRV_CLIENT_P_H
#define LTRSRV_CLIENT_P_H

#include "ltrsrv_client.h"
#include "ltrsrv_wait.h"

// команды клиент-сервер
#define LTR_CLIENT_CMD_SIZE                        8UL

#define LTR_CLIENT_CMD_BASE_MASK_                  0xFFFFFF00UL
#define LTR_CLIENT_CMD_BASE_                       0xABCDEF00UL

#define LTR_CLIENT_CMD_INIT_CONNECTION             (LTR_CLIENT_CMD_BASE_ + 0x00)



#define LTR_CLIENT_LOCATION_SIZE       128

typedef struct {
    uint32_t sign;
    uint32_t cmd;
    uint8_t data[1];
} t_ltr_client_cmd;

typedef struct {
    uint32_t ack;
    uint8_t data[1];
} t_ltr_client_cmd_resp;


typedef enum {
    CMD_STATE_IDLE,               /* нет обрабатываемой команды между клиентом и ltrd */
    CMD_STATE_RECV_UNKNOWN_SIZE,  /* идет прием команды, но еще не известен размер,
                                     так как не приняли необходимые для этого поля */
    CMD_STATE_RECV_FINAL,         /* идет прием команды и размер уже известен */
    CMD_STATE_SEND_RESP           /* передается ответ на команду */
} t_client_cmd_state;

typedef enum {
    LTRSRV_CLIENT_STATE_INIT,
    LTRSRV_CLIENT_STATE_DATA_STREAM,
    LTRSRV_CLIENT_STATE_CONTROL,
    LTRSRV_CLIENT_STATE_LOGPROTO,
    LTRSRV_CLIENT_STATE_CLOSED
} t_ltr_client_state;

typedef enum {
    LTRSRV_CLIENT_FLAG_DEBUG     = 0x80,
    LTRSRV_CLIENT_FLAG_RAW_DATA  = 0x40,
    LTRSRV_CLIENT_FLAG_INTF_MSK  = 0x07
} t_ltr_client_flags;


/** описание состояние клиента (не видно другим файлам) */
typedef struct st_ltr_client {
    uint32_t sign; /** признак правильности структуры */
    t_socket sock; /** сокет для обмена данными с клиентом */
    char location[LTR_CLIENT_LOCATION_SIZE]; /** строка с адресом клиента */
    char* log_str; /** строка для вывода в лог, описывающие данное подключение */
    t_ltr_client_state state; /** состяние клиента */    
    int wt_flags; /** флаги ожидания - нужно ожидать на прием и/или
                      передачу по сокету t_ltrsrv_wait_flags */
    uint8_t flags; /** Флаги, с которыми был открыт клиент */        
    uint8_t wt_cb; /** Признак ожидания завершения команды к крейту */

    uint8_t close_req; /* Запрос на закрытие */
    int close_req_err; /* Ошибка, соответствующая запросу на закрытие соединения */

    t_client_cmd_state cmd_state; /** состояние передачи команды */
    t_ltr_client_cmd* cmd; /** буфер для приема команды или ответа*/
    uint32_t last_cmd_code; /** код последней команды */
    unsigned int cmd_pos; /** позиция при приеме */
    unsigned int cmd_size; /** размер, скольк нам нужно принять */
    unsigned int cmd_max_size; /** выделенный размер под буфер команды */
    uint32_t def_recv_size;


    uint8_t part_recv[3]; /**< буфер для сохранения частично принятого слова от клиента */
    uint8_t part_snd[3]; /**< буфер для сохранения частично переданного слова клиенту */
    uint8_t part_snd_pos;
    uint8_t part_recv_pos;


    t_ltr_crate *crate; /** крейт, к которому подключен клиент (или NULL - если
                            соединен с самим сервером) */
    unsigned int slot; /** слот модуля, с которым соединен клиент (только для состяния
                            LTRSRV_CLIENT_STATE_DATA_STREAM) */
    t_ltr_client_snd_rdy_cb snd_rdy_cb; /** callback, который нужно вызвать,
                                      когда сокет будет доступен на передачу
                                    (только для состяния LTRSRV_CLIENT_STATE_DATA_STREAM)*/
} t_ltr_client;

int p_client_create_logstr(t_ltr_client *client);
int p_client_cmd_realloc_buf(t_ltr_client * client, unsigned int new_size);
int p_client_cmd_get_len(t_ltr_client* client);
int p_client_cmd_process(t_ltr_client* client);
int p_client_cmd_proc_send(t_ltr_client* client);
int p_client_cmd_post_process(t_ltr_client* client);
int p_client_get_ctl_cnt_from_crate(t_ltr_crate* crate);



#endif // LTRSRV_CLIENT_P_H
