From d81310d55b9b7d07904c19f879f50e52fd7be489 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Mon, 06 Nov 2023 16:52:08 +0800 Subject: [PATCH] Add new code --- prj1_tlv/tlv_server.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 208 insertions(+), 32 deletions(-) diff --git a/prj1_tlv/tlv_server.c b/prj1_tlv/tlv_server.c index 64782a4..43251b6 100644 --- a/prj1_tlv/tlv_server.c +++ b/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" @@ -28,6 +30,19 @@ #define DEF_LISTEN_PORT 10086 #define MAX_EVENTS 512 + + +/* Every client need get a stand alone buffer to save TLV packet data */ +typedef struct cli_buf_s +{ + int fd; /* client fd */ + char buf[512]; /* client receive buffer */ + int bytes; /* left bytes in buffer */ + 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) { @@ -71,9 +86,13 @@ socket_t sock; int epollfd; int connfd; + int fd; + int nfds; struct epoll_event event_array[MAX_EVENTS]; - char buf[1024]; + cli_buf_t *cli_buf; + cli_buf_t *node; + struct list_head buf_list; /* every client get a stand alone buffer saved in the list */ struct option long_options[] = { {"port", required_argument, NULL, 'p'}, @@ -86,6 +105,7 @@ memset(&logger, 0, sizeof(logger)); memset(&sock, 0, sizeof(sock)); + INIT_LIST_HEAD(&buf_list); progname = basename(argv[0]); /* get program name */ @@ -154,14 +174,17 @@ log_nrml("TLV server program start running\n"); + /* set open file description number to max */ set_socket_rlimit(); + /* initial listen socket */ if( socket_listen(&sock, DEF_LISTEN_IP, port) < 0 ) { log_err("create listen socket failure\n"); return -2; } + /* create epoll and put listen socket into it */ if( (epollfd=epoll_init(MAX_EVENTS, sock.fd)) < 0 ) { log_err("initial epoll for listen socket failure\n"); @@ -171,73 +194,98 @@ /* g_signal.stop defined in proc.c, and will be set when catch stop signal */ while( !g_signal.stop ) { - /* program will blocked here */ - rv = epoll_wait(epollfd, event_array, MAX_EVENTS, -1/* never timeout */); - if( rv < 0 ) + /* epoll wailt and program will blocked here */ + nfds = epoll_wait(epollfd, event_array, MAX_EVENTS, -1 /* never timeout */); + if( nfds <= 0 ) { - log_err("epoll failure: %s\n", strerror(errno)); - continue; - } - else if( rv == 0) - { - log_err("epoll get timeout\n"); + log_err("epoll_wait failure or timeout: %s\n", strerror(errno)); continue; } - /* rv>0 is the active events count */ - for(i=0; i<rv; i++) + /* nfds>0 is the active events count */ + for(i=0; i<nfds; i++) { + fd = event_array[i].data.fd; + + /* epoll get error */ if ( (event_array[i].events&EPOLLERR) || (event_array[i].events&EPOLLHUP) ) { - log_err("epoll_wait get error on fd[%d]: %s\n", event_array[i].data.fd, strerror(errno)); - epoll_del(epollfd, event_array[i].data.fd); - close(event_array[i].data.fd); + log_err("epoll_wait get error on fd[%d]: %s\n", fd, strerror(errno)); + if( fd != sock.fd ) + term_socket_client(epollfd, event_array[i].data.fd, &buf_list); + + continue; } /* listen socket get event means new client start connect now */ - if( event_array[i].data.fd == sock.fd ) + if( fd == sock.fd ) { - struct epoll_event event; + /* accept new client socket */ if( (connfd=accept(sock.fd, (struct sockaddr *)NULL, NULL)) < 0) { log_nrml("accept new client failure: %s\n", strerror(errno)); continue; } - log_info("accept new client socket[%d]\n", connfd); - event.data.fd = connfd; - event.events = EPOLLIN; - epoll_ctl(epollfd, EPOLL_CTL_ADD, connfd, &event); - -#if 0 + /* add new client socket into epoll */ if( epoll_add(epollfd, connfd) < 0 ) { close(connfd); log_err("epoll add client socket failure, rv=%d\n", rv); } - log_dbg("epoll add new client socket[%d] ok.\n", connfd); -#endif + + /* malloc client buffer and add it into list */ + if( NULL != (cli_buf=(cli_buf_t *)malloc(sizeof(*cli_buf))) ) + { + memset(cli_buf, 0, sizeof(cli_buf)); + cli_buf->fd = connfd; + list_add_tail(&cli_buf->list, &buf_list); + log_info("alloc and add socket[%d] buffer[%p] into list\n", cli_buf->fd, cli_buf); + } + + log_nrml("accept and add new client socket[%d] ok.\n", connfd); } + /* already connected client socket get data arrive */ else { - rv=read(event_array[i].data.fd, buf, sizeof(buf)); + cli_buf = NULL; + + /* Use list_for_each_entry to find the client buf in buf list */ + list_for_each_entry(node, &buf_list, list) + { + if( node->fd == fd ) + { + log_info("found socket[%d] buffer[%p] in list\n", fd, node); + cli_buf = node; + } + } + + if( !cli_buf ) + { + log_err("can not find socket[%d] buffer and close it now\n", fd); + term_socket_client(epollfd, fd, NULL); + } + + rv=read(fd, &cli_buf->buf[cli_buf->bytes], sizeof(cli_buf->buf)-cli_buf->bytes); if( rv <= 0 ) { - printf("socket[%d] read failure [%s] or disconncet, close and remove now.\n", - event_array[i].data.fd, strerror(errno)); + log_warn("socket[%d] read failure [%s] or disconncet, terminate it now.\n", + fd, strerror(errno)); - epoll_del(epollfd, event_array[i].data.fd); - close( event_array[i].data.fd ); + term_socket_client(epollfd, fd, &buf_list); continue; } else { - log_dbg("socket[%d] receive %d bytes data\n", event_array[i].data.fd, rv); - logger_dump(LOG_LEVEL_INFO, buf, rv); + cli_buf->bytes += rv; + log_dbg("socket[%d] receive %d bytes data\n", fd, rv); } + parser_tlvpack(cli_buf); } } + + sleep(1); } logger_term(); @@ -245,3 +293,131 @@ 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; + + log_warn("start terminatl client socket[%d]\n", fd); + + /* if get buf_list, then remove buf from list */ + if( buf_list ) + { + /* Use list_for_each_entry_safe to travel the socket list and destroy the buffer */ + list_for_each_entry_safe(buf, tmp, buf_list, list) + { + if( buf->fd == fd ) + { + list_del(&buf->list); + free(buf); + log_info("free socket[%d] buffer[%p]\n", fd, buf); + break; + } + } + } + + epoll_del(epollfd, fd); + close( fd ); +} + -- Gitblit v1.9.1