APUE Learning Example Source Code
guowenxue
2020-06-07 8a383b8715fc07145fdc3f3e3dbe6ecd93f72989
update tlv_server program, add TLV parser support
2 files modified
124 ■■■■■ changed files
prj1_tlv/lylib/tlv_pack.h 14 ●●●●● patch | view | raw | blame | history
prj1_tlv/tlv_server.c 110 ●●●●● patch | view | raw | blame | history
prj1_tlv/lylib/tlv_pack.h
@@ -30,6 +30,7 @@
/* TLV packet Minimum size is fixed bytes + 1 byte data */
#define TLV_MIN_SIZE       (TLV_FIXED_SIZE+1)
#define TLV_MAX_SIZE       32    /* all TLV packet length are no more than 32 bytes */
/* Tag definition */
@@ -53,6 +54,19 @@
    int                    size; /* buffer size */
} tlv_buf_t;  
typedef struct tlv_pack_s
{
    unsigned char          header;
    unsigned char          tag;
    char                   len;
    char                   data[0];
    /* followed: $len bytes payload data */
    /* followed: 2 bytes CRC checksum    */
} tlv_pack_t;
/* Packet TLV message for server reply ACK message: ACK(ack=1)/NAK(ack=0) */
#define ACK         1
#define NAK         0
prj1_tlv/tlv_server.c
@@ -20,6 +20,8 @@
#include "logger.h"
#include "proc.h"
#include "socket.h"
#include "tlv_pack.h"
#include "crc-itu-t.h"
#define PROG_VERSION     "1.0.0"
@@ -39,7 +41,7 @@
    struct list_head     list;       /* all client buffer saved in a list */
} cli_buf_t;  
static int  parser_tlvpack(cli_buf_t *cli_buf);
static void term_socket_client(int epollfd, int fd, struct list_head *buf_list);
static void banner(void)
@@ -275,9 +277,11 @@
                }
                else
                {
                    cli_buf->bytes += rv;
                    log_dbg("socket[%d] receive %d bytes data\n", fd, rv); 
                    logger_dump(LOG_LEVEL_INFO, cli_buf->buf, rv);
                }
                parser_tlvpack(cli_buf);
            }
        }
@@ -289,6 +293,108 @@
    return 0;
static int parser_tlvpack(cli_buf_t *cli_buf)
{
    int                     i;
    int                     left_bytes;
    unsigned short          crc16;
    tlv_pack_t             *tlv_pack;
    if( !cli_buf )
    {
        log_err("Invalid input arguments\n");
        return -1;
    }
    log_info("start to parser client buffer %d bytes data:\n", cli_buf->bytes);
    logger_dump(LOG_LEVEL_INFO, cli_buf->buf, cli_buf->bytes);
    if( cli_buf->bytes < TLV_MIN_SIZE )
    {
        log_warn("TLV packet bytes less than min. size\n");
        return -2;
    }
PARSER_AGAIN:
    for(i=0; i<cli_buf->bytes; i++)
    {
        if( PACK_HEADER == (unsigned char )cli_buf->buf[i] )
        {
            log_dbg("found TLV packet header on [%d]\n", i);
            left_bytes = cli_buf->bytes - i;
            if(left_bytes < TLV_MIN_SIZE)
            {
                log_warn("TLV packet bytes less than min. size\n");
                memmove(cli_buf->buf, &cli_buf->buf[i], left_bytes);
                cli_buf->bytes = left_bytes;
                break;
            }
            tlv_pack = (tlv_pack_t *) &cli_buf->buf[i];
            log_info("header: 0x%02x tag: 0x%02x len: 0x%02x\n", tlv_pack->header, tlv_pack->tag, tlv_pack->len);
            if(tlv_pack->len > left_bytes )
            {
                log_err("TLV packet not integrated, continue to receive left data\n");
                memmove(cli_buf->buf, &cli_buf->buf[i], left_bytes);
                cli_buf->bytes = left_bytes;
                break;
            }
            if( tlv_pack->len > TLV_MAX_SIZE )
            {
                log_err("TLV packet length more than max. length, maybe found wrong header?\n");
                /* skip current header */
                left_bytes -= 1;
                memmove(cli_buf->buf, &cli_buf->buf[i+1], left_bytes);
                cli_buf->bytes = left_bytes;
                goto PARSER_AGAIN;
            }
            crc16 = crc_itu_t(MAGIC_CRC, (unsigned char *)&cli_buf->buf[i], tlv_pack->len-2);
            if( crc16 != bytes_to_ushort((unsigned char *)&cli_buf->buf[i+tlv_pack->len-2], 2) )
            {
                log_err("TLV packet CRC check error, maybe found wrong header?\n");
                /* skip current header */
                left_bytes -= 1;
                memmove(cli_buf->buf, &cli_buf->buf[i+1], left_bytes);
                cli_buf->bytes = left_bytes;
                goto PARSER_AGAIN;
            }
            if( tlv_pack->tag == TAG_SN )
            {
                log_nrml("Found SN TLV data:\n");
                dump_buf(tlv_pack->data, tlv_pack->len-TLV_FIXED_SIZE);
            }
            else if( tlv_pack->tag == TAG_TEMP )
            {
                log_nrml("Found temperature TLV data:\n");
                dump_buf(tlv_pack->data, tlv_pack->len-TLV_FIXED_SIZE);
            }
            else if( tlv_pack->tag == TAG_TIME )
            {
                log_nrml("Found date time TLV data:\n");
                dump_buf(tlv_pack->data, tlv_pack->len-TLV_FIXED_SIZE);
            }
            left_bytes -= tlv_pack->len;
            memmove(cli_buf->buf, &cli_buf->buf[i+tlv_pack->len], left_bytes);
            cli_buf->bytes = left_bytes;
            log_info("left %d bytes data:\n", cli_buf->bytes);
            logger_dump(LOG_LEVEL_INFO, cli_buf->buf, cli_buf->bytes);
            goto PARSER_AGAIN;
        }
    }
    return 0;
}
static void term_socket_client(int epollfd, int fd, struct list_head *buf_list)
{
    cli_buf_t          *buf, *tmp;