From b0053f87034ff358b7ccadc7f2d9643e9a7767e7 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Thu, 30 Apr 2020 16:15:09 +0800
Subject: [PATCH] update tlv project for server
---
prj1_tlv/lylib/proc.c | 2
prj1_tlv/lylib/socket.h | 32 +
prj1_tlv/tlv_client.c | 4
prj1_tlv/lylib/socket.c | 92 ++++
prj1_tlv/lylib/list.h | 723 ++++++++++++++++++++++++++++++++++++++++++
prj1_tlv/lylib/logger.c | 2
prj1_tlv/tlv_server.c | 115 ++++++
7 files changed, 951 insertions(+), 19 deletions(-)
diff --git a/prj1_tlv/lylib/list.h b/prj1_tlv/lylib/list.h
new file mode 100644
index 0000000..a8c3636
--- /dev/null
+++ b/prj1_tlv/lylib/list.h
@@ -0,0 +1,723 @@
+/*********************************************************************************
+ * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ * All rights reserved.
+ *
+ * Filename: list.h
+ * Description: This file is copied from Linux kernel, which provide link list API.
+ *
+ * Version: 1.0.0(08/09/2012~)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "08/09/2012 02:24:34 AM"
+ *
+ ********************************************************************************/
+
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <linux/stddef.h>
+
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr: the pointer to the member.
+ * @type: the type of the container struct this is embedded in.
+ * @member: the name of the member within the struct.
+ *
+ */
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
+
+#ifndef ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCH
+static inline void prefetch(const void *x) {;}
+#endif
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ first->prev = prev;
+ prev->next = first;
+
+ last->next = next;
+ next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+/**
+ * list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; prefetch(pos->next), pos != (head); \
+ pos = pos->next)
+
+/**
+ * __list_for_each - iterate over a list
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev - iterate over a list backwards
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @head: the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+ for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+ pos = pos->prev)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ prefetch(pos->prev), pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+static inline void INIT_HLIST_NODE(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ INIT_HLIST_NODE(n);
+ }
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if(next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+
+#endif
+
+
diff --git a/prj1_tlv/lylib/logger.c b/prj1_tlv/lylib/logger.c
index 9763d7b..a28c2aa 100644
--- a/prj1_tlv/lylib/logger.c
+++ b/prj1_tlv/lylib/logger.c
@@ -137,7 +137,7 @@
logger->fp = fopen(logger->file, filemode);
if (NULL == logger->fp)
{
- fprintf(stderr, "Open log file \"%s\" in %s failure\n", logger->file, filemode);
+ fprintf(stderr, "Open log file \"%s\" in %s failure: %s\n", logger->file, filemode, strerror(errno));
return -2;
}
diff --git a/prj1_tlv/lylib/proc.c b/prj1_tlv/lylib/proc.c
index 015609f..154864c 100644
--- a/prj1_tlv/lylib/proc.c
+++ b/prj1_tlv/lylib/proc.c
@@ -304,7 +304,7 @@
* *****************************************************************************/
int set_daemon_running(const char *pid_file)
{
- daemonize(0, 1);
+ daemonize(1, 1);
log_nrml("Program running as daemon [PID:%d].\n", getpid());
if (record_daemon_pid(pid_file) < 0)
diff --git a/prj1_tlv/lylib/socket.c b/prj1_tlv/lylib/socket.c
index 1d7b0be..1a0053e 100644
--- a/prj1_tlv/lylib/socket.c
+++ b/prj1_tlv/lylib/socket.c
@@ -22,7 +22,7 @@
* $create: call socket() create or not
* return value: <0: failure 0: successfully
*/
-int socket_ctx_init(socket_t *sock, uint8_t type, int create)
+int socket_init(socket_t *sock, uint8_t type, int create)
{
int fd = -1;
@@ -116,7 +116,6 @@
int socket_listen(socket_t *sock, char *ipaddr, int port)
{
int rv = 0;
- int fd = -1;
struct sockaddr_in addr;
int backlog = 13;
@@ -126,7 +125,7 @@
return -1;
}
- if( sock->status != SOCK_STAT_INIT )
+ if( sock->status != SOCK_STAT_UNINIT )
{
socket_close(sock);
}
@@ -149,7 +148,7 @@
}
/* initial socket context and create socket fd */
- if( socket_ctx_init(sock, SOCK_TYPE_LISTEN, SOCK_CREATE) < 0)
+ if( socket_init(sock, SOCK_TYPE_LISTEN, SOCK_CREATE) < 0)
{
log_err("socket context initial failure\n");
return -2;
@@ -179,8 +178,6 @@
goto cleanup;
}
- log_nrml("create socket and listen on [%s:%d] already\n", sock->laddr, sock->lport);
-
cleanup:
if( rv )
{
@@ -190,7 +187,7 @@
else
{
sock->status = SOCK_STAT_LISTENED;
- log_nrml("Create socket[%p:%d] listen [%s:%d] ok\n", sock, sock->fd, sock->laddr, sock->lport);
+ log_nrml("Create socket[%d] listen [%s:%d] ok\n", sock->fd, sock->laddr, sock->lport);
}
return rv;
@@ -236,7 +233,7 @@
/* socket not initial before */
if( SOCK_STAT_UNINIT== sock->status )
{
- if( socket_ctx_init(sock, SOCK_TYPE_LISTEN, SOCK_NOT_CREATE) < 0)
+ if( socket_init(sock, SOCK_TYPE_LISTEN, SOCK_NOT_CREATE) < 0)
{
log_err("ERROR: initial socket context failure\n");
return -2;
@@ -559,6 +556,72 @@
}
+/* description: create epoll for socket server and add listenfd into it
+ * input args: $max_evts: max events for epoll_create()
+ * $listenfd: listen socket fd
+ * return value: <0: failure >=0: epollfd
+ */
+int epoll_init(int max_evts, int listenfd)
+{
+ int epollfd;
+ struct epoll_event event;
+
+ if( max_evts<=0 || listenfd<0 )
+ {
+ log_err("Invalid input arguments\n");
+ return -1;
+ }
+
+ if( (epollfd=epoll_create(max_evts)) < 0 )
+ {
+ log_err("epoll_create() failure: %s\n", strerror(errno));
+ return -2;
+ }
+
+ if( epoll_add(epollfd, listenfd) < 0 )
+ {
+ log_err("epoll add listen socket[%d] failure: %s\n", listenfd, strerror(errno));
+ close(epollfd);
+ return -2;
+ }
+
+ log_nrml("epoll add listen socket[%d] ok\n", listenfd);
+ return epollfd;
+}
+
+/* description: add new fd into epoll to monitor
+ * input args: $epollfd: epoll fd
+ * $fd: socket fd need added into epoll
+ * return value: <0: failure 0: successfully
+ */
+inline int epoll_add(int epollfd, int fd)
+{
+ struct epoll_event event;
+
+ if( epollfd<0 || fd<0 )
+ {
+ log_err("Invalid input arguments\n");
+ return -1;
+ }
+
+ //event.events = EPOLLIN | EPOLLET; /* Edge Triggered */
+ event.events = EPOLLIN; /* default Level Triggered */
+ event.data.fd = fd;
+
+ if( epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event) < 0)
+ {
+ log_err("epoll add fd[%d] failure: %s\n", fd, strerror(errno));
+ return -2;
+ }
+
+ return 0;
+}
+
+
+
+/*+-------------------------------------------------------------------+
+ *| socket utils function |
+ *+-------------------------------------------------------------------+*/
/* description: parser hostname and port from $host and set it into $sock
* input args: $sock: socket context
@@ -787,3 +850,16 @@
}
+/* Set open file description count to max */
+void set_socket_rlimit(void)
+{
+ struct rlimit limit = {0};
+
+ getrlimit(RLIMIT_NOFILE, &limit );
+ limit.rlim_cur = limit.rlim_max;
+ setrlimit(RLIMIT_NOFILE, &limit );
+
+ log_nrml("set socket open fd max count to %d\n", limit.rlim_max);
+}
+
+
diff --git a/prj1_tlv/lylib/socket.h b/prj1_tlv/lylib/socket.h
index 1b5a043..b472ae6 100644
--- a/prj1_tlv/lylib/socket.h
+++ b/prj1_tlv/lylib/socket.h
@@ -32,6 +32,11 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
+#include <sys/epoll.h>
+#include <sys/resource.h>
+
+#include "list.h"
+
#define HOSTNAME_LEN 128
enum
@@ -69,7 +74,9 @@
int keepintvl; /* keepalive detect interval */
int keepcnt; /* keepalive count */
- struct sockaddr saddr; /* sockaddr for connect */
+ struct sockaddr saddr; /* sockaddr for connect */
+
+ struct list_head list; /* socket server manage client link list */
} socket_t;
@@ -88,7 +95,7 @@
SOCK_NOT_CREATE,
SOCK_CREATE,
};
-int socket_ctx_init(socket_t *sock, uint8_t type, int create);
+int socket_init(socket_t *sock, uint8_t type, int create);
/* description: close socket and set socket status as SOCK_STAT_INIT
@@ -148,6 +155,25 @@
int socket_recv(socket_t *sock, char *buf, int size, int timeout);
+/* description: create epoll for socket server and add listenfd into it
+ * input args: $max_evts: max events for epoll_create()
+ * $listenfd: listen socket fd
+ * return value: <0: failure >=0: epollfd
+ */
+int epoll_init(int max_evts, int listenfd);
+
+/* description: add new fd into epoll to monitor
+ * input args: $epollfd: epoll fd
+ * $fd: socket fd need added into epoll
+ * return value: <0: failure 0: successfully
+ */
+inline int epoll_add(int epollfd, int fd);
+
+static inline int epoll_del(int epollfd, int fd)
+{
+ return epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
+}
+
/*+-------------------------------------------------------------------+
*| socket utils function |
*+-------------------------------------------------------------------+*/
@@ -171,6 +197,8 @@
/* set heartbeat keepalive */
int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt);
+/* Set open file description count to max */
+void set_socket_rlimit(void);
#endif /* ----- #ifndef _SOCKET_H_ ----- */
diff --git a/prj1_tlv/tlv_client.c b/prj1_tlv/tlv_client.c
index 98c392d..03305be 100644
--- a/prj1_tlv/tlv_client.c
+++ b/prj1_tlv/tlv_client.c
@@ -69,7 +69,7 @@
char pid_file[64] = { 0 }; /* The file used to record the PID */
const char *progname=NULL;
- char *host = "192.168.2.110:10086";
+ char *host = "127.0.0.1:10086";
//char *host = "baidu.com:10086";
int log_level = LOG_LEVEL_NRML;
char *log_file = DEF_LOG_FILE;
@@ -321,7 +321,7 @@
if( (rv=socket_recv(sock, buf, sizeof(buf), timeout)) < 0 )
{
- log_err("read ACK from server failure, rv=%d\n");
+ log_err("read ACK from server failure, rv=%d\n", rv);
return -2;
}
}
diff --git a/prj1_tlv/tlv_server.c b/prj1_tlv/tlv_server.c
index f0e2d56..64782a4 100644
--- a/prj1_tlv/tlv_server.c
+++ b/prj1_tlv/tlv_server.c
@@ -19,10 +19,15 @@
#include "logger.h"
#include "proc.h"
+#include "socket.h"
#define PROG_VERSION "1.0.0"
#define DEF_LOG_FILE "tlv_server.log"
+#define DEF_LISTEN_IP "0.0.0.0"
+#define DEF_LISTEN_PORT 10086
+
+#define MAX_EVENTS 512
static void banner(void)
{
@@ -52,8 +57,9 @@
{
int opt;
int i = 0;
- //int rv = 0;
+ int rv = 0;
int debug = 0;
+ int port = DEF_LISTEN_PORT;
char pid_file[64] = { 0 }; /* The file used to record the PID */
const char *progname=NULL;
@@ -62,7 +68,15 @@
char *log_file = DEF_LOG_FILE;
logger_t logger;
+ socket_t sock;
+ int epollfd;
+ int connfd;
+ struct epoll_event event_array[MAX_EVENTS];
+
+ char buf[1024];
+
struct option long_options[] = {
+ {"port", required_argument, NULL, 'p'},
{"debug", no_argument, NULL, 'd'},
{"level", required_argument, NULL, 'l'},
{"version", no_argument, NULL, 'v'},
@@ -71,14 +85,18 @@
};
memset(&logger, 0, sizeof(logger));
+ memset(&sock, 0, sizeof(sock));
progname = basename(argv[0]); /* get program name */
/* parser the command line parameters */
- while ((opt = getopt_long(argc, argv, "c:dl:vh", long_options, NULL)) != -1)
+ while ((opt = getopt_long(argc, argv, "p:dl:vh", long_options, NULL)) != -1)
{
switch (opt)
{
+ case 'p': /* listen port */
+ port = atoi(optarg);
+ break;
case 'd': /* set debug running */
debug = 1;
@@ -105,6 +123,12 @@
}
}
+ if( port <= 0 )
+ {
+ printf("ERROR: no listen port specified, refer to program usage\n\n");
+ program_usage(progname);
+ }
+
/* check program already running or not, if already running then exit, or set running as daemon */
snprintf(pid_file, sizeof(pid_file), "/var/run/%s.pid", progname);
if( !debug )
@@ -114,6 +138,8 @@
printf("Programe already running, exit now.\n");
return -1;
}
+
+ set_daemon_running(pid_file);
}
/* initial and open logger system */
@@ -126,13 +152,92 @@
/* install signal proc handler */
install_proc_signal();
- log_nrml("Program start running\n");
+ log_nrml("TLV server program start running\n");
+
+ set_socket_rlimit();
+
+ if( socket_listen(&sock, DEF_LISTEN_IP, port) < 0 )
+ {
+ log_err("create listen socket failure\n");
+ return -2;
+ }
+
+ if( (epollfd=epoll_init(MAX_EVENTS, sock.fd)) < 0 )
+ {
+ log_err("initial epoll for listen socket failure\n");
+ return -2;
+ }
/* g_signal.stop defined in proc.c, and will be set when catch stop signal */
while( !g_signal.stop )
{
- log_dbg("Program still running\n");
- sleep(3);
+ /* program will blocked here */
+ rv = epoll_wait(epollfd, event_array, MAX_EVENTS, -1/* never timeout */);
+ if( rv < 0 )
+ {
+ log_err("epoll failure: %s\n", strerror(errno));
+ continue;
+ }
+ else if( rv == 0)
+ {
+ log_err("epoll get timeout\n");
+ continue;
+ }
+
+ /* rv>0 is the active events count */
+ for(i=0; i<rv; i++)
+ {
+ 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);
+ }
+
+ /* listen socket get event means new client start connect now */
+ if( event_array[i].data.fd == sock.fd )
+ {
+ struct epoll_event event;
+ 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
+ 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
+ }
+ else
+ {
+ rv=read(event_array[i].data.fd, buf, sizeof(buf));
+ if( rv <= 0 )
+ {
+ printf("socket[%d] read failure [%s] or disconncet, close and remove now.\n",
+ event_array[i].data.fd, strerror(errno));
+
+ epoll_del(epollfd, event_array[i].data.fd);
+ close( event_array[i].data.fd );
+ continue;
+ }
+ else
+ {
+ log_dbg("socket[%d] receive %d bytes data\n", event_array[i].data.fd, rv);
+ logger_dump(LOG_LEVEL_INFO, buf, rv);
+ }
+
+ }
+ }
}
logger_term();
--
Gitblit v1.9.1