From f63647218e192628aa8598d504e064529398f159 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Mon, 06 Nov 2023 17:22:09 +0800
Subject: [PATCH] rename ddns example code

---
 prj1_tlv/tlv_server.c |  206 ++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 192 insertions(+), 14 deletions(-)

diff --git a/prj1_tlv/tlv_server.c b/prj1_tlv/tlv_server.c
index ed2b7d2..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,10 +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'}, 
@@ -87,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 */
 
@@ -186,17 +205,20 @@
         /* 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 )
             {
                 /* accept new client socket  */
                 if( (connfd=accept(sock.fd, (struct sockaddr *)NULL, NULL)) < 0)
@@ -204,7 +226,6 @@
                     log_nrml("accept new client failure: %s\n", strerror(errno));
                     continue;
                 }
-                log_info("accept new client socket[%d]\n", connfd);
 
                 /* add new client socket into epoll  */
                 if( epoll_add(epollfd, connfd) < 0 )
@@ -212,26 +233,55 @@
                     close(connfd);
                     log_err("epoll add client socket failure, rv=%d\n", rv);
                 }
-                log_dbg("epoll add new client socket[%d] ok.\n", connfd); 
+
+                /* 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);
             }
         }
 
@@ -243,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