//
// Created by xajhuang on 2023/4/20.
//

#ifndef VCPE_DHCP_NETWORK_H
#define VCPE_DHCP_NETWORK_H
#include <uv.h>
#include <linux/if_packet.h>
#include "network/vlan.h"
#include "service/dhcpd.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MAC_TO_STR(mac, str) \
    sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])

#define PKG_MMAP_BLOCKSIZ (1 << 22)
#define PKG_MMAP_FRAMESIZ (1 << 11)
#define PKG_MMAP_BLOCKNUM (64)

typedef struct {
    int                 sock;
    struct sockaddr_ll  addr;
    struct iovec       *rx;
    struct iovec       *tx;
    uint8_t            *map_recv;
    uint8_t            *map_send;
    struct tpacket_req3 recv;
    struct tpacket_req3 send;
    unsigned int        index;
} PACKET_MMAP_RING, *PPACKET_MMAP_RING;

typedef struct {
    char *pIfName;
    U32   ipAddr;
    U32   netmask;
    U8    macAddr[ETH_ALEN];
    S8    hostname[MAX_PATH];
} NIC_INFO, *PNIC_INFO;

struct block_desc {
    uint32_t              version;
    uint32_t              offset_to_priv;
    struct tpacket_hdr_v1 h1;
};

typedef struct {
    uv_work_cb       work_cb;
    uv_after_work_cb after_work_cb;
} RECV_CB_DATA, *PRECV_CB_DATA;

#pragma pack(1)

typedef struct {
    VLAN_PKG_HDR vlan_hdr;
    DHCP_PROTO   dhcp;
} DHCP_PACKAGE, *PDHCP_PACKAGE;

typedef struct {
    uv_work_t      uvWork;
    unsigned short nSize;
    unsigned char *pPkgBase;
    void          *pData;
} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO;

typedef struct {
    unsigned int      nf;
    PPKG_PROCESS_INFO pPkgInfo;
} PKG_MSG, *PPKG_MSG;

#pragma pack()

void  raw_sock_recv_cb(uv_poll_t *handle, int status, int events);
void  socket_send_task(uv_timer_t *UNUSED(pArg));
void  init_raw_socket_poll(void *pRecv, void *pClean);
int   create_udp_raw_socket(const char *pNicName);
void  init_filter(const char *pNetFilter);
void *get_pkg_free_buf();
U32   pkg_mmap_tx(U8 *pData, U32 nBytes);
int   dhcp_uninit();
#ifdef __cplusplus
}
#endif
#endif    //VCPE_DHCP_NETWORK_H