#pragma once

struct tfe_cmsg;
struct tfe_cmsg_serialize_header;


enum tfe_cmsg_errno
{
	TFE_CMSG_INVALID_FORMAT = -1,
	TFE_CMSG_BUFF_NOT_ENOUGH = -2,
	TFE_CMSG_INVALID_TYPE = -3,
};

enum tfe_cmsg_tlv_type
{
    /* TCP restore information */
    TFE_CMSG_TCP_RESTORE_SEQ = 0x0,
    TFE_CMSG_TCP_RESTORE_ACK = 0x1,
    TFE_CMSG_TCP_RESTORE_MSS_CLIENT = 0x2,
    TFE_CMSG_TCP_RESTORE_MSS_SERVER = 0x3,
    TFE_CMSG_TCP_RESTORE_WSACLE_CLIENT = 0x4,
    TFE_CMSG_TCP_RESTORE_WSACLE_SERVER = 0x5,
    TFE_CMSG_TCP_RESTORE_SACK_CLIENT = 0x6,
    TFE_CMSG_TCP_RESTORE_SACK_SERVER = 0x7,
    TFE_CMSG_TCP_RESTORE_TS_CLIENT = 0x8,
    TFE_CMSG_TCP_RESTORE_TS_SERVER = 0x9,
    TFE_CMSG_TCP_RESTORE_PROTOCOL = 0xa,
    TFE_CMSG_TCP_RESTORE_WINDOW_CLIENT = 0xb,
    TFE_CMSG_TCP_RESTORE_WINDOW_SERVER = 0xc,
    TFE_CMSG_TCP_RESTORE_INFO_PACKET_CUR_DIR = 0xd, 
    TFE_CMSG_TCP_RESTORE_TS_CLIENT_VAL = 0xe,
    TFE_CMSG_TCP_RESTORE_TS_SERVER_VAL = 0xf,

    TFE_CMSG_POLICY_ID = 0x10,
    TFE_CMSG_STREAM_TRACE_ID = 0x11,

    TFE_CMSG_SSL_INTERCEPT_STATE,     //size uint64_t, 0-passthrough, 1-intercept, 2-shutdown, referer from enum ssl_stream_action
    TFE_CMSG_SSL_SERVER_SIDE_LATENCY, //size uint64_t, milisecond
    TFE_CMSG_SSL_CLIENT_SIDE_LATENCY, //size uint64_t, milisecond
    TFE_CMSG_SSL_SERVER_SIDE_VERSION, //string, SSLv3 TLSv1 TLSv1.1 TLSv1.2 TLSv1.3 unknown
    TFE_CMSG_SSL_CLIENT_SIDE_VERSION,
    TFE_CMSG_SSL_PINNING_STATE, //size uint64_t, 0-not pinning 1-pinning 2-maybe pinning
    TFE_CMSG_SSL_CERT_VERIFY,
    TFE_CMSG_SSL_ERROR, //string

    /* Original Traffic's src & dst MAC address */
    TFE_CMSG_SRC_MAC,
    TFE_CMSG_DST_MAC,

    /* TCP option information */
    TFE_CMSG_DOWNSTREAM_TCP_NODELAY,
    TFE_CMSG_DOWNSTREAM_TCP_TTL,
    TFE_CMSG_DOWNSTREAM_TCP_KEEPALIVE,
    TFE_CMSG_DOWNSTREAM_TCP_KEEPCNT,
    TFE_CMSG_DOWNSTREAM_TCP_KEEPIDLE,
    TFE_CMSG_DOWNSTREAM_TCP_KEEPINTVL,
    TFE_CMSG_DOWNSTREAM_TCP_USER_TIMEOUT,

    TFE_CMSG_UPSTREAM_TCP_NODELAY,
    TFE_CMSG_UPSTREAM_TCP_TTL,
    TFE_CMSG_UPSTREAM_TCP_KEEPALIVE,
    TFE_CMSG_UPSTREAM_TCP_KEEPCNT,
    TFE_CMSG_UPSTREAM_TCP_KEEPIDLE,
    TFE_CMSG_UPSTREAM_TCP_KEEPINTVL,
    TFE_CMSG_UPSTREAM_TCP_USER_TIMEOUT,

    TFE_CMSG_TCP_PASSTHROUGH,

    /* Share tsg scan result */
    TFE_CMSG_SRC_SUB_ID,              // string max size 256
    TFE_CMSG_DST_SUB_ID,              // string max size 256
    TFE_CMSG_SRC_ASN,                 // string max size 64
    TFE_CMSG_DST_ASN,                 // string max size 64
    TFE_CMSG_SRC_ORGANIZATION,        // string max size 256
    TFE_CMSG_DST_ORGANIZATION,        // string max size 256
    TFE_CMSG_SRC_IP_LOCATION_COUNTRY, // string max size 256
    TFE_CMSG_DST_IP_LOCATION_COUNTRY, // string max size 256
    TFE_CMSG_SRC_IP_LOCATION_PROVINE, // string max size 256
    TFE_CMSG_DST_IP_LOCATION_PROVINE, // string max size 256
    TFE_CMSG_SRC_IP_LOCATION_CITY,    // string max size 256
    TFE_CMSG_DST_IP_LOCATION_CITY,    // string max size 256

    /* SSL ja3 fingerprint */
    TFE_CMSG_SSL_CLIENT_JA3_FINGERPRINT, // string max size 32

    TFE_CMSG_FQDN_CAT_ID_NUM, // unsigned int
    TFE_CMSG_FQDN_CAT_ID_VAL, // max size 8 * sizeof(unsigned int)

    TFE_CMSG_COMMON_DIRECTION,
    /* Add new cmsg here */
    /* Add new cmsg here */
    /* Add new cmsg here */

    /* MAX cmsg num */
    TFE_CMSG_TLV_NR_MAX
};

struct tfe_cmsg* tfe_cmsg_init();
void tfe_cmsg_destroy(struct tfe_cmsg *cmsg);

int tfe_cmsg_get_value(struct tfe_cmsg * cmsg, enum tfe_cmsg_tlv_type type, unsigned char * out_value,
    size_t sz_out_value_buf, uint16_t * out_size);
int tfe_cmsg_set(struct tfe_cmsg * cmsg, enum tfe_cmsg_tlv_type type, const unsigned char * value, uint16_t size);
uint16_t tfe_cmsg_serialize_size_get(struct tfe_cmsg *cmsg);
int tfe_cmsg_serialize(struct tfe_cmsg *cmsg, unsigned char *buff, uint16_t bufflen, uint16_t *serialize_len);
int tfe_cmsg_deserialize(const unsigned char *data, uint16_t len, struct tfe_cmsg** pcmsg);
