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