├── .gitignore ├── Makefile ├── README.md ├── domain_parse.c ├── domain_parse.h ├── list.h ├── rtt.c ├── sarudp_comm.c ├── sarudp_comm.h ├── sarudp_peer.c ├── sarudp_peer.h ├── sarudp_serv.c ├── sarudp_serv.h ├── su_peer_client.c ├── su_peer_server.c ├── su_serv_server.c ├── unprtt.h ├── wrapfunc.c ├── wrapfunc.h ├── yharguments.c ├── yharguments.h ├── yhdaemon.c ├── yhdaemon.h ├── yherror.c ├── yherror.h ├── yhevent.c ├── yhevent.h ├── yhrbtree.c ├── yhrbtree.h ├── yhtime.c └── yhtime.h /.gitignore: -------------------------------------------------------------------------------- 1 | ### git's track ignore file-list. 2 | ### vim tempfile 3 | .*.swp 4 | tags 5 | cscope.in.out 6 | cscope.out 7 | cscope.po.out 8 | 9 | ### Source Insight 10 | *.IAB 11 | *.IAD 12 | *.IMB 13 | *.IMD 14 | *.PFI 15 | *.PO 16 | *.PR 17 | *.PRI 18 | *.PS 19 | *.WK3 20 | *.SearchResults 21 | 22 | ### SlickEdit 23 | *.vpwhist 24 | *.vtg 25 | *.vpj 26 | *.vpw 27 | 28 | !.gitignore 29 | !.gitmodules 30 | 31 | # Other ignore the trace files 32 | *.o 33 | #*.a 34 | #*.bak 35 | #*~ 36 | #*.so 37 | #*.log 38 | #*.gz 39 | #*.bz2 40 | su_peer_server 41 | su_peer_client 42 | su_serv_server 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS += -g 3 | CFLAGS += -D_REENTRANT -Wall 4 | CFLAGS += -O0 5 | 6 | #CFLAGS += -Wno-unused-variable 7 | #CFLAGS += -Wno-unused-but-set-variable 8 | 9 | CFLAGS += -Dpromiscuous_mode 10 | 11 | #CFLAGS += -DSU_DEBUG_RTT 12 | #CFLAGS += -DSU_DEBUG_PEER_RECV 13 | #CFLAGS += -DSU_DEBUG_PEER_RESEND 14 | #CFLAGS += -DSU_DEBUG_TIMEVERBOSE 15 | #CFLAGS += -DSU_DEBUG_LIST 16 | #CFLAGS += -DSU_DEBUG_RBTREE 17 | CFLAGS += -DSU_DEBUG_IP6FULL 18 | 19 | CLIBS = -lpthread 20 | 21 | RANLIB = ranlib 22 | 23 | CLEANFILES = core core.* *.core *.o temp.* typescript* *.lc *.lh 24 | 25 | PROGS = su_peer_client su_peer_server su_serv_server 26 | 27 | all: ${PROGS} 28 | 29 | .PHONY: all clean clear cmake remake 30 | 31 | su_peer_client: su_peer_client.o sarudp_peer.o sarudp_comm.o rtt.o domain_parse.o wrapfunc.o \ 32 | yhevent.o yherror.o yharguments.o yhtime.o yhrbtree.o 33 | ${CC} ${CFLAGS} -o $@ $^ ${CLIBS} 34 | su_peer_server: su_peer_server.o sarudp_peer.o sarudp_comm.o rtt.o domain_parse.o wrapfunc.o \ 35 | yhevent.o yherror.o yharguments.o yhtime.o yhrbtree.o yhdaemon.o 36 | ${CC} ${CFLAGS} -o $@ $^ ${CLIBS} 37 | 38 | su_serv_server: su_serv_server.o sarudp_serv.o sarudp_comm.o rtt.o domain_parse.o wrapfunc.o \ 39 | yhevent.o yherror.o yharguments.o yhtime.o yhrbtree.o yhdaemon.o 40 | ${CC} ${CFLAGS} -o $@ $^ ${CLIBS} 41 | 42 | clean: 43 | rm -f ${PROGS} ${CLEANFILES} 44 | clear: 45 | clear 46 | cmake: 47 | make clear 48 | make 49 | remake: 50 | make clear 51 | make clean 52 | make all 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | sarudp 是在 UDP 上实现了重传机制增加传输可靠性的协议,它同时具有 UDP 和 TCP 的优点,并且可同时支持 IPv6 和 IPv4 网络程序开发。
2 |
3 | [详细...](http://git.oschina.net/yuanhack/sarudp/wikis/Home) 4 | -------------------------------------------------------------------------------- /domain_parse.c: -------------------------------------------------------------------------------- 1 | #include "domain_parse.h" 2 | 3 | int domain_parse(const char *str, char *buff, int len, char *errinfo, int errlen) 4 | { 5 | struct addrinfo *answer, hint, *curr; 6 | bzero(&hint, sizeof(hint)); 7 | hint.ai_family = AF_INET; 8 | hint.ai_socktype = SOCK_STREAM; 9 | 10 | memset(errinfo, 0, errlen); 11 | 12 | int ret = getaddrinfo(str, NULL, &hint, &answer); 13 | if (ret != 0) { 14 | snprintf(errinfo, errlen, "getaddrinfo() %s: %s", str, gai_strerror(ret)); 15 | return -1; 16 | } 17 | 18 | for (curr = answer; curr != NULL; curr = curr->ai_next) { 19 | if (!inet_ntop(AF_INET, &(((struct sockaddr_in *)(curr->ai_addr))->sin_addr), buff, len)) { 20 | snprintf(errinfo, errlen, "inet_ntop() error: %s", strerror(errno)); 21 | freeaddrinfo(answer); 22 | return -1; 23 | } 24 | break; 25 | } 26 | freeaddrinfo(answer); 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /domain_parse.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH__STASH_SRC_DNS_DOMAIN_PARSE_H__ 2 | #define __YH__STASH_SRC_DNS_DOMAIN_PARSE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | 21 | int domain_parse(const char *str, char *buff, int len, 22 | char *errinfo, int errlen); 23 | 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | #endif /* __YH__STASH_SRC_DNS_DOMAIN_PARSE_H__ */ 29 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_LIST_H__ 2 | #define __YH_LIST_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" 6 | { 7 | #endif 8 | 9 | /********************************************************** 10 | 功能: 计算MEMBER成员在TYPE结构体中的偏移量 11 | **********************************************************/ 12 | #ifndef offsetof 13 | #define offsetof(type, member) \ 14 | (size_t)&(((type *)0)->member) 15 | #endif 16 | 17 | /********************************************************** 18 | 功能: 计算链表元素的起始地址 19 | 输入: 20 | ptr: type结构体中的链表指针 21 | type: 结构体类型 22 | member: 链表成员名称 23 | **********************************************************/ 24 | //#define container_of(ptr, type, member) (type *)((char*)(ptr) - offsetof(type, member)) 25 | #ifndef container_of 26 | #define container_of(ptr, type, member) \ 27 | ({\ 28 | const typeof(((type *)0)->member) * __mptr = (ptr);\ 29 | (type *)((char *)__mptr - offsetof(type, member)); \ 30 | }) 31 | #endif 32 | 33 | #define LIST_HEAD_INIT(name) {&(name), &(name)} 34 | 35 | struct list 36 | { 37 | struct list *prev, *next; 38 | }; 39 | 40 | static inline void list_init(struct list *list) 41 | { 42 | list->next = list; 43 | list->prev = list; 44 | } 45 | 46 | static inline int list_empty(struct list *list) 47 | { 48 | return list->next == list; 49 | } 50 | 51 | static inline void list_insert_prev(struct list* link, struct list *newn) 52 | { 53 | newn->prev = link->prev; 54 | newn->next = link; 55 | newn->prev->next = newn; 56 | newn->next->prev = newn; 57 | } 58 | static inline void list_insert_next(struct list* link, struct list *newn) 59 | { 60 | newn->prev = link; 61 | newn->next = link->next; 62 | newn->prev->next = newn; 63 | newn->next->prev = newn; 64 | } 65 | 66 | /********************************************************** 67 | 功能: 将new_link节点插入到list链表中 68 | 表头作为哨兵 插入表头之后第一个位置 69 | **********************************************************/ 70 | static inline void list_insert(struct list *list, struct list *new_link) 71 | { 72 | list_insert_next(list, new_link); 73 | } 74 | 75 | /********************************************************** 76 | 功能: 将new_link节点追加到list链表中 77 | 对于循环列表而言插入到表头之前即是添加到表尾 78 | **********************************************************/ 79 | static inline void list_append(struct list *list, struct list *new_link) 80 | { 81 | list_insert_prev(list, new_link); 82 | } 83 | 84 | /********************************************************** 85 | 功能: 从链表中移除节点 86 | **********************************************************/ 87 | static inline void list_remove(struct list *link) 88 | { 89 | link->prev->next = link->next; 90 | link->next->prev = link->prev; 91 | } 92 | 93 | /********************************************************** 94 | 获取link节点对应的结构体变量地址 95 | link: 链表节点指针 96 | type: 结构体类型名 97 | member: 结构体成员变量名 98 | **********************************************************/ 99 | #define list_entry(link, type, member) container_of(link, type, member) 100 | 101 | 102 | /********************************************************** 103 | 获取链表头节点对应的结构体变量地址 104 | list: 链表头指针 105 | type: 结构体类型名 106 | member: 结构体成员变量名 107 | Note: 108 | 链表头节点实际为链表头的下一个节点,链表头未使用,相当于哨兵 109 | **********************************************************/ 110 | #define list_head(list, type, member) list_entry((list)->next, type, member) 111 | 112 | /********************************************************** 113 | 获取链表尾节点对应的结构体变量地址 114 | list: 链表头指针 115 | type: 结构体类型名 116 | member: 结构体成员变量名 117 | **********************************************************/ 118 | #define list_tail(list, type, member) list_entry((list)->prev, type, member) 119 | 120 | /********************************************************** 121 | 返回链表下一个节点对应的结构体指针 122 | elm: 结构体变量指针 123 | type: 结构体类型名 124 | member: 结构体成员变量名(链表变量名) 125 | **********************************************************/ 126 | #define list_next(elm,type,member) list_entry((elm)->member.next, type, member) 127 | 128 | /* 返回上一个 */ 129 | #define list_prev(elm,type,member) list_entry((elm)->member.prev, type, member) 130 | 131 | /********************************************************** 132 | 遍历链表所有节点对应的结构体 133 | pos : 结构体指针 134 | type : 结构体类型名 135 | list : 链表头指针 136 | member : 结构体成员变量名(链表变量名) 137 | Note : 链表头未使用,因此遍历结束后,pos指向的不是有效的结构体地址 138 | **********************************************************/ 139 | #define list_for_each_entry(pos, type, list, member) \ 140 | for (pos = list_head(list, type, member); \ 141 | &pos->member != (list); \ 142 | pos = list_next(pos, type, member)) 143 | 144 | #define list_for_each_entry_reverse(pos, type, list, member) \ 145 | for (pos = list_tail(list, type, member); \ 146 | &pos->member != (list); \ 147 | pos = list_prev(pos, type, member)) 148 | 149 | //////////// 手工遍历 150 | /* 151 | #include 152 | struct list ls = LIST_HEAD_INIT(ls); 153 | //.... list_appent(...); 154 | 155 | struct list *p1, *p2; 156 | p2 = &ls; 157 | p1 = p2->next; 158 | printf("\nend %12lx, tail %12lx first %12lx, new %12lx\n", p2, p2->prev, p1, &pc->node); 159 | for (;p1 != p2; p1 = p1->next) { 160 | printf("\tpc %12lx [%12lx %12lx]\n", p1, p1->prev, p1->next); 161 | } 162 | */ 163 | /////////// 164 | 165 | #ifdef __cplusplus 166 | } 167 | #endif 168 | #endif /* __YH_LIST_H__ */ 169 | -------------------------------------------------------------------------------- /rtt.c: -------------------------------------------------------------------------------- 1 | /* include rtt1 */ 2 | #include "unprtt.h" 3 | #include "wrapfunc.h" 4 | #include 5 | #include 6 | 7 | int rtt_d_flag = 1; /* debug flag; can be set by caller */ 8 | 9 | /* 10 | * Calculate the RTO value based on current estimators: 11 | * smoothed RTT plus four times the deviation 12 | */ 13 | #define RTT_RTOCALC(ptr) ((ptr)->rtt_srtt + (4.0 * (ptr)->rtt_rttvar)) 14 | 15 | static float 16 | rtt_minmax(float rto) 17 | { 18 | if (rto < RTT_RXTMIN) 19 | rto = RTT_RXTMIN; 20 | else if (rto > RTT_RXTMAX) 21 | rto = RTT_RXTMAX; 22 | return(rto); 23 | } 24 | 25 | void 26 | rtt_init(struct rtt_info *ptr, uint8_t retry) 27 | { 28 | struct timeval tv; 29 | 30 | Gettimeofday(&tv, NULL); 31 | ptr->rtt_base = tv.tv_sec; /* # sec since 1/1/1970 at start */ 32 | 33 | ptr->rtt_retry = retry; 34 | ptr->rtt_rtt = 0; 35 | ptr->rtt_srtt = 0; 36 | ptr->rtt_rttvar = 0.75; 37 | ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr)); 38 | /* first RTO at (srtt + (4 * rttvar)) = 3 seconds */ 39 | } 40 | /* end rtt1 */ 41 | 42 | /* 43 | * Return the current timestamp. 44 | * Our timestamps are 32-bit integers that count milliseconds since 45 | * rtt_init() was called. 46 | */ 47 | 48 | /* include rtt_ts */ 49 | uint32_t 50 | rtt_ts(struct rtt_info *ptr) 51 | { 52 | uint32_t ts; 53 | struct timeval tv; 54 | 55 | Gettimeofday(&tv, NULL); 56 | ts = ((tv.tv_sec - ptr->rtt_base) * 1000) + (tv.tv_usec / 1000); 57 | return(ts); 58 | } 59 | 60 | void 61 | rtt_newpack(struct rtt_info *ptr) 62 | { 63 | ptr->rtt_nrexmt = 0; 64 | } 65 | 66 | int 67 | rtt_start(struct rtt_info *ptr) 68 | { 69 | return((int) (ptr->rtt_rto + 0.5)); /* round float to int */ 70 | /* 4return value can be used as: alarm(rtt_start(&foo)) */ 71 | } 72 | /* end rtt_ts */ 73 | 74 | /* 75 | * A response was received. 76 | * Stop the timer and update the appropriate values in the structure 77 | * based on this packet's RTT. We calculate the RTT, then update the 78 | * estimators of the RTT and its mean deviation. 79 | * This function should be called right after turning off the 80 | * timer with alarm(0), or right after a timeout occurs. 81 | */ 82 | 83 | /* include rtt_stop */ 84 | void 85 | rtt_stop(struct rtt_info *ptr, uint32_t ms) 86 | { 87 | double delta; 88 | 89 | ptr->rtt_rtt = ms / 1000.0; /* measured RTT in seconds */ 90 | 91 | /* 92 | * Update our estimators of RTT and mean deviation of RTT. 93 | * See Jacobson's SIGCOMM '88 paper, Appendix A, for the details. 94 | * We use floating point here for simplicity. 95 | */ 96 | 97 | delta = ptr->rtt_rtt - ptr->rtt_srtt; 98 | ptr->rtt_srtt += delta / 8; /* g = 1/8 */ 99 | 100 | if (delta < 0.0) 101 | delta = -delta; /* |delta| */ 102 | 103 | ptr->rtt_rttvar += (delta - ptr->rtt_rttvar) / 4; /* h = 1/4 */ 104 | 105 | ptr->rtt_rto = rtt_minmax(RTT_RTOCALC(ptr)); 106 | } 107 | /* end rtt_stop */ 108 | 109 | /* 110 | * A timeout has occurred. 111 | * Return -1 if it's time to give up, else return 0. 112 | */ 113 | 114 | /* include rtt_timeout */ 115 | int 116 | rtt_timeout(struct rtt_info *ptr) 117 | { 118 | ptr->rtt_rto *= 2; /* next RTO */ 119 | if (ptr->rtt_rto > RTT_MAXRTO) 120 | ptr->rtt_rto = RTT_MAXRTO; 121 | 122 | if (++ptr->rtt_nrexmt > ptr->rtt_retry) 123 | return(-1); /* time to give up for this packet */ 124 | return(0); 125 | } 126 | /* end rtt_timeout */ 127 | 128 | /* 129 | * Print debugging information on stderr, if the "rtt_d_flag" is nonzero. 130 | */ 131 | 132 | void 133 | rtt_debug(struct rtt_info *ptr) 134 | { 135 | if (rtt_d_flag == 0) 136 | return; 137 | 138 | fprintf(stderr, "\e[31mrtt = %.3f, srtt = %.3f, rttvar = %.3f, rto = %.3f\n\e[m", 139 | ptr->rtt_rtt, ptr->rtt_srtt, ptr->rtt_rttvar, ptr->rtt_rto); 140 | fflush(stderr); 141 | } 142 | -------------------------------------------------------------------------------- /sarudp_comm.c: -------------------------------------------------------------------------------- 1 | #include "sarudp_comm.h" 2 | 3 | static uint8_t ipv4lead[12] = { 4 | 0x0, 0x0, 0x0, 0x0, 5 | 0x0, 0x0, 0x0, 0x0, 6 | 0x0, 0x0, 0xff,0xff}; 7 | 8 | /* * 9 | * Not only compare the address and port also offers rbtree node sorting 10 | * */ 11 | inline int sockaddr_in6_cmp( 12 | struct sockaddr_in6 *p1, struct sockaddr_in6 *p2) 13 | { 14 | struct in6_addr *in1 = &p1->sin6_addr; /* only address is not port */ 15 | struct in6_addr *in2 = &p2->sin6_addr; 16 | 17 | if (p1->sin6_port == p2->sin6_port) { 18 | #if defined __USE_MISC || defined __USE_GNU 19 | /* #define __in6_u.__u6_addr32 s6_addr32 20 | * in the /usr/include/netinet/in.h */ 21 | if (in1->s6_addr32[0] == in2->s6_addr32[0]) { 22 | if (in1->s6_addr32[1] == in2->s6_addr32[1]) { 23 | if (in1->s6_addr32[2] == in2->s6_addr32[2]) { 24 | return (in1->s6_addr32[3] - in2->s6_addr32[3]); 25 | } return (in1->s6_addr32[2] - in2->s6_addr32[2]); 26 | } return (in1->s6_addr32[1] - in2->s6_addr32[1]); 27 | } return (in1->s6_addr32[0] - in2->s6_addr32[0]); 28 | #else 29 | return memcmp(in1, in2, sizeof(struct in6_addr)); 30 | #endif 31 | } return p1->sin6_port - p2->sin6_port; 32 | } 33 | inline int sockaddr_in4_cmp( 34 | struct sockaddr_in *p1, struct sockaddr_in *p2) 35 | { 36 | if (p1->sin_port == p2->sin_port) { 37 | return p1->sin_addr.s_addr - p2->sin_addr.s_addr; 38 | } return p1->sin_port - p2->sin_port; 39 | } 40 | 41 | inline int search_cache_key_in6_addr_seq_cmp( 42 | rb_key_cache_t *r1, rb_key_cache_t *r2) 43 | { 44 | #ifndef promiscuous_mode 45 | if (r1->sid == r2->sid) 46 | return (r1->seq - r2->seq); 47 | return (r1->sid - r2->sid); 48 | #else 49 | int ret = sockaddr_in6_cmp(&r1->destaddr.addr6, &r2->destaddr.addr6); 50 | 51 | if (r1->sid == r2->sid) { 52 | if (0 == ret) { 53 | return (r1->seq - r2->seq); 54 | } return (ret); 55 | } return (r1->sid - r2->sid); 56 | #endif 57 | } 58 | 59 | inline const void* cache_getkey(const void *pnode) 60 | { 61 | return rb_entry(pnode, cache_t, rbn); 62 | } 63 | inline const int search_cache_cmp( 64 | const void * nodes_cache, const void* rb_search_key) 65 | { 66 | rb_key_cache_t *kk = (rb_key_cache_t*) rb_search_key; 67 | cache_t *cache = (cache_t*) nodes_cache; 68 | 69 | rb_key_cache_t con; 70 | memcpy(&con.destaddr, &cache->frame.srcaddr, sizeof(SAUN)); 71 | con.destlen = cache->frame.srclen; 72 | con.seq = cache->frame.recvhdr.seq; 73 | con.sid = cache->frame.recvhdr.sid; 74 | 75 | return search_cache_key_in6_addr_seq_cmp(&con, kk); 76 | } 77 | inline struct rb_node * rb_search(rb_root_t *root, const void *key) 78 | { 79 | struct rb_node *node = root->rb_node; 80 | 81 | while (node) 82 | { 83 | int result = search_cache_cmp(rb_entry(node, cache_t, rbn), key); 84 | 85 | if (result < 0) 86 | node = node->rb_left; 87 | else if (result > 0) 88 | node = node->rb_right; 89 | else 90 | return node; 91 | } 92 | return 0; 93 | } 94 | inline int insert_cache_in6_addr_seq_cmp(cache_t *r1, cache_t *r2) 95 | { 96 | #ifndef promiscuous_mode 97 | if (r1->frame.recvhdr.sid == r2->frame.recvhdr.sid) 98 | return (r1->frame.recvhdr.seq - r2->frame.recvhdr.seq); 99 | return (r1->frame.recvhdr.sid - r2->frame.recvhdr.sid); 100 | #else 101 | int ret = 102 | sockaddr_in6_cmp(&r1->frame.srcaddr.addr6, &r2->frame.srcaddr.addr6); 103 | 104 | if (r1->frame.recvhdr.sid == r2->frame.recvhdr.sid) { 105 | if (0 == ret) { 106 | return (r1->frame.recvhdr.seq - r2->frame.recvhdr.seq); 107 | } return (ret); 108 | } return (r1->frame.recvhdr.sid - r2->frame.recvhdr.sid); 109 | 110 | #endif 111 | } 112 | 113 | inline const int insert_cache_cmp(const void * node1, const void* node2) 114 | { 115 | cache_t *k1 = (cache_t*) node1; 116 | cache_t *k2 = (cache_t*) node2; 117 | 118 | return insert_cache_in6_addr_seq_cmp(k1, k2); 119 | } 120 | inline int rb_insert(struct rb_root *root, struct rb_node *new_node) 121 | { 122 | struct rb_node **now = &(root->rb_node); 123 | struct rb_node *parent = 0; 124 | 125 | /* Figure out where to put now node */ 126 | while (*now) 127 | { 128 | //int result = insert_cache_cmp(root->getkey(*now), root->getkey(new_node)); 129 | int result = insert_cache_cmp(rb_entry(*now, cache_t, rbn), 130 | rb_entry(new_node, cache_t, rbn)); 131 | 132 | parent = *now; 133 | 134 | if (result < 0) 135 | now = &((*now)->rb_left); 136 | else if (result > 0) 137 | now = &((*now)->rb_right); 138 | else 139 | return -1; /* the key is already exists */ 140 | } 141 | 142 | /* Add new node and rebalance tree. */ 143 | rb_link_node(new_node, parent, now); 144 | rb_insert_color(new_node, root); 145 | 146 | return 0; 147 | } 148 | 149 | void su_get_ip_port(SAUN *s, char *ipbuff, int len, int *port) 150 | { 151 | if (s->sfamily == PF_INET) { 152 | inet_ntop(PF_INET, &s->s4addr, ipbuff, len); 153 | if (port) 154 | *port = ntohs(s->s4port); 155 | } else if (s->sfamily == PF_INET6) { 156 | if (memcmp(s->addr6.sin6_addr.s6_addr, ipv4lead, 12) == 0) 157 | inet_ntop(PF_INET, &s->s6addr.s6_addr[12], ipbuff,len); 158 | else 159 | inet_ntop(PF_INET6,&s->s6addr.s6_addr, ipbuff, len); 160 | if (port) 161 | *port = ntohs(s->s6port); 162 | } else { 163 | snprintf(ipbuff, len, "su_get_ip_port unknown protocol"); 164 | if (port) 165 | *port = -1; 166 | } 167 | } 168 | void su_get_ip_port_f(SAUN *s, char *ipbuff, int len, int *port) 169 | { 170 | if (s->sfamily == PF_INET) { 171 | inet_ntop(PF_INET, &s->s4addr, ipbuff, len); 172 | if (port) 173 | *port = ntohs(s->s4port); 174 | } else if (s->sfamily == PF_INET6) { 175 | inet_ntop(PF_INET6,&s->s6addr.s6_addr, ipbuff, len); 176 | if (port) 177 | *port = ntohs(s->s6port); 178 | } else { 179 | snprintf(ipbuff, len, "su_get_ip_port_f unknown protocol"); 180 | if (port) 181 | *port = -1; 182 | } 183 | } 184 | void su_get_ip(SAUN *s, char *ipbuff, int len) 185 | { 186 | if (s->sfamily == PF_INET) { 187 | inet_ntop(PF_INET, &s->s4addr, ipbuff, len); 188 | } else if (s->sfamily == PF_INET6) { 189 | if (memcmp(s->addr6.sin6_addr.s6_addr, ipv4lead, 12) == 0) 190 | inet_ntop(PF_INET, &s->s6addr.s6_addr[12], ipbuff,len); 191 | else 192 | inet_ntop(PF_INET6,&s->s6addr.s6_addr, ipbuff, len); 193 | } else { 194 | snprintf(ipbuff, len, "su_get_ip unknown protocol"); 195 | } 196 | } 197 | void su_get_ip_f(SAUN *s, char *ipbuff, int len) 198 | { 199 | if (s->sfamily == PF_INET) { 200 | inet_ntop(PF_INET, &s->s4addr, ipbuff, len); 201 | } else if (s->sfamily == PF_INET6) { 202 | inet_ntop(PF_INET6,&s->s6addr.s6_addr, ipbuff, len); 203 | } else { 204 | snprintf(ipbuff, len, "su_get_ip_f unknown protocol"); 205 | } 206 | } 207 | void su_get_port(SAUN *s, int *port) 208 | { 209 | if (!port) 210 | return; 211 | if (s->sfamily == PF_INET) { 212 | *port = ntohs(s->s4port); 213 | } else if (s->sfamily == PF_INET6) { 214 | *port = ntohs(s->s6port); 215 | } else { 216 | *port = -1; 217 | } 218 | } 219 | 220 | void showaddr6_8_16(SA6 *ps) 221 | { 222 | log_msg("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", 223 | ps->sin6_addr.s6_addr[0], ps->sin6_addr.s6_addr[1], 224 | ps->sin6_addr.s6_addr[2], ps->sin6_addr.s6_addr[3], 225 | ps->sin6_addr.s6_addr[4], ps->sin6_addr.s6_addr[5], 226 | ps->sin6_addr.s6_addr[6], ps->sin6_addr.s6_addr[7], 227 | ps->sin6_addr.s6_addr[8], ps->sin6_addr.s6_addr[9], 228 | ps->sin6_addr.s6_addr[10], ps->sin6_addr.s6_addr[11], 229 | ps->sin6_addr.s6_addr[12], ps->sin6_addr.s6_addr[13], 230 | ps->sin6_addr.s6_addr[14], ps->sin6_addr.s6_addr[15]); 231 | } 232 | void showaddr6_16_8(SA6 *ps) 233 | { 234 | log_msg("%04x %04x %04x %04x %04x %04x %04x %04x", 235 | ps->sin6_addr.s6_addr16[0], 236 | ps->sin6_addr.s6_addr16[1], 237 | ps->sin6_addr.s6_addr16[2], 238 | ps->sin6_addr.s6_addr16[3], 239 | ps->sin6_addr.s6_addr16[4], 240 | ps->sin6_addr.s6_addr16[5], 241 | ps->sin6_addr.s6_addr16[6], 242 | ps->sin6_addr.s6_addr16[7]); 243 | } 244 | void showaddr6_32_4(SA6 *ps) 245 | { 246 | log_msg("%08x %08x %08x %08x", 247 | ps->sin6_addr.s6_addr32[0], 248 | ps->sin6_addr.s6_addr32[1], 249 | ps->sin6_addr.s6_addr32[2], 250 | ps->sin6_addr.s6_addr32[3]); 251 | } 252 | 253 | -------------------------------------------------------------------------------- /sarudp_comm.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_SARUDP_COMM_H__ 2 | #define __YH_SARUDP_COMM_H__ 3 | 4 | /* common use */ 5 | 6 | #include "unprtt.h" 7 | #include "wrapfunc.h" 8 | #include "list.h" 9 | 10 | #include "yherror.h" 11 | #include "yhevent.h" 12 | #include "yhrbtree.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #define REALDATAMAX 1024 /* datagram max size */ 25 | #define CACHETIMEOUT 90 /* reliable request-result cached seconds */ 26 | 27 | #define ColorRed "\e[31m" 28 | #define ColorGre "\e[32m" 29 | #define ColorYel "\e[33m" 30 | #define ColorBlue "\e[34m" 31 | #define ColorEnd "\e[m" 32 | 33 | #pragma pack(push) 34 | #pragma pack(1) 35 | /* protocol header */ 36 | typedef struct hdr { 37 | /* packet action */ 38 | #define SU_SYN 0xff /* request */ 39 | #define SU_ACK 0xfe /* respnose */ 40 | uint8_t act; /* protocol action */ 41 | 42 | /* packet type */ 43 | #define SU_ORDINARY 0 /* ordinary, foreign host Don't need to reply */ 44 | #define SU_RELIABLE 1 /* reliable, foreign host Must reply */ 45 | uint8_t type; /* protocol type */ 46 | 47 | uint16_t sid; /* service id */ 48 | uint32_t seq; /* sequence # */ 49 | uint32_t ts; /* timestamp when sent */ 50 | } suhdr_t; 51 | #pragma pack(pop) 52 | 53 | typedef struct sockaddr SA; 54 | typedef struct sockaddr_in SA4; 55 | typedef struct sockaddr_in6 SA6; 56 | 57 | typedef union { 58 | SA addr; 59 | #define sfamily addr.sa_family 60 | SA4 addr4; 61 | #define s4addr addr4.sin_addr 62 | #define s4port addr4.sin_port 63 | SA6 addr6; 64 | #define s6addr addr6.sin6_addr 65 | #define s6port addr6.sin6_port 66 | } SAUN; 67 | 68 | /* recv storage data, list node */ 69 | typedef struct frames { 70 | struct list node; 71 | SAUN srcaddr; 72 | socklen_t srclen; 73 | suhdr_t recvhdr; 74 | int len; 75 | uint8_t data[]; 76 | } frames_t; 77 | 78 | typedef struct cache { 79 | time_t ts; 80 | struct rb_node rbn; 81 | frames_t frame; 82 | } cache_t; 83 | 84 | typedef struct rb_key_cache { 85 | SAUN destaddr; 86 | socklen_t destlen; 87 | uint16_t sid; 88 | uint32_t seq; 89 | } rb_key_cache_t; 90 | 91 | inline int sockaddr_in6_cmp( struct sockaddr_in6 *p1, struct sockaddr_in6 *p2); 92 | inline int sockaddr_in4_cmp( struct sockaddr_in *p1, struct sockaddr_in *p2); 93 | inline const void* cache_getkey(const void *pnode); 94 | 95 | inline int search_cache_key_in6_addr_seq_cmp( rb_key_cache_t *r1, rb_key_cache_t *r2); 96 | inline int insert_cache_in6_addr_seq_cmp(cache_t *r1, cache_t *r2); 97 | 98 | inline const int search_cache_cmp( const void * nodes_cache, const void* rb_search_key); 99 | inline const int insert_cache_cmp(const void * node1, const void* node2); 100 | 101 | inline struct rb_node * rb_search(rb_root_t *root, const void *key); 102 | inline int rb_insert(struct rb_root *root, struct rb_node *new_node); 103 | 104 | void showaddr6_8_16(SA6 *ps); 105 | void showaddr6_16_8(SA6 *ps); 106 | void showaddr6_32_4(SA6 *ps); 107 | 108 | 109 | void su_get_ip_port(SAUN *s, char *ipbuff, int len, int *port); 110 | void su_get_ip(SAUN *s, char *ipbuff, int len); 111 | void su_get_port(SAUN *s, int *port); 112 | 113 | void su_get_ip_port_f(SAUN *s, char *ipbuff, int len, int *port); 114 | void su_get_ip_f(SAUN *s, char *ipbuff, int len); 115 | 116 | #endif /* __YH_SARUDP_COMM_H__ */ 117 | -------------------------------------------------------------------------------- /sarudp_peer.c: -------------------------------------------------------------------------------- 1 | #include "sarudp_peer.h" 2 | 3 | #include "yherror.h" 4 | #include "yhevent.h" 5 | #include "yhtime.h" 6 | #include "yhrbtree.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | pthread_mutex_t emutex = PTHREAD_MUTEX_INITIALIZER; 14 | em_t * sugem = 0; 15 | char rejectbuff[1024*10] = {0}; 16 | 17 | static inline int reliable_ack___hold(su_peer_t *psar, frames_t *frame) 18 | { 19 | cache_t * newack; 20 | newack = calloc(1, sizeof(cache_t)); 21 | if (newack == 0) { 22 | errno = ENOBUFS; 23 | return -1; 24 | } 25 | time(&newack->ts); 26 | memcpy(&newack->frame, frame, sizeof(frames_t)); 27 | newack->frame.len = -1; 28 | 29 | /* Adding associated */ 30 | if (rb_insert(&psar->rbackcache, &newack->rbn) < 0) { 31 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 32 | char ipbuff[INET6_ADDRSTRLEN]; 33 | int port; 34 | #ifdef SU_DEBUG_IP6FULL 35 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 36 | #else 37 | su_get_ip_port(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 38 | #endif 39 | log_msg("peer %x time %u key(%s:%d:%u:%u)" 40 | ColorRed " !ACK cache %p failed" ColorEnd, 41 | psar, newack->ts, ipbuff, port, 42 | newack->frame.recvhdr.sid, newack->frame.recvhdr.seq, newack); 43 | #endif 44 | free(newack); 45 | errno = EALREADY; 46 | return -1; 47 | } else { 48 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 49 | char ipbuff[INET6_ADDRSTRLEN]; 50 | int port; 51 | #ifdef SU_DEBUG_IP6FULL 52 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 53 | #else 54 | su_get_ip_port(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 55 | #endif 56 | log_msg("peer %x time %u key(%s:%d:%u:%u)" 57 | ColorRed " !ACK cache %p" ColorEnd, 58 | psar, newack->ts, ipbuff, port, 59 | newack->frame.recvhdr.sid, newack->frame.recvhdr.seq, newack); 60 | 61 | #endif 62 | list_append(&psar->lsackcache, &newack->frame.node); 63 | } 64 | return 0; 65 | } 66 | 67 | static inline int reliable_ack___save (su_peer_t *psar, 68 | const void *outbuff, int outbytes) 69 | { 70 | /* Construct search key */ 71 | rb_key_cache_t key; 72 | memcpy(&key.destaddr, & psar->nowsynframe->srcaddr, sizeof(SAUN)); 73 | key.destlen = psar->nowsynframe->srclen; 74 | key.seq = psar->nowsynframe->recvhdr.seq; 75 | key.sid = psar->nowsynframe->recvhdr.sid; 76 | 77 | struct rb_node *cachenode; 78 | cache_t *cache; 79 | 80 | /* If is no reply content, only replace len value, don't replace node 81 | * If have a content, must allocating and replacing new node */ 82 | if (outbuff == 0 && outbytes == 0) { 83 | if ((cachenode = rb_search(&psar->rbackcache, &key))) { 84 | cache = rb_entry(cachenode, cache_t, rbn); 85 | cache->frame.len = 0; 86 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 87 | char ipbuff[INET6_ADDRSTRLEN]; 88 | int port; 89 | #ifdef SU_DEBUG_IP6FULL 90 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 91 | #else 92 | su_get_ip_port(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 93 | #endif 94 | log_msg("peer %x time %u key(%s:%d:%u:%u) " 95 | ColorRed "+ACK cache %p" ColorEnd , 96 | psar, cache->ts, ipbuff, port, 97 | cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); 98 | #endif 99 | return 0; 100 | } 101 | errno = ENOKEY; 102 | return -1; 103 | } 104 | 105 | cache_t * newack; 106 | newack = calloc(1, sizeof(cache_t) + outbytes); 107 | if (newack == 0) { 108 | errno = ENOBUFS; 109 | return -1; 110 | } 111 | 112 | /* Construct a new node */ 113 | memcpy(&newack->frame, psar->nowsynframe, sizeof(frames_t)); 114 | memcpy(newack->frame.data, outbuff, outbytes); 115 | newack->frame.len = outbytes; 116 | 117 | /* Find and replace the hold node */ 118 | if ((cachenode = rb_search(&psar->rbackcache, &key))) { 119 | rb_replace_node(cachenode, &newack->rbn, &psar->rbackcache); 120 | cache = rb_entry(cachenode, cache_t, rbn); 121 | newack->ts = cache->ts; 122 | list_remove(&cache->frame.node); 123 | list_append(&psar->lsackcache, &newack->frame.node); 124 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 125 | char ipbuff[INET6_ADDRSTRLEN]; 126 | int port; 127 | #ifdef SU_DEBUG_IP6FULL 128 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 129 | #else 130 | su_get_ip_port(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 131 | #endif 132 | log_msg("peer %x time %u key(%s:%d:%u:%u) " 133 | ColorRed "+ACK cache %p Swap %p" ColorEnd , 134 | psar, newack->ts, ipbuff, port, 135 | frame->recvhdr.sid, frame->recvhdr.seq, cache, newack); 136 | #endif 137 | free(cache); 138 | return 0; 139 | } 140 | free(newack); 141 | errno = ENOKEY; 142 | return -1; 143 | } 144 | 145 | static inline void reliable_ack_unsave (su_peer_t *psar) 146 | { 147 | time_t nowtime; 148 | 149 | cache_t *frees, *cache = container_of 150 | ( list_head(&psar->lsackcache, frames_t, node), cache_t, frame ); 151 | 152 | time(&nowtime); 153 | 154 | while ( &psar->lsackcache != &cache->frame.node ) { 155 | if ( abs(nowtime - cache->ts) < CACHETIMEOUT ) break; 156 | frees = cache; 157 | cache = container_of 158 | ( list_next(&cache->frame, frames_t, node), cache_t, frame ); 159 | 160 | /* Disconnect associated */ 161 | list_remove(&frees->frame.node); 162 | rb_erase(&frees->rbn, &psar->rbackcache); 163 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 164 | char ipbuff[INET6_ADDRSTRLEN]; 165 | int port; 166 | #ifdef SU_DEBUG_IP6FULL 167 | su_get_ip_port_f(&frees->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 168 | #else 169 | su_get_ip_port(&frees->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 170 | #endif 171 | LOG_MSG("peer %x time %u key(%s:%d:%u:%u)" ColorRed " -ACK cache %p" ColorEnd, 172 | psar, frees->ts, ipbuff, ntohs(port), 173 | frees->frame.recvhdr.sid, frees->frame.recvhdr.seq, frees); 174 | #endif 175 | free(frees); 176 | } 177 | } 178 | 179 | static void su_peer_list_empty(su_peer_t *psar, struct list *l) 180 | { 181 | frames_t *realnode; 182 | struct list *node = l->next; 183 | 184 | while ( node != l ) { 185 | list_remove(node); 186 | realnode = container_of(node, frames_t, node); 187 | node = node->next; 188 | free(realnode); 189 | #ifdef SU_DEBUG_LIST 190 | LOG_MSG("peer %x free frames_t node " ColorRed "%p" ColorEnd, psar, realnode); 191 | #endif 192 | } 193 | } 194 | 195 | void request_handle(su_peer_t *psar) 196 | { 197 | frames_t *frame = psar->nowsynframe; 198 | suhdr_t *phdr = &frame->recvhdr; 199 | 200 | switch (phdr->type) { 201 | case SU_RELIABLE: 202 | if (psar->reliable_request_handle) { 203 | psar->reliable_request_handle(psar, (char*)frame->data, frame->len); 204 | } break; 205 | case SU_ORDINARY: 206 | if (psar->ordinary_request_handle) { 207 | psar->ordinary_request_handle(psar, (char*)frame->data, frame->len); 208 | } break; 209 | default: 210 | LOG_MSG("peer %x recv request type unknown %d", psar, phdr->type); 211 | return; 212 | } 213 | } 214 | 215 | static void *thread_request_handle(void *v) 216 | { 217 | su_peer_t *psar = (su_peer_t*)v; 218 | struct list *synnode; 219 | frames_t *frame; 220 | 221 | int ret; 222 | struct timespec abstime = {0}; 223 | 224 | for (;psar->run;) { 225 | pthread_mutex_lock(&psar->lock); 226 | while ((synnode = psar->synrecvls.next) == &psar->synrecvls) { 227 | maketimeout_seconds(&abstime, 1); 228 | ret = pthread_cond_timedwait(&psar->syncond, &psar->lock, &abstime); 229 | if (!psar->run) { 230 | pthread_mutex_unlock(&psar->lock); 231 | goto quit; 232 | } 233 | if ( ret == ETIMEDOUT ) { 234 | pthread_mutex_lock(&psar->cachelock); 235 | reliable_ack_unsave(psar); 236 | pthread_mutex_unlock(&psar->cachelock); 237 | } 238 | } 239 | list_remove(synnode); 240 | pthread_mutex_unlock(&psar->lock); 241 | 242 | // TODO: Have a request 243 | frame = container_of(synnode, frames_t, node); 244 | 245 | rb_key_cache_t key; 246 | memcpy(&key.destaddr, &frame->srcaddr, sizeof(SAUN)); 247 | key.destlen = frame->srclen; 248 | key.seq = frame->recvhdr.seq; 249 | key.sid = frame->recvhdr.sid; 250 | 251 | struct rb_node *cachenode; 252 | cache_t *cache; 253 | 254 | pthread_mutex_lock(&psar->cachelock); 255 | reliable_ack_unsave(psar); 256 | if (frame->recvhdr.type == SU_RELIABLE && 257 | (cachenode = rb_search(&psar->rbackcache, &key))) { 258 | cache = rb_entry(cachenode, cache_t, rbn); 259 | 260 | if (cache->frame.len == -1) { 261 | #ifdef SU_DEBUG_RBTREE 262 | char ipbuff[INET6_ADDRSTRLEN]; 263 | int port; 264 | #ifdef SU_DEBUG_IP6FULL 265 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 266 | #else 267 | su_get_ip_port(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 268 | #endif 269 | log_msg("peer %x time %u key(%s:%d:%u:%u)" 270 | ColorRed " 0ACK cache %p" ColorEnd, 271 | psvr, cache->ts, ipbuff, port, 272 | cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); 273 | #endif 274 | pthread_mutex_unlock(&psar->cachelock); 275 | free(frame); 276 | continue; 277 | } 278 | 279 | #ifdef SU_DEBUG_RBTREE 280 | char ipbuff[INET6_ADDRSTRLEN]; 281 | int port; 282 | #ifdef SU_DEBUG_IP6FULL 283 | su_get_ip_port_f(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 284 | #else 285 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 286 | #endif 287 | log_msg("peer %x time %u key(%s:%d:%u:%u)" ColorRed " @ACK cache %p" ColorEnd, 288 | psar,cache->ts, ipbuff, port, 289 | cache->frame.recvhdr.sid, 290 | cache->frame.recvhdr.seq, 291 | cache); 292 | #endif 293 | 294 | struct iovec iovsend[2] = {{0}}; 295 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 296 | 297 | frame->recvhdr.act = SU_ACK; 298 | msgsend.msg_name = (void*)&cache->frame.srcaddr; 299 | msgsend.msg_namelen = cache->frame.srclen; 300 | msgsend.msg_iov = &iovsend[0]; 301 | msgsend.msg_iovlen = 2; 302 | 303 | iovsend[0].iov_base = &frame->recvhdr; 304 | iovsend[0].iov_len = sizeof(suhdr_t); 305 | iovsend[1].iov_base = (void*)cache->frame.data; /* get the cache results */ 306 | iovsend[1].iov_len = cache->frame.len; 307 | 308 | if (sendmsg(psar->fd, &msgsend, 0) != sizeof(suhdr_t) + cache->frame.len) { 309 | char ipbuff[INET6_ADDRSTRLEN]; 310 | int port; 311 | #ifdef SU_DEBUG_IP6FULL 312 | su_get_ip_port_f(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 313 | #else 314 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 315 | #endif 316 | err_ret("retransmit sendmsg %s:%d:%u:%u:%u error", 317 | ipbuff, port, frame->recvhdr.sid, 318 | frame->recvhdr.seq, frame->recvhdr.ts); 319 | } 320 | #ifdef SU_DEBUG_PEER_RESEND 321 | else { 322 | char ipbuff[INET6_ADDRSTRLEN]; 323 | int port; 324 | #ifdef SU_DEBUG_IP6FULL 325 | su_get_ip_port_f(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 326 | #else 327 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 328 | #endif 329 | log_msg("retransmit sendmsg %s:%d:%u:%u:%u", 330 | ipbuff, port, frame->recvhdr.sid, 331 | frame->recvhdr.seq, frame->recvhdr.ts); 332 | } 333 | #endif 334 | pthread_mutex_unlock(&psar->cachelock); 335 | free(frame); 336 | continue; 337 | } else { 338 | if (reliable_ack___hold(psar, frame) < 0) { 339 | err_ret("peer %x reliable_ack___hold error", psar); 340 | pthread_mutex_unlock(&psar->cachelock); 341 | free(frame); 342 | continue; 343 | } 344 | } 345 | 346 | psar->nowsynframe = frame; 347 | request_handle(psar); 348 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 349 | log_msg("peer %x delete syn "ColorRed"%p"ColorEnd" seq %d datagram len %d", 350 | psar, frame, frame->recvhdr.seq, frame->len); 351 | #endif 352 | free(frame); 353 | psar->nowsynframe = 0; 354 | pthread_mutex_unlock(&psar->cachelock); 355 | } 356 | 357 | quit: 358 | return (void*)0; 359 | } 360 | 361 | static int su_peer_thread_install(su_peer_t *psar) 362 | { 363 | pthread_attr_t attr; 364 | 365 | psar->run = 0; 366 | psar->reliable_request_handle = 0; 367 | psar->ordinary_request_handle = 0; 368 | 369 | pthread_attr_init(&attr); 370 | pthread_attr_setstacksize(&attr, 1024*1024); 371 | 372 | errno = pthread_create(&psar->tid, &attr, thread_request_handle, psar); 373 | if (errno != 0) { 374 | pthread_attr_destroy(&attr); 375 | return (-1); 376 | } 377 | pthread_attr_destroy(&attr); 378 | psar->run = 1; 379 | return 0; 380 | } 381 | 382 | static int su_peer_thread_uninstall(su_peer_t *psar) 383 | { 384 | void *ret; 385 | 386 | psar->run = 0; 387 | errno = pthread_join(psar->tid, &ret); 388 | if (errno != 0) 389 | err_sys("peer %x can't join with thread %x error"); 390 | log_msg("peer %x join with thread %x code %d", psar, psar->tid, ret); 391 | return 0; 392 | } 393 | 394 | void su_peer_reliable_request_handle_install(su_peer_t *psar, 395 | cb_su_peer_receiver_t* reliable_request_handle) 396 | { 397 | pthread_mutex_lock(&psar->lock); 398 | psar->reliable_request_handle = reliable_request_handle; 399 | pthread_mutex_unlock(&psar->lock); 400 | } 401 | 402 | void su_peer_ordinary_request_handle_install(su_peer_t *psar, 403 | cb_su_peer_receiver_t* ordinary_request_handle) 404 | { 405 | pthread_mutex_lock(&psar->lock); 406 | psar->ordinary_request_handle = ordinary_request_handle; 407 | pthread_mutex_unlock(&psar->lock); 408 | } 409 | 410 | void su_peer_reliable_request_handle_uninstall(su_peer_t *psar) 411 | { 412 | pthread_mutex_lock(&psar->lock); 413 | psar->reliable_request_handle = 0; 414 | pthread_mutex_unlock(&psar->lock); 415 | } 416 | 417 | void su_peer_ordinary_request_handle_uninstall(su_peer_t *psar) 418 | { 419 | pthread_mutex_lock(&psar->lock); 420 | psar->ordinary_request_handle = 0; 421 | pthread_mutex_unlock(&psar->lock); 422 | } 423 | 424 | static void handle_su_peer_recv(fe_t * fe) 425 | { 426 | int ret, port; 427 | char ipbuff[INET6_ADDRSTRLEN]; 428 | SAUN saddr; 429 | socklen_t socklen; 430 | su_peer_t *psar = container_of(fe, su_peer_t, fe); 431 | struct iovec iovrecv[2] = {{0}}; /* assumed init to 0 */ 432 | struct msghdr msgrecv = {0}; /* assumed init to 0 */ 433 | frames_t *frame; 434 | recvagain: 435 | socklen = psar->destlen; 436 | frame = calloc(1, sizeof(frames_t) + REALDATAMAX); 437 | if (frame == 0) { 438 | errno = ENOBUFS; // ENOMEM 439 | log_msg("peer %x ENOBUFS", psar); 440 | /* reject datagram */ 441 | ret = recvfrom(fe->fd, rejectbuff, sizeof(rejectbuff), 0, (SA*)&saddr, &socklen); 442 | if (ret < 0 && errno == EAGAIN) { 443 | return; 444 | } 445 | #ifdef SU_DEBUG_PEER_RECV 446 | switch (saddr.sfamily) { 447 | case PF_INET: 448 | case PF_INET6: 449 | #ifdef SU_DEBUG_IP6FULL 450 | su_get_ip_port_f(&saddr, ipbuff, sizeof(ipbuff), &port); 451 | #else 452 | su_get_ip_port(&saddr, ipbuff, sizeof(ipbuff), &port); 453 | #endif 454 | break; 455 | default: 456 | log_msg("peer %x reject unknown protocol raw bytes %d", psar, ret); 457 | free(frame); 458 | goto recvagain; 459 | }; 460 | ERR_RET("peer %x recv %s:%d bytes %d, but reject datas", 461 | psar, ipbuff, port, ret); 462 | #endif 463 | return; 464 | } 465 | 466 | frame->srclen = psar->destlen; 467 | 468 | msgrecv.msg_name = & frame->srcaddr; 469 | msgrecv.msg_namelen = frame->srclen; 470 | msgrecv.msg_iov = iovrecv; 471 | msgrecv.msg_iovlen = 2; 472 | 473 | iovrecv[0].iov_base = & frame->recvhdr; 474 | iovrecv[0].iov_len = sizeof(suhdr_t); 475 | iovrecv[1].iov_base = frame->data; 476 | iovrecv[1].iov_len = REALDATAMAX; 477 | 478 | if ((ret = recvmsg(fe->fd, &msgrecv, 0)) < 0) { 479 | if (ret < 0 && errno == EAGAIN) { 480 | free(frame); 481 | return; 482 | } 483 | ERR_RET("recvmsg error"); 484 | } 485 | 486 | switch (frame->srcaddr.sfamily) { 487 | case PF_INET: 488 | case PF_INET6: 489 | #ifdef SU_DEBUG_IP6FULL 490 | su_get_ip_port_f(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 491 | #else 492 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 493 | #endif 494 | break; 495 | default: 496 | log_msg("peer %x reject unknown protocol type %d raw bytes %d", 497 | psar, frame->srcaddr.sfamily, ret); 498 | free(frame); 499 | goto recvagain; 500 | }; 501 | 502 | #ifdef SU_DEBUG_PEER_RECV 503 | log_msg("peer %x recv %s:%d raw bytes %d", psar, ipbuff, port, ret); 504 | #endif 505 | 506 | if (ret < sizeof(suhdr_t)) { 507 | #ifdef SU_DEBUG_PEER_RECV 508 | errno = EBADMSG; 509 | err_ret("peer %x recv %s:%d raw bytes %d less than the protocol header %d", psar, 510 | ipbuff, port, ret, sizeof(suhdr_t)); 511 | #endif 512 | free(frame); 513 | goto recvagain; 514 | } 515 | 516 | suhdr_t *r = &frame->recvhdr; 517 | uint8_t act = r->act; 518 | uint8_t type = r->type; 519 | 520 | frame->len = ret - sizeof(suhdr_t); 521 | 522 | SAUN *psrc, *pdst; 523 | psrc = &frame->srcaddr; // foreign host 524 | pdst = &psar->destaddr; // localhost 525 | 526 | #ifndef promiscuous_mode 527 | /* Filter: Check address and port 528 | * compare datagram source and peer destination */ 529 | if ( (pdst->sfamily == PF_INET6 && 530 | sockaddr_in6_cmp(&psrc->addr6, &pdst->addr6 ) != 0) 531 | || (pdst->sfamily == PF_INET && 532 | sockaddr_in4_cmp(&psrc->addr4, &pdst->addr4 ) != 0) ){ 533 | #ifdef SU_DEBUG_PEER_RECV 534 | log_msg(ColorYel"peer %x reject act[0x%02x] from %s:%d datagram len %d"ColorEnd, 535 | act, psar, ipbuff, port, frame->len); 536 | #endif 537 | free(frame); 538 | goto recvagain; 539 | } 540 | #endif /* #ifndef promiscuous_mode */ 541 | 542 | pthread_mutex_lock(&psar->lock); 543 | if (act == SU_SYN && frame->len > 0) { 544 | if (!psar->run) { 545 | log_msg("peer %x thread handle no run"); 546 | pthread_mutex_unlock(&psar->lock); 547 | free(frame); 548 | goto recvagain; 549 | } 550 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 551 | log_msg("peer %x append syn "ColorRed"%p"ColorEnd" seq %d datagram len %d", 552 | psar, frame, r->seq, frame->len); 553 | #endif 554 | list_append(&psar->synrecvls, &frame->node); 555 | pthread_mutex_unlock(&psar->lock); 556 | pthread_cond_broadcast(&psar->syncond); 557 | goto recvagain; 558 | } else if (act == SU_ACK && type == SU_RELIABLE) { 559 | #ifdef promiscuous_mode 560 | /* Filter: receive response from self request */ 561 | if ( (pdst->sfamily == PF_INET6 && 562 | sockaddr_in6_cmp(&psrc->addr6, &pdst->addr6 ) != 0) 563 | || (pdst->sfamily == PF_INET && 564 | sockaddr_in4_cmp(&psrc->addr4, &pdst->addr4 ) != 0) ){ 565 | #ifdef SU_DEBUG_PEER_RECV 566 | log_msg(ColorYel "peer %x reject ack from %s:%d datagram len %d" ColorEnd, psar, 567 | ipbuff, port, frame->len); 568 | #endif 569 | pthread_mutex_unlock(&psar->lock); 570 | free(frame); 571 | goto recvagain; 572 | } 573 | #endif /* #ifdef promiscuous_mode */ 574 | if (psar->ackwaitnum <= 0) { 575 | pthread_mutex_unlock(&psar->lock); 576 | free(frame); 577 | goto recvagain; 578 | } 579 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 580 | log_msg("peer %x append ack "ColorRed"%p"ColorEnd" seq %d datagram len %d", 581 | psar, frame, r->seq, frame->len); 582 | #endif 583 | list_append(&psar->ackrecvls, &frame->node); 584 | pthread_mutex_unlock(&psar->lock); 585 | pthread_cond_broadcast(&psar->ackcond); 586 | goto recvagain; 587 | } else { 588 | pthread_mutex_unlock(&psar->lock); 589 | #ifdef SU_DEBUG_PEER_RECV 590 | errno = EPROTO; 591 | err_ret("peer %x recv %s:%d raw bytes %d", psar, ipbuff, port, ret); 592 | #endif 593 | free(frame); 594 | return; 595 | 596 | } 597 | pthread_mutex_unlock(&psar->lock); 598 | 599 | goto recvagain; 600 | } 601 | 602 | int su_peer_create_bind(su_peer_t *psar, int port, const SA *destaddr, socklen_t destlen) 603 | { 604 | psar->fd = socket(destaddr->sa_family, SOCK_DGRAM, 0); 605 | if (psar->fd < 0) { 606 | err_ret("peer %x create failed, socket error", psar); 607 | return -1; 608 | } 609 | 610 | if (port > 0 && port <= 65535) { 611 | void *paddr; 612 | SA4 s4; 613 | SA6 s6; 614 | switch (destaddr->sa_family) { 615 | case PF_INET: 616 | memcpy(&s4, destaddr, destlen); /* for sin_family and more... */ 617 | s4.sin_port = htons(port); 618 | inet_pton(PF_INET, "0.0.0.0", &s4.sin_addr.s_addr); 619 | paddr = &s4; 620 | break; 621 | case PF_INET6: 622 | memcpy(&s6, destaddr, destlen); /* for sin6_family and more... */ 623 | s6.sin6_port = htons(port); 624 | inet_pton(PF_INET6, "::", &s6.sin6_addr.__in6_u); 625 | paddr = &s6; 626 | break; 627 | default: 628 | close(psar->fd); 629 | psar->fd = -1; 630 | errno = EINVAL; 631 | return -1; 632 | } 633 | int reuse = 1; 634 | if (setsockopt(psar->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) { 635 | close(psar->fd); 636 | psar->fd = -1; 637 | return -1; 638 | } 639 | if (bind(psar->fd, paddr, destlen) < 0) { 640 | close(psar->fd); 641 | psar->fd = -1; 642 | return -1; 643 | } 644 | } 645 | 646 | if (setfd_nonblock(psar->fd) < 0) { 647 | close(psar->fd); 648 | psar->fd = -1; 649 | return -1; 650 | } 651 | 652 | memset(&psar->destaddr, 0, sizeof(SAUN)); 653 | memcpy(&psar->destaddr, destaddr, destlen); 654 | psar->destlen = destlen; 655 | 656 | psar->seq = 0; 657 | psar->rttinit = 0; 658 | psar->retry = RTT_MAXNREXMT; 659 | 660 | psar->ackwaitnum = 0; 661 | list_init(&psar->ackrecvls); 662 | list_init(&psar->synrecvls); 663 | list_init(&psar->lsackcache); 664 | rbt_init(&psar->rbackcache, cache_getkey, search_cache_cmp); 665 | 666 | psar->nowsynframe = 0; 667 | 668 | pthread_mutex_init(&psar->mutex, 0); 669 | pthread_mutex_init(&psar->lock, 0); 670 | pthread_cond_init(&psar->ackcond, 0); 671 | pthread_cond_init(&psar->syncond, 0); 672 | pthread_mutex_init(&psar->cachelock, 0); 673 | 674 | if (su_peer_thread_install(psar) < 0) { 675 | pthread_mutex_destroy(&psar->mutex); 676 | pthread_mutex_destroy(&psar->lock); 677 | pthread_cond_destroy(&psar->ackcond); 678 | pthread_cond_destroy(&psar->syncond); 679 | pthread_mutex_destroy(&psar->cachelock); 680 | 681 | close(psar->fd); 682 | psar->fd = -1; 683 | return -1; 684 | } 685 | 686 | pthread_mutex_lock(&emutex); 687 | if (sugem == 0) { 688 | sugem = Em_open(100, -1, 0, 0, 0); 689 | Em_run(sugem, 1); 690 | 691 | struct timeval now; 692 | gettimeofday(&now, 0); 693 | srand(now.tv_sec % 1000 + now.tv_usec); 694 | } 695 | psar->sid = rand() % 65535; 696 | pthread_mutex_unlock(&emutex); 697 | 698 | memset(&psar->fe, 0, sizeof(fe_t)); 699 | fe_init(&psar->fe, sugem, psar->fd); 700 | fe_set(&psar->fe, EPOLLIN, handle_su_peer_recv); 701 | fe_set(&psar->fe, EPOLLET, 0); 702 | Fe_em_add(&psar->fe); 703 | 704 | return psar->fd; 705 | } 706 | 707 | int su_peer_create(su_peer_t *psar, const SA *ptoaddr, socklen_t servlen) 708 | { 709 | return su_peer_create_bind(psar, 0, ptoaddr, servlen); 710 | } 711 | 712 | void su_peer_destroy(su_peer_t *psar) 713 | { 714 | su_peer_thread_uninstall(psar); 715 | 716 | pthread_mutex_destroy(&psar->mutex); 717 | pthread_mutex_destroy(&psar->lock); 718 | pthread_cond_destroy(&psar->ackcond); 719 | pthread_cond_destroy(&psar->syncond); 720 | pthread_mutex_destroy(&psar->cachelock); 721 | 722 | close(psar->fd); 723 | psar->fd = -1; 724 | 725 | su_peer_list_empty(psar, &psar->ackrecvls); 726 | su_peer_list_empty(psar, &psar->synrecvls); 727 | 728 | cache_t *frees, *cache = container_of 729 | ( list_head(&psar->lsackcache, frames_t, node), cache_t, frame ); 730 | 731 | while ( &psar->lsackcache != &cache->frame.node ) { 732 | frees = cache; 733 | cache = container_of 734 | ( list_next(&cache->frame, frames_t, node), cache_t, frame ); 735 | 736 | /* Disconnect associated And Cleanup All */ 737 | list_remove(&frees->frame.node); 738 | rb_erase(&frees->rbn, &psar->rbackcache); 739 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 740 | char ipbuff[INET6_ADDRSTRLEN]; 741 | int port; 742 | su_get_ip_port_f(&frees->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 743 | log_msg("peer %x time %u key(%s:%d:%u:%u)" ColorRed " _ACK cache %p" ColorEnd, 744 | psar, frees->ts, ipbuff, port, 745 | frees->frame.recvhdr.sid, frees->frame.recvhdr.seq, frees); 746 | #endif 747 | free(frees); 748 | } 749 | 750 | LOG_MSG("peer %x finish destroyed", psar); 751 | } 752 | 753 | static int su_peer_send_act(su_peer_t *psar, const void *outbuff, int outbytes) 754 | { 755 | int n; 756 | struct iovec iovsend[2] = {{0}}; 757 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 758 | suhdr_t sendhdr = {0}; /* SU_RELIABLE Request protocol head */ 759 | 760 | pthread_mutex_lock(&psar->lock); 761 | sendhdr.act = SU_SYN; 762 | sendhdr.type = SU_ORDINARY; 763 | sendhdr.sid = psar->sid; 764 | sendhdr.seq = ++psar->seq; 765 | sendhdr.ts = 0; 766 | msgsend.msg_name = (void*)&psar->destaddr; 767 | msgsend.msg_namelen = psar->destlen; 768 | msgsend.msg_iov = &iovsend[0]; 769 | msgsend.msg_iovlen = 2; 770 | 771 | iovsend[0].iov_base = &sendhdr; 772 | iovsend[0].iov_len = sizeof(suhdr_t); 773 | iovsend[1].iov_base = (void*)outbuff; 774 | iovsend[1].iov_len = outbytes; 775 | 776 | n = sendmsg(psar->fd, &msgsend, 0); 777 | pthread_mutex_unlock(&psar->lock); 778 | 779 | if (n != sizeof(suhdr_t) + outbytes) 780 | return(-1); 781 | 782 | return(outbytes); 783 | } 784 | 785 | static int su_cmp_ack_SU_RELIABLE(suhdr_t *syn, suhdr_t *ack) 786 | { 787 | if ( 788 | SU_ACK == ack->act && 789 | syn->type == ack->type && 790 | syn->seq == ack->seq && 791 | syn->ts == ack->ts 792 | ) 793 | return 1; 794 | return 0; 795 | } 796 | 797 | static int su_peer_send_recv_act(su_peer_t *psar, 798 | const void *outbuff, int outbytes, 799 | void *inbuff, int inbytes, int retransmit) 800 | { 801 | int n; 802 | struct iovec iovsend[2]={{0}}; 803 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 804 | suhdr_t *r, sendhdr = {0}; /* protocol header */ 805 | int ret, waitsec; 806 | 807 | struct list *node = 0; 808 | frames_t *packet = 0; 809 | 810 | pthread_mutex_lock(&psar->mutex); 811 | pthread_mutex_lock(&psar->lock); 812 | 813 | if (retransmit == 0) { 814 | psar->seq++; 815 | psar->retransmission = 1; 816 | } else { 817 | if (psar->retransmission == 0) { 818 | pthread_mutex_unlock(&psar->mutex); 819 | pthread_mutex_unlock(&psar->lock); 820 | errno = ETIMEDOUT; 821 | return -1; 822 | } 823 | psar->retransmission --; 824 | } 825 | 826 | if (psar->rttinit == 0) { 827 | rtt_init(&psar->rttinfo, psar->retry); /* first time we're called */ 828 | psar->rttinit = 1; 829 | } 830 | 831 | sendhdr.act = SU_SYN; 832 | sendhdr.type = SU_RELIABLE; 833 | sendhdr.sid = psar->sid; 834 | sendhdr.seq = psar->seq; 835 | msgsend.msg_name = (void*)&psar->destaddr; 836 | msgsend.msg_namelen = psar->destlen; 837 | msgsend.msg_iov = iovsend; 838 | msgsend.msg_iovlen = 2; 839 | 840 | iovsend[0].iov_base = (void*)&sendhdr; 841 | iovsend[0].iov_len = sizeof(suhdr_t); 842 | iovsend[1].iov_base = (void*)outbuff; 843 | iovsend[1].iov_len = outbytes; 844 | 845 | struct timespec abstime = {0}; 846 | suhdr_t *precvhdr; 847 | 848 | rtt_newpack(&psar->rttinfo); /* initialize for this packet */ 849 | psar->ackwaitnum ++; 850 | 851 | sendagain: 852 | sendhdr.ts = rtt_ts(&psar->rttinfo); 853 | if (sendmsg(psar->fd, &msgsend, 0) < 0) { 854 | ERR_RET("sendmsg error"); 855 | goto error_ret; 856 | } 857 | 858 | waitsec = rtt_start(&psar->rttinfo); /* calc timeout value & start timer */ 859 | #ifdef SU_DEBUG_RTT 860 | fprintf(stderr, ColorRed "send seq %4d: " ColorEnd, sendhdr.seq); 861 | rtt_debug(&psar->rttinfo); 862 | #endif 863 | 864 | /* set timed wait time-point */ 865 | maketimeout_seconds(&abstime, waitsec); 866 | 867 | #ifdef SU_DEBUG_TIMEVERBOSE 868 | struct timeval now; 869 | gettimeofday(&now, 0); 870 | log_msg( ColorBlue "pthread_cond_timedwait : %u.%u time expire" ColorEnd, 871 | abstime.tv_sec, abstime.tv_nsec); 872 | log_msg( ColorBlue "pthread_cond_timedwait : %d.%d now time" ColorEnd, 873 | now.tv_sec, now.tv_usec*1000); 874 | #endif 875 | 876 | timedwaitagain: 877 | ret = pthread_cond_timedwait(&psar->ackcond, &psar->lock, &abstime); 878 | if (ret == 0) { 879 | #ifdef SU_DEBUG_TIMEVERBOSE 880 | struct timeval now; 881 | gettimeofday(&now, 0); 882 | log_msg(ColorBlue "pthread_cond_timedwait : %d.%d ack cond interrupt" ColorEnd, 883 | now.tv_sec, now.tv_usec*1000); 884 | #endif 885 | node = psar->ackrecvls.next; 886 | for (; node != &psar->ackrecvls; node = node->next) { 887 | packet = container_of(node, frames_t, node); 888 | r = &packet->recvhdr; 889 | if (su_cmp_ack_SU_RELIABLE(&sendhdr, r)) { break; } 890 | } 891 | if ( node == &psar->ackrecvls ) { 892 | /* Be careful of the lock, locked -> timedwait -> unlock */ 893 | #ifdef SU_DEBUG_LIST 894 | log_msg("peer %x no found seq %d ack, timed wait again", psar, sendhdr.seq); 895 | #endif 896 | goto timedwaitagain; 897 | } 898 | 899 | /* Find response packet node */ 900 | list_remove(&packet->node); 901 | 902 | n = packet->len; 903 | precvhdr = &packet->recvhdr; 904 | 905 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 906 | log_msg("peer %x finded ack " ColorRed "%p" ColorEnd " seq %d datagram len %d", 907 | psar, packet, r->seq, packet->len); 908 | #endif 909 | 910 | #ifdef SU_DEBUG_RTT 911 | fprintf(stderr, ColorRed "recv seq %4d \n" ColorEnd, precvhdr->seq); 912 | #endif 913 | // TODO: SU_RELIABLE received response, copy to user's buffer 914 | memcpy(inbuff, packet->data, n > inbytes ? inbytes : n); 915 | 916 | } else if (ret == EINTR) { 917 | log_msg("pthread_cond_timedwait system EINTR"); 918 | goto timedwaitagain; 919 | } else if (ret == ETIMEDOUT) { 920 | #ifdef SU_DEBUG_TIMEVERBOSE 921 | struct timeval now; 922 | gettimeofday(&now, 0); 923 | log_msg(ColorBlue "pthread_cond_timedwait : %u.%u ETIMEOUT have expired" ColorEnd, 924 | now.tv_sec, now.tv_usec*1000); 925 | #endif 926 | if (rtt_timeout(&psar->rttinfo) < 0) { 927 | #ifdef SU_DEBUG_RTT 928 | err_msg(ColorYel "no response from server, giving up" ColorEnd); 929 | #endif 930 | psar->rttinit = 0; /* reinit in case we're called again */ 931 | errno = ETIMEDOUT; 932 | goto error_ret; 933 | } 934 | #ifdef SU_DEBUG_RTT 935 | err_msg(ColorRed " seq %4d timeout, retransmitting %d" ColorEnd, 936 | sendhdr.seq, ++retransmit); 937 | #endif 938 | goto sendagain; 939 | } else { 940 | errno = ret; 941 | ERR_RET("unknown error[%d]", ret); 942 | goto error_ret; 943 | } 944 | 945 | /* calculate & store new RTT estimator values */ 946 | rtt_stop(&psar->rttinfo, rtt_ts(&psar->rttinfo) - precvhdr->ts); 947 | 948 | if (--psar->ackwaitnum == 0) { 949 | su_peer_list_empty(psar, &psar->ackrecvls); 950 | } 951 | pthread_mutex_unlock(&psar->mutex); 952 | pthread_mutex_unlock(&psar->lock); 953 | 954 | #ifdef SU_DEBUG_LIST 955 | log_msg("peer %x free node " ColorRed "%p"ColorEnd" seq %d", psar, packet, sendhdr.seq); 956 | #endif 957 | 958 | free(packet); 959 | 960 | return(n); /* return size of received datagram */ 961 | 962 | error_ret: 963 | if (--psar->ackwaitnum == 0) { 964 | su_peer_list_empty(psar, &psar->ackrecvls); 965 | } 966 | pthread_mutex_unlock(&psar->mutex); 967 | pthread_mutex_unlock(&psar->lock); 968 | return(-1); 969 | } 970 | 971 | static int su_peer_reply_act(su_peer_t *psar, 972 | const void *outbuff, int outbytes) 973 | { 974 | if (psar->nowsynframe == 0) { 975 | err_msg("peer %x is no request data"); 976 | return -1; 977 | } 978 | 979 | int n; 980 | struct iovec iovsend[2] = {{0}}; 981 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 982 | frames_t *frame = psar->nowsynframe; 983 | suhdr_t answerhdr = frame->recvhdr; 984 | 985 | answerhdr.act = SU_ACK; 986 | msgsend.msg_name = (void*)&frame->srcaddr; 987 | msgsend.msg_namelen = frame->srclen; 988 | msgsend.msg_iov = &iovsend[0]; 989 | msgsend.msg_iovlen = 2; 990 | 991 | iovsend[0].iov_base = &answerhdr; 992 | iovsend[0].iov_len = sizeof(suhdr_t); 993 | iovsend[1].iov_base = (void*)outbuff; 994 | iovsend[1].iov_len = outbytes; 995 | 996 | if (answerhdr.type == SU_RELIABLE) { 997 | if (reliable_ack___save(psar, outbuff, outbytes) < 0) { 998 | err_ret("reliable_ack___save error"); 999 | return -1; 1000 | } 1001 | } 1002 | 1003 | n = sendmsg(psar->fd, &msgsend, 0); 1004 | if (n != sizeof(suhdr_t) + outbytes) { 1005 | err_ret("sendmsg error"); 1006 | return(-1); 1007 | } 1008 | 1009 | return(outbytes); 1010 | } 1011 | 1012 | int su_peer_getsrcaddr_act(su_peer_t *psar, SAUN *addr) 1013 | { 1014 | if (psar->nowsynframe == 0) { 1015 | err_msg("peer %x is no request source"); 1016 | return -1; 1017 | } 1018 | memcpy(addr, &psar->nowsynframe->srcaddr, sizeof(SAUN)); 1019 | return 0; 1020 | } 1021 | 1022 | int su_peer_reply(su_peer_t *psar, const void *outbuff, int outbytes) 1023 | { 1024 | if (psar == 0) { errno = EINVAL; return -1;} 1025 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 1026 | if ( (outbytes < 0) || 1027 | (outbytes == 0 && outbuff) || 1028 | (outbytes > 0 && !outbuff) ) 1029 | { errno = EINVAL; return -1; } 1030 | return su_peer_reply_act(psar, outbuff, outbytes); 1031 | } 1032 | 1033 | void su_peer_reply_ignore_act(su_peer_t *psar) 1034 | { 1035 | rb_key_cache_t key; 1036 | memcpy(&key.destaddr, &psar->nowsynframe->srcaddr, sizeof(SAUN)); 1037 | key.destlen = psar->nowsynframe->srclen; 1038 | key.seq = psar->nowsynframe->recvhdr.seq; 1039 | key.sid = psar->nowsynframe->recvhdr.sid; 1040 | 1041 | struct rb_node *cachenode; 1042 | cache_t *frees; 1043 | 1044 | if ((cachenode = rb_search(&psar->rbackcache, &key))) { 1045 | frees = rb_entry(cachenode, cache_t, rbn); 1046 | list_remove (&frees->frame.node); 1047 | rb_erase (&frees->rbn, &psar->rbackcache); 1048 | free(frees); 1049 | return; 1050 | } 1051 | } 1052 | 1053 | void su_peer_reply_ignore(su_peer_t *psar) 1054 | { 1055 | if (psar == 0 || psar->nowsynframe == 0) { return; } 1056 | su_peer_reply_ignore_act(psar); 1057 | } 1058 | 1059 | int su_peer_reply_ack(su_peer_t *psar) 1060 | { 1061 | if (psar == 0) { errno = EINVAL; return -1;} 1062 | return su_peer_reply_act(psar, 0, 0); 1063 | } 1064 | 1065 | int su_peer_send(su_peer_t *psar, const void *outbuff, int outbytes) 1066 | { 1067 | if (psar == 0) { errno = EINVAL; return -1;} 1068 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 1069 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 1070 | return su_peer_send_act(psar, outbuff, outbytes); 1071 | } 1072 | 1073 | int su_peer_request(su_peer_t *psar, const void *outbuff, int outbytes, 1074 | void *inbuff, int inbytes) 1075 | { 1076 | if (psar == 0) { errno = EINVAL; return -1;} 1077 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 1078 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 1079 | if (inbytes <= 0 || inbuff== 0) { errno = EINVAL; return -1;} 1080 | return su_peer_send_recv_act(psar, outbuff, outbytes, inbuff, inbytes, 0); 1081 | } 1082 | 1083 | int su_peer_request_retry(su_peer_t *psar, const void *outbuff, int outbytes, 1084 | void *inbuff, int inbytes) 1085 | { 1086 | if (psar == 0) { errno = EINVAL; return -1;} 1087 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 1088 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 1089 | if (inbytes <= 0 || inbuff== 0) { errno = EINVAL; return -1;} 1090 | return su_peer_send_recv_act(psar, outbuff, outbytes, inbuff, inbytes, 1); 1091 | } 1092 | 1093 | int su_peer_getsrcaddr(su_peer_t *psar, SAUN *addr) 1094 | { 1095 | if (psar == 0) { errno = EINVAL; return -1;} 1096 | if (addr == 0) { errno = EINVAL; return -1;} 1097 | return su_peer_getsrcaddr_act(psar, addr); 1098 | } 1099 | -------------------------------------------------------------------------------- /sarudp_peer.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_SARUDP_PEER_H__ 2 | #define __YH_SARUDP_PEER_H__ 3 | 4 | #include "sarudp_comm.h" 5 | 6 | typedef struct sar_udp_peer su_peer_t; 7 | typedef void cb_su_peer_receiver_t(su_peer_t *ps, char* buff, int len); 8 | 9 | /* SYN/ACK/Retransfer UDP peer manager */ 10 | struct sar_udp_peer { 11 | /* foreign host info */ 12 | int fd; 13 | SAUN destaddr; 14 | socklen_t destlen; 15 | uint16_t sid; 16 | uint32_t seq; 17 | struct rtt_info rttinfo; 18 | int retry; 19 | int retransmission; /* retransmit counting */ 20 | int rttinit; 21 | 22 | /* event driver */ 23 | fe_t fe; 24 | cb_su_peer_receiver_t * reliable_request_handle; 25 | cb_su_peer_receiver_t * ordinary_request_handle; 26 | 27 | pthread_t tid; 28 | int run; 29 | 30 | pthread_mutex_t mutex; 31 | pthread_mutex_t lock; 32 | pthread_cond_t ackcond; 33 | pthread_cond_t syncond; 34 | 35 | int ackwaitnum; /* SU_RELIABLE Requester number */ 36 | 37 | /* frames_t list: foreign respnose */ 38 | struct list ackrecvls; /* SU_RELIABLE Reply of the foreign host */ 39 | 40 | /* frames_t list: foreign request */ 41 | struct list synrecvls; /* Receive foreign host the active request */ 42 | frames_t *nowsynframe; /* Currently working with active request (syn) */ 43 | 44 | /* container cache_t: foreign reply result datas */ 45 | struct list lsackcache; /* The cache results for timeout check */ 46 | rb_root_t rbackcache; /* The cache results for re-syn search */ 47 | pthread_mutex_t cachelock; 48 | }; 49 | 50 | int su_peer_create(su_peer_t *psar, const SA *ptoaddr, socklen_t servlen); 51 | int su_peer_create_bind(su_peer_t *psar, int port, const SA *ptoaddr, socklen_t servlen); 52 | void su_peer_destroy(su_peer_t *psar); 53 | 54 | void su_peer_reliable_request_handle_install(su_peer_t *psar, cb_su_peer_receiver_t* reliable_request_handle); 55 | void su_peer_ordinary_request_handle_install(su_peer_t *psar, cb_su_peer_receiver_t* ordinary_request_handle); 56 | void su_peer_reliable_request_handle_uninstall(su_peer_t *psar); 57 | void su_peer_ordinary_request_handle_uninstall(su_peer_t *psar); 58 | 59 | int su_peer_send(su_peer_t *psar, const void *outbuff, int outbytes); 60 | int su_peer_request(su_peer_t *psar, const void *outbuff, int outbytes, void *inbuff, int inbytes); 61 | int su_peer_request_retry(su_peer_t *psar, const void *outbuff, int outbytes, void *inbuff, int inbytes); 62 | 63 | int su_peer_getsrcaddr(su_peer_t *psar, SAUN *addr); 64 | 65 | int su_peer_reply(su_peer_t *psar, const void *outbuff, int outbytes); 66 | int su_peer_reply_ack(su_peer_t *psar); 67 | void su_peer_reply_ignore(su_peer_t *psar); 68 | 69 | #endif /* __YH_SARUDP_PEER_H__ */ 70 | -------------------------------------------------------------------------------- /sarudp_serv.c: -------------------------------------------------------------------------------- 1 | #include "sarudp_serv.h" 2 | 3 | #include "yherror.h" 4 | #include "yhevent.h" 5 | #include "yhtime.h" 6 | #include "yhrbtree.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | pthread_mutex_t emutex = PTHREAD_MUTEX_INITIALIZER; 14 | em_t * sugem = 0; 15 | char rejectbuff[1024*10] = {0}; 16 | 17 | static inline int reliable_ack___hold(su_serv_t *psvr, const frames_t *frame) 18 | { 19 | cache_t * newack; 20 | newack = calloc(1, sizeof(cache_t)); 21 | if (newack == 0) { 22 | errno = ENOBUFS; 23 | return -1; 24 | } 25 | time(&newack->ts); 26 | memcpy(&newack->frame, frame, sizeof(frames_t)); 27 | newack->frame.len = -1; 28 | 29 | /* Adding associated */ 30 | if (rb_insert(&psvr->rbackcache, &newack->rbn) < 0) { 31 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 32 | pthread_t tid = pthread_self(); 33 | char ipbuff[INET6_ADDRSTRLEN]; 34 | int port; 35 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 36 | log_msg("serv %x %x time %u key(%s:%d:%u:%u)" ColorRed " !ACK cache %p failed" ColorEnd , 37 | psvr, tid, newack->ts, ipbuff, port, 38 | newack->frame.recvhdr.sid, newack->frame.recvhdr.seq, newack); 39 | #endif 40 | free(newack); 41 | errno = EALREADY; 42 | return -1; 43 | } else { 44 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 45 | pthread_t tid = pthread_self(); 46 | char ipbuff[INET6_ADDRSTRLEN]; 47 | int port; 48 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 49 | log_msg("serv %x %x time %u key(%s:%d:%u:%u)" ColorRed " !ACK cache %p" ColorEnd , 50 | psvr, tid, newack->ts, ipbuff, port, 51 | newack->frame.recvhdr.sid, newack->frame.recvhdr.seq, newack); 52 | 53 | #endif 54 | list_append(&psvr->lsackcache, &newack->frame.node); 55 | } 56 | return 0; 57 | } 58 | static inline int reliable_ack___save (su_serv_t *psvr, 59 | const frames_t *frame, const void *outbuff, int outbytes) 60 | { 61 | /* Construct search key */ 62 | rb_key_cache_t key; 63 | memcpy(&key.destaddr, & frame->srcaddr, sizeof(SAUN)); 64 | key.destlen = frame->srclen; 65 | key.seq = frame->recvhdr.seq; 66 | key.sid = frame->recvhdr.sid; 67 | 68 | struct rb_node *cachenode; 69 | cache_t *cache; 70 | 71 | /* If is no reply content, only replace len value, don't replace node 72 | * If have a content, must allocating and replacing new node */ 73 | if (outbuff == 0 && outbytes == 0) { 74 | if ((cachenode = rb_search(&psvr->rbackcache, &key))) { 75 | cache = rb_entry(cachenode, cache_t, rbn); 76 | cache->frame.len = 0; 77 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 78 | pthread_t tid = pthread_self(); 79 | char ipbuff[INET6_ADDRSTRLEN]; 80 | int port; 81 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 82 | log_msg("serv %x %x time %u key(%s:%d:%u:%u) " 83 | ColorRed "+ACK cache %p" ColorEnd , 84 | psvr, tid, cache->ts, ipbuff, port, 85 | cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); 86 | #endif 87 | return 0; 88 | } 89 | errno = ENOKEY; 90 | return -1; 91 | } 92 | 93 | cache_t * newack; 94 | newack = calloc(1, sizeof(cache_t) + outbytes); 95 | if (newack == 0) { 96 | errno = ENOBUFS; 97 | return -1; 98 | } 99 | 100 | /* Construct a new node */ 101 | memcpy(&newack->frame, frame, sizeof(frames_t)); 102 | memcpy(newack->frame.data, outbuff, outbytes); 103 | newack->frame.len = outbytes; 104 | 105 | /* Find and replace the hold node */ 106 | if ((cachenode = rb_search(&psvr->rbackcache, &key))) { 107 | rb_replace_node(cachenode, &newack->rbn, &psvr->rbackcache); 108 | cache = rb_entry(cachenode, cache_t, rbn); 109 | newack->ts = cache->ts; 110 | list_remove(&cache->frame.node); 111 | list_append(&psvr->lsackcache, &newack->frame.node); 112 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 113 | pthread_t tid = pthread_self(); 114 | char ipbuff[INET6_ADDRSTRLEN]; 115 | int port; 116 | su_get_ip_port_f(&newack->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 117 | log_msg("serv %x %x time %u key(%s:%d:%u:%u) " 118 | ColorRed "+ACK cache %p Swap %p" ColorEnd , 119 | psvr, tid, newack->ts, ipbuff, port, 120 | frame->recvhdr.sid, frame->recvhdr.seq, cache, newack); 121 | #endif 122 | free(cache); 123 | return 0; 124 | } 125 | free(newack); 126 | errno = ENOKEY; 127 | return -1; 128 | } 129 | 130 | static inline void reliable_ack_unsave (su_serv_t *psvr) 131 | { 132 | time_t nowtime; 133 | 134 | cache_t *frees, *cache = container_of 135 | ( list_head(&psvr->lsackcache, frames_t, node), cache_t, frame ); 136 | 137 | time(&nowtime); 138 | 139 | while ( &psvr->lsackcache != &cache->frame.node ) { 140 | if ( abs(nowtime - cache->ts) < CACHETIMEOUT ) break; 141 | frees = cache; 142 | cache = container_of 143 | ( list_next(&cache->frame, frames_t, node), cache_t, frame ); 144 | 145 | /* Disconnect associated */ 146 | list_remove(&frees->frame.node); 147 | rb_erase(&frees->rbn, &psvr->rbackcache); 148 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 149 | pthread_t tid = pthread_self(); 150 | char ipbuff[INET6_ADDRSTRLEN]; 151 | int port; 152 | su_get_ip_port_f(&frees->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 153 | log_msg("serv %x %x time %u key(%s:%d:%u:%u)" ColorRed " -ACK cache %p" ColorEnd, 154 | psvr, tid, frees->ts, ipbuff, port, 155 | frees->frame.recvhdr.sid, frees->frame.recvhdr.seq, frees); 156 | #endif 157 | free(frees); 158 | } 159 | } 160 | 161 | static inline void su_serv_list_empty(su_serv_t *psvr, struct list *l) 162 | { 163 | frames_t *realnode; 164 | struct list *node = l->next; 165 | 166 | while ( node != l ) { 167 | list_remove(node); 168 | realnode = container_of(node, frames_t, node); 169 | node = node->next; 170 | free(realnode); 171 | #ifdef SU_DEBUG_LIST 172 | log_msg("serv %x free frames_t node " ColorRed "%p" ColorEnd, psvr, realnode); 173 | #endif 174 | } 175 | } 176 | 177 | void request_handle(su_serv_t *psvr, frames_t * frame) 178 | { 179 | suhdr_t *phdr = &frame->recvhdr; 180 | pthread_t tid; 181 | 182 | switch (phdr->type) { 183 | case SU_RELIABLE: 184 | if (psvr->reliable_request_handle) { 185 | psvr->reliable_request_handle(psvr, frame, (char*)frame->data, frame->len); 186 | } break; 187 | case SU_ORDINARY: 188 | if (psvr->ordinary_request_handle) { 189 | psvr->ordinary_request_handle(psvr, frame, (char*)frame->data, frame->len); 190 | } break; 191 | default: 192 | tid = pthread_self(); 193 | LOG_MSG("serv %x %x recv request type unknown %d", psvr, tid, phdr->type); 194 | return; 195 | } 196 | } 197 | 198 | static void *thread_request_handle(void *v) 199 | { 200 | int ret; 201 | struct list *synnode; 202 | struct timespec abstime = {0}; 203 | frames_t *frame; 204 | su_serv_t *psvr = (su_serv_t*)v; 205 | 206 | pthread_t tid __attribute__((unused)) = pthread_self(); 207 | log_msg("serv %x create thread_request_handle %x success", psvr, tid); 208 | 209 | for (;psvr->run;) { 210 | pthread_mutex_lock(&psvr->lock); 211 | while ((synnode = psvr->synrecvls.next) == &psvr->synrecvls) { 212 | maketimeout_seconds(&abstime, 1); 213 | ret = pthread_cond_timedwait(&psvr->syncond, &psvr->lock, &abstime); 214 | if (!psvr->run) { 215 | pthread_mutex_unlock(&psvr->lock); 216 | goto quit; 217 | } 218 | if ( ret == ETIMEDOUT ) { 219 | pthread_mutex_lock(&psvr->cachelock); 220 | reliable_ack_unsave(psvr); 221 | pthread_mutex_unlock(&psvr->cachelock); 222 | } 223 | } 224 | list_remove(synnode); 225 | pthread_mutex_unlock(&psvr->lock); 226 | 227 | /* have request datagram */ 228 | frame = container_of(synnode, frames_t, node); 229 | 230 | rb_key_cache_t key; 231 | memcpy(&key.destaddr, &frame->srcaddr, sizeof(SAUN)); 232 | key.destlen = frame->srclen; 233 | key.seq = frame->recvhdr.seq; 234 | key.sid = frame->recvhdr.sid; 235 | 236 | struct rb_node *cachenode; 237 | cache_t *cache; 238 | 239 | pthread_mutex_lock(&psvr->cachelock); 240 | reliable_ack_unsave(psvr); 241 | if (frame->recvhdr.type == SU_RELIABLE) { 242 | if ( (cachenode = rb_search(&psvr->rbackcache, &key))) { 243 | cache = rb_entry(cachenode, cache_t, rbn); 244 | 245 | if (cache->frame.len == -1) { 246 | #ifdef SU_DEBUG_RBTREE 247 | char ipbuff[INET6_ADDRSTRLEN]; 248 | int port; 249 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 250 | log_msg("serv %x %x time %u key(%s:%d:%u:%u)" 251 | ColorRed " 0ACK cache %p" ColorEnd, 252 | psvr, tid, cache->ts, ipbuff, port, 253 | cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); 254 | #endif 255 | pthread_mutex_unlock(&psvr->cachelock); 256 | free(frame); 257 | continue; 258 | } 259 | 260 | #ifdef SU_DEBUG_RBTREE 261 | char ipbuff[INET6_ADDRSTRLEN]; 262 | int port; 263 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 264 | log_msg("serv %x %x time %u key(%s:%d:%u:%u)" 265 | ColorRed " @ACK cache %p" ColorEnd, 266 | psvr, tid, cache->ts, ipbuff, port, 267 | cache->frame.recvhdr.sid, cache->frame.recvhdr.seq, cache); 268 | #endif 269 | 270 | struct iovec iovsend[2] = {{0}}; 271 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 272 | 273 | frame->recvhdr.act = SU_ACK; 274 | msgsend.msg_name = (void*)&cache->frame.srcaddr; 275 | msgsend.msg_namelen = cache->frame.srclen; 276 | msgsend.msg_iov = &iovsend[0]; 277 | msgsend.msg_iovlen = 2; 278 | 279 | iovsend[0].iov_base = &frame->recvhdr; 280 | iovsend[0].iov_len = sizeof(suhdr_t); 281 | iovsend[1].iov_base = (void*)cache->frame.data; /* get the cache results */ 282 | iovsend[1].iov_len = cache->frame.len; 283 | 284 | /* resend from cache */ 285 | if (sendmsg(psvr->fd, &msgsend, 0) != sizeof(suhdr_t) + cache->frame.len) { 286 | char ipbuff[INET6_ADDRSTRLEN]; 287 | int port; 288 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 289 | ERR_RET("retransmit sendmsg %s:%d:%u:%u:%u error", 290 | ipbuff, port, 291 | frame->recvhdr.seq, frame->recvhdr.ts, 292 | frame->recvhdr.sid); 293 | } 294 | #ifdef SU_DEBUG_PEER_RESEND 295 | else { 296 | char ipbuff[INET6_ADDRSTRLEN]; 297 | int port; 298 | su_get_ip_port_f(&cache->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 299 | log_msg("retransmit sendmsg %s:%d:%u:%u:%u", 300 | ipbuff, port, 301 | frame->recvhdr.seq, frame->recvhdr.ts, 302 | frame->recvhdr.sid); 303 | } 304 | #endif 305 | pthread_mutex_unlock(&psvr->cachelock); 306 | free(frame); 307 | continue; 308 | } else { 309 | if (reliable_ack___hold(psvr, frame) < 0) { 310 | err_ret("serv %x %x reliable_ack___hold error", psvr, tid); 311 | pthread_mutex_unlock(&psvr->cachelock); 312 | free(frame); 313 | continue; 314 | } 315 | } 316 | } 317 | pthread_mutex_unlock(&psvr->cachelock); 318 | request_handle(psvr, frame); 319 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 320 | log_msg("serv %x %x delete syn "ColorRed"%p"ColorEnd" seq %d datagram len %d", 321 | psvr, tid, frame, frame->recvhdr.seq, frame->len); 322 | #endif 323 | free(frame); 324 | } 325 | 326 | quit: 327 | pthread_exit(0); 328 | } 329 | 330 | static int su_serv_thread_install(su_serv_t *psvr, int nthread) 331 | { 332 | int i, n; 333 | void *retr; 334 | pthread_attr_t attr; 335 | 336 | psvr->tids = calloc(nthread, sizeof(pthread_t)); 337 | if ( !psvr->tids ) return -1; 338 | 339 | psvr->run = 0; 340 | psvr->tnum = 0; 341 | psvr->reliable_request_handle = 0; 342 | psvr->ordinary_request_handle = 0; 343 | 344 | /* Set stack size 1M */ 345 | pthread_attr_init(&attr); 346 | pthread_attr_setstacksize(&attr, 1024*1024); 347 | 348 | for (n = 0; n < nthread; n++) { 349 | errno = pthread_create (&psvr->tids[n], &attr, thread_request_handle, psvr); 350 | if (errno != 0) { 351 | err_ret("serv %x pthread_create[%d] error", n); 352 | for (i = 0; i < n; i++) { 353 | errno = pthread_join(psvr->tids[i], &retr); 354 | if (errno != 0) 355 | err_sys("serv %x join with thread %x error"); 356 | } 357 | pthread_attr_destroy(&attr); 358 | free(psvr->tids); 359 | return (-1); 360 | } 361 | } 362 | pthread_attr_destroy(&attr); 363 | psvr->run = 1; 364 | psvr->tnum = nthread; 365 | return 0; 366 | } 367 | 368 | static int su_serv_thread_uninstall(su_serv_t *psvr) 369 | { 370 | int i; 371 | void *ret; 372 | 373 | psvr->run = 0; 374 | for (i = 0; i < psvr->tnum; i++) { 375 | errno = pthread_join(psvr->tids[i], &ret); 376 | if (errno != 0) 377 | err_sys("serv %x can't join with thread %x error"); 378 | log_msg("serv %x join with thread %x code %d", psvr, psvr->tids[i], ret); 379 | } 380 | free(psvr->tids); 381 | return 0; 382 | } 383 | 384 | void su_serv_reliable_request_handle_install(su_serv_t *psvr, 385 | cb_su_serv_receiver_t* reliable_request_handle) 386 | { 387 | pthread_mutex_lock(&psvr->lock); 388 | psvr->reliable_request_handle = reliable_request_handle; 389 | pthread_mutex_unlock(&psvr->lock); 390 | } 391 | 392 | void su_serv_ordinary_request_handle_install(su_serv_t *psvr, 393 | cb_su_serv_receiver_t* ordinary_request_handle) 394 | { 395 | pthread_mutex_lock(&psvr->lock); 396 | psvr->ordinary_request_handle = ordinary_request_handle; 397 | pthread_mutex_unlock(&psvr->lock); 398 | } 399 | 400 | void su_serv_reliable_request_handle_uninstall(su_serv_t *psvr) 401 | { 402 | pthread_mutex_lock(&psvr->lock); 403 | psvr->reliable_request_handle = 0; 404 | pthread_mutex_unlock(&psvr->lock); 405 | } 406 | 407 | void su_serv_ordinary_request_handle_uninstall(su_serv_t *psvr) 408 | { 409 | pthread_mutex_lock(&psvr->lock); 410 | psvr->ordinary_request_handle = 0; 411 | pthread_mutex_unlock(&psvr->lock); 412 | } 413 | 414 | static void handle_su_serv_recv(fe_t * fe) 415 | { 416 | int ret; 417 | char ipbuff[INET6_ADDRSTRLEN]; 418 | int port; 419 | SAUN saddr; 420 | socklen_t socklen; 421 | su_serv_t *psvr = container_of(fe, su_serv_t, fe); 422 | struct iovec iovrecv[2] = {{0}}; /* assumed init to 0 */ 423 | struct msghdr msgrecv = {0}; /* assumed init to 0 */ 424 | frames_t *frame; 425 | recvagain: 426 | socklen = sizeof(SA6); 427 | frame = calloc(1, sizeof(frames_t) + REALDATAMAX); 428 | if (frame == 0) { 429 | errno = ENOBUFS; // ENOMEM 430 | err_ret("serv %x ENOBUFS", psvr); 431 | /* reject datagram */ 432 | ret = recvfrom(fe->fd, rejectbuff, sizeof(rejectbuff), 0, (SA*)&saddr, &socklen); 433 | if (ret < 0 && errno == EAGAIN) { 434 | return; 435 | } 436 | #ifdef SU_DEBUG_PEER_RECV 437 | switch (saddr.sfamily) { 438 | case PF_INET: 439 | case PF_INET6: 440 | #ifdef SU_DEBUG_IP6FULL 441 | su_get_ip_port_f(&saddr, ipbuff, sizeof(ipbuff), &port); 442 | #else 443 | su_get_ip_port(&saddr, ipbuff, sizeof(ipbuff), &port); 444 | #endif 445 | break; 446 | default: 447 | log_msg("serv %x reject unknown protocol raw bytes %d", psvr, ret); 448 | goto recvagain; 449 | }; 450 | ERR_RET("serv %x %d recv %s:%d bytes %d, but reject datas", psvr, 451 | fe->fd, ipbuff, port, ret); 452 | #endif 453 | return; 454 | } 455 | 456 | frame->srclen = psvr->servlen; 457 | 458 | msgrecv.msg_name = & frame->srcaddr; 459 | msgrecv.msg_namelen = frame->srclen; 460 | msgrecv.msg_iov = iovrecv; 461 | msgrecv.msg_iovlen = 2; 462 | 463 | iovrecv[0].iov_base = & frame->recvhdr; 464 | iovrecv[0].iov_len = sizeof(suhdr_t); 465 | iovrecv[1].iov_base = frame->data; 466 | iovrecv[1].iov_len = REALDATAMAX; 467 | 468 | if ((ret = recvmsg(fe->fd, &msgrecv, 0)) < 0) { 469 | if (ret < 0 && errno == EAGAIN) { 470 | free(frame); 471 | return; 472 | } 473 | ERR_RET("recvmsg error"); 474 | } 475 | 476 | switch (frame->srcaddr.sfamily) { 477 | case PF_INET: 478 | case PF_INET6: 479 | #ifdef SU_DEBUG_IP6FULL 480 | su_get_ip_port_f(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 481 | #else 482 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 483 | #endif 484 | break; 485 | default: 486 | log_msg("serv %x reject unknown protocol raw bytes %d", psvr, ret); 487 | free(frame); 488 | goto recvagain; 489 | }; 490 | 491 | if (ret < sizeof(suhdr_t)) { 492 | #ifdef SU_DEBUG_PEER_RECV 493 | errno = EBADMSG; 494 | err_ret("serv %x recv %s:%d raw bytes %d less-then head %d bytes", 495 | psvr, ipbuff, port, ret, sizeof(suhdr_t)); 496 | #endif 497 | free(frame); 498 | goto recvagain; 499 | } 500 | 501 | #ifdef SU_DEBUG_PEER_RECV 502 | log_msg("serv %x recv %s:%d raw bytes %d", psvr, 503 | ipbuff, port, ret); 504 | #endif 505 | 506 | suhdr_t *r = &frame->recvhdr; 507 | uint8_t act = r->act; 508 | uint8_t type = r->type; 509 | 510 | frame->len = ret - sizeof(suhdr_t); 511 | 512 | pthread_mutex_lock(&psvr->lock); 513 | if (act == SU_SYN && frame->len > 0) { 514 | if (!psvr->run) { 515 | pthread_mutex_unlock(&psvr->lock); 516 | free(frame); 517 | goto recvagain; 518 | } 519 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 520 | log_msg("serv %x append syn "ColorRed"%p"ColorEnd" seq %d datagram len %d", 521 | psvr, frame, r->seq, frame->len); 522 | #endif 523 | list_append(&psvr->synrecvls, &frame->node); 524 | pthread_mutex_unlock(&psvr->lock); 525 | pthread_cond_broadcast(&psvr->syncond); 526 | goto recvagain; 527 | } else if (act == SU_ACK && type == SU_RELIABLE) { 528 | if (psvr->ackwaitnum <= 0) { 529 | pthread_mutex_unlock(&psvr->lock); 530 | free(frame); 531 | goto recvagain; 532 | } 533 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 534 | log_msg("serv %x append ack "ColorRed"%p"ColorEnd" seq %d datagram len %d", 535 | psvr, frame, r->seq, frame->len); 536 | #endif 537 | list_append(&psvr->ackrecvls, &frame->node); 538 | pthread_mutex_unlock(&psvr->lock); 539 | pthread_cond_broadcast(&psvr->ackcond); 540 | goto recvagain; 541 | } else { 542 | pthread_mutex_unlock(&psvr->lock); 543 | #ifdef SU_DEBUG_PEER_RECV 544 | errno = EPROTO; 545 | err_ret("serv %x recv %s:%d raw bytes %d", psvr, 546 | ipbuff, port, ret); 547 | #endif 548 | free(frame); 549 | return; 550 | 551 | } 552 | pthread_mutex_unlock(&psvr->lock); 553 | 554 | goto recvagain; 555 | } 556 | 557 | void epoll_outs(const em_t * const em, int n) 558 | { 559 | log_msg("epoll_wait ret %d", n); 560 | } 561 | 562 | int su_serv_create(su_serv_t *psvr, const SA *saddr, socklen_t servlen, int nthread) 563 | { 564 | if (nthread <= 0) { 565 | errno = EINVAL; 566 | return -1; 567 | } 568 | psvr->fd = socket(saddr->sa_family, SOCK_DGRAM, 0); 569 | if (psvr->fd < 0) { 570 | err_ret("serv %x create failed, socket error", psvr); 571 | return -1; 572 | } 573 | int reuse = 1; 574 | if (setsockopt(psvr->fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) { 575 | close(psvr->fd); 576 | psvr->fd = -1; 577 | return -1; 578 | } 579 | if (bind(psvr->fd, saddr, servlen) < 0) { 580 | close(psvr->fd); 581 | psvr->fd = -1; 582 | return -1; 583 | } 584 | if (setfd_nonblock(psvr->fd) < 0) { 585 | close(psvr->fd); 586 | psvr->fd = -1; 587 | return -1; 588 | } 589 | 590 | memset(&psvr->servaddr, 0, sizeof(SAUN)); 591 | memcpy(&psvr->servaddr, saddr, servlen); 592 | psvr->servlen = servlen; 593 | 594 | psvr->seq = 0; 595 | psvr->rttinit = 0; 596 | psvr->retry = RTT_MAXNREXMT; 597 | 598 | psvr->ackwaitnum = 0; 599 | list_init(&psvr->ackrecvls); 600 | list_init(&psvr->synrecvls); 601 | list_init(&psvr->lsackcache); 602 | rbt_init(&psvr->rbackcache, cache_getkey, search_cache_cmp); 603 | 604 | pthread_mutex_init(&psvr->mutex, 0); 605 | pthread_mutex_init(&psvr->lock, 0); 606 | pthread_cond_init(&psvr->ackcond, 0); 607 | pthread_cond_init(&psvr->syncond, 0); 608 | pthread_mutex_init(&psvr->cachelock, 0); 609 | 610 | if (su_serv_thread_install(psvr, nthread) < 0) { 611 | pthread_mutex_destroy(&psvr->mutex); 612 | pthread_mutex_destroy(&psvr->lock); 613 | pthread_mutex_destroy(&psvr->cachelock); 614 | pthread_cond_destroy(&psvr->ackcond); 615 | pthread_cond_destroy(&psvr->syncond); 616 | close(psvr->fd); 617 | psvr->fd = -1; 618 | return -1; 619 | } 620 | 621 | pthread_mutex_lock(&emutex); 622 | if (sugem == 0) { 623 | #ifdef SU_DEBUG_PEER_RECV 624 | sugem = Em_open(100, -1, 0, epoll_outs, 0); 625 | #else 626 | sugem = Em_open(100, -1, 0, 0, 0); 627 | #endif 628 | Em_run(sugem, nthread / 8 + 1); 629 | 630 | struct timeval now; 631 | gettimeofday(&now, 0); 632 | srand(now.tv_sec % 1000 + now.tv_usec); 633 | } 634 | psvr->sid = rand() % 65535; 635 | pthread_mutex_unlock(&emutex); 636 | 637 | memset(&psvr->fe, 0, sizeof(fe_t)); 638 | fe_init(&psvr->fe, sugem, psvr->fd); 639 | fe_set(&psvr->fe, EPOLLIN, handle_su_serv_recv); 640 | fe_set(&psvr->fe, EPOLLET, 0); 641 | Fe_em_add(&psvr->fe); 642 | 643 | return psvr->fd; 644 | } 645 | 646 | void su_serv_destroy(su_serv_t *psvr) 647 | { 648 | su_serv_thread_uninstall(psvr); 649 | 650 | pthread_mutex_destroy(&psvr->mutex); 651 | pthread_mutex_destroy(&psvr->lock); 652 | pthread_mutex_destroy(&psvr->cachelock); 653 | pthread_cond_destroy(&psvr->ackcond); 654 | pthread_cond_destroy(&psvr->syncond); 655 | 656 | close(psvr->fd); 657 | psvr->fd = -1; 658 | 659 | su_serv_list_empty(psvr, &psvr->ackrecvls); 660 | su_serv_list_empty(psvr, &psvr->synrecvls); 661 | 662 | cache_t *frees, *cache = container_of 663 | ( list_head(&psvr->lsackcache, frames_t, node), cache_t, frame ); 664 | 665 | while ( &psvr->lsackcache != &cache->frame.node ) { 666 | frees = cache; 667 | cache = container_of 668 | ( list_next(&cache->frame, frames_t, node), cache_t, frame ); 669 | 670 | /* Disconnect associated And Cleanup All */ 671 | list_remove(&frees->frame.node); 672 | rb_erase(&frees->rbn, &psvr->rbackcache); 673 | #if defined SU_DEBUG_LIST || defined SU_DEBUG_RBTREE 674 | char ipbuff[INET6_ADDRSTRLEN]; 675 | int port; 676 | su_get_ip_port_f(&frees->frame.srcaddr, ipbuff, sizeof(ipbuff), &port); 677 | log_msg("serv %x time %u key(%s:%d:%u:%u)" ColorRed " _ACK cache %p" ColorEnd, 678 | psvr, frees->ts, ipbuff, port, 679 | frees->frame.recvhdr.sid, frees->frame.recvhdr.seq, frees); 680 | #endif 681 | free(frees); 682 | } 683 | 684 | LOG_MSG("serv %x finish destroyed", psvr); 685 | } 686 | 687 | static int su_serv_reply_act(su_serv_t *psvr, const frames_t *frame, 688 | const void *outbuff, int outbytes) 689 | { 690 | int n; 691 | struct iovec iovsend[2] = {{0}}; 692 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 693 | suhdr_t answerhdr = frame->recvhdr; 694 | 695 | answerhdr.act = SU_ACK; 696 | msgsend.msg_name = (void*)&frame->srcaddr; 697 | msgsend.msg_namelen = frame->srclen; 698 | msgsend.msg_iov = &iovsend[0]; 699 | msgsend.msg_iovlen = 2; 700 | 701 | iovsend[0].iov_base = &answerhdr; 702 | iovsend[0].iov_len = sizeof(suhdr_t); 703 | iovsend[1].iov_base = (void*)outbuff; 704 | iovsend[1].iov_len = outbytes; 705 | 706 | if (answerhdr.type == SU_RELIABLE) { 707 | pthread_mutex_lock(&psvr->cachelock); 708 | if (reliable_ack___save(psvr, frame, outbuff, outbytes) < 0) { 709 | pthread_mutex_unlock(&psvr->cachelock); 710 | err_ret("reliable_ack___save error"); 711 | return -1; 712 | } 713 | pthread_mutex_unlock(&psvr->cachelock); 714 | } 715 | 716 | n = sendmsg(psvr->fd, &msgsend, 0); 717 | if (n != sizeof(suhdr_t) + outbytes) { 718 | err_ret("sendmsg error"); 719 | return(-1); 720 | } 721 | 722 | return(outbytes); 723 | } 724 | 725 | static int su_serv_send_act(su_serv_t *psvr, SA *destaddr, socklen_t destlen, const void *outbuff, int outbytes) 726 | { 727 | int n; 728 | struct iovec iovsend[2] = {{0}}; 729 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 730 | suhdr_t sendhdr = {0}; /* SU_RELIABLE Request protocol head */ 731 | 732 | pthread_mutex_lock(&psvr->lock); 733 | sendhdr.act = SU_SYN; 734 | sendhdr.type = SU_ORDINARY; 735 | sendhdr.seq = ++psvr->seq; 736 | sendhdr.ts = 0; 737 | msgsend.msg_name = (void*)destaddr; 738 | msgsend.msg_namelen = destlen; 739 | msgsend.msg_iov = &iovsend[0]; 740 | msgsend.msg_iovlen = 2; 741 | 742 | iovsend[0].iov_base = &sendhdr; 743 | iovsend[0].iov_len = sizeof(suhdr_t); 744 | iovsend[1].iov_base = (void*)outbuff; 745 | iovsend[1].iov_len = outbytes; 746 | 747 | n = sendmsg(psvr->fd, &msgsend, 0); 748 | pthread_mutex_unlock(&psvr->lock); 749 | 750 | if (n != sizeof(suhdr_t) + outbytes) 751 | return(-1); 752 | 753 | return(outbytes); 754 | } 755 | 756 | static int su_cmp_ack_SU_RELIABLE(suhdr_t *syn, suhdr_t *ack) 757 | { 758 | if ( 759 | SU_ACK == ack->act && 760 | syn->type == ack->type && 761 | syn->seq == ack->seq && 762 | syn->ts == ack->ts 763 | ) 764 | return 1; 765 | return 0; 766 | } 767 | 768 | static int su_serv_send_recv_act(su_serv_t *psvr, SA *destaddr, socklen_t destlen, 769 | const void *outbuff, int outbytes, void *inbuff, int inbytes, int retransmit) 770 | { 771 | int n; 772 | struct iovec iovsend[2]={{0}}; 773 | struct msghdr msgsend = {0}; /* assumed init to 0 */ 774 | suhdr_t *r, sendhdr = {0}; /* protocol header */ 775 | int ret, waitsec; 776 | 777 | struct list *node = 0; 778 | frames_t *packet = 0; 779 | 780 | pthread_mutex_lock(&psvr->mutex); 781 | pthread_mutex_lock(&psvr->lock); 782 | 783 | if (retransmit == 0) { 784 | psvr->seq++; 785 | psvr->retransmission = 1; 786 | } else { 787 | if (psvr->retransmission == 0) { 788 | pthread_mutex_unlock(&psvr->mutex); 789 | pthread_mutex_unlock(&psvr->lock); 790 | errno = ETIMEDOUT; 791 | return -1; 792 | } 793 | psvr->retransmission --; 794 | } 795 | 796 | if (psvr->rttinit == 0) { 797 | rtt_init(&psvr->rttinfo, psvr->retry); /* first time we're called */ 798 | psvr->rttinit = 1; 799 | } 800 | 801 | sendhdr.act = SU_SYN; 802 | sendhdr.type = SU_RELIABLE; 803 | sendhdr.sid = psvr->sid; 804 | sendhdr.seq = psvr->seq; 805 | msgsend.msg_name = (void*)destaddr; 806 | msgsend.msg_namelen = destlen; 807 | msgsend.msg_iov = iovsend; 808 | msgsend.msg_iovlen = 2; 809 | 810 | iovsend[0].iov_base = (void*)&sendhdr; 811 | iovsend[0].iov_len = sizeof(suhdr_t); 812 | iovsend[1].iov_base = (void*)outbuff; 813 | iovsend[1].iov_len = outbytes; 814 | 815 | struct timespec abstime = {0}; 816 | suhdr_t *precvhdr; 817 | 818 | rtt_newpack(&psvr->rttinfo); /* initialize for this packet */ 819 | psvr->ackwaitnum ++; 820 | 821 | sendagain: 822 | sendhdr.ts = rtt_ts(&psvr->rttinfo); 823 | if (sendmsg(psvr->fd, &msgsend, 0) < 0) { 824 | ERR_RET("sendmsg error"); 825 | goto error_ret; 826 | } 827 | 828 | waitsec = rtt_start(&psvr->rttinfo); /* calc timeout value & start timer */ 829 | #ifdef SU_DEBUG_RTT 830 | fprintf(stderr, ColorRed "send seq %4d: " ColorEnd, sendhdr.seq); 831 | rtt_debug(&psvr->rttinfo); 832 | #endif 833 | 834 | /* set timed wait time-point */ 835 | maketimeout_seconds(&abstime, waitsec); 836 | 837 | #ifdef SU_DEBUG_TIMEVERBOSE 838 | struct timeval now; 839 | gettimeofday(&now, 0); 840 | log_msg( ColorBlue "pthread_cond_timedwait : %u.%u time expire" ColorEnd, 841 | abstime.tv_sec, abstime.tv_nsec); 842 | log_msg( ColorBlue "pthread_cond_timedwait : %d.%d now time" ColorEnd, 843 | now.tv_sec, now.tv_usec*1000); 844 | #endif 845 | 846 | timedwaitagain: 847 | ret = pthread_cond_timedwait(&psvr->ackcond, &psvr->lock, &abstime); 848 | if (ret == 0) { 849 | #ifdef SU_DEBUG_TIMEVERBOSE 850 | struct timeval now; 851 | gettimeofday(&now, 0); 852 | log_msg(ColorBlue "pthread_cond_timedwait : %d.%d ack cond interrupt" ColorEnd, 853 | now.tv_sec, now.tv_usec*1000); 854 | #endif 855 | node = psvr->ackrecvls.next; 856 | for (; node != &psvr->ackrecvls; node = node->next) { 857 | packet = container_of(node, frames_t, node); 858 | r = &packet->recvhdr; 859 | if (su_cmp_ack_SU_RELIABLE(&sendhdr, r)) { break; } 860 | } 861 | if ( node == &psvr->ackrecvls ) { 862 | /* Be careful of the lock, locked -> timedwait -> unlock */ 863 | #ifdef SU_DEBUG_LIST 864 | log_msg("serv %x no found seq %d ack, timed wait again", psvr, sendhdr.seq); 865 | #endif 866 | goto timedwaitagain; 867 | } 868 | 869 | /* Find response packet node */ 870 | list_remove(&packet->node); 871 | 872 | n = packet->len; 873 | precvhdr = &packet->recvhdr; 874 | 875 | #if defined SU_DEBUG_PEER_RECV || defined SU_DEBUG_LIST 876 | log_msg("serv %x finded ack " ColorRed "%p" ColorEnd " seq %d datagram len %d", 877 | psvr, packet, r->seq, packet->len); 878 | #endif 879 | 880 | #ifdef SU_DEBUG_RTT 881 | fprintf(stderr, ColorRed "recv seq %4d \n" ColorEnd, precvhdr->seq); 882 | #endif 883 | // SU_RELIABLE received response, copy to user buffer 884 | memcpy(inbuff, packet->data, n > inbytes ? inbytes : n); 885 | 886 | } else if (ret == EINTR) { 887 | log_msg("pthread_cond_timedwait system EINTR"); 888 | goto timedwaitagain; 889 | } else if (ret == ETIMEDOUT) { 890 | #ifdef SU_DEBUG_TIMEVERBOSE 891 | struct timeval now; 892 | gettimeofday(&now, 0); 893 | log_msg(ColorBlue "pthread_cond_timedwait : %u.%u ETIMEOUT have expired" ColorEnd, 894 | now.tv_sec, now.tv_usec*1000); 895 | #endif 896 | if (rtt_timeout(&psvr->rttinfo) < 0) { 897 | #ifdef SU_DEBUG_RTT 898 | err_msg(ColorYel "no response from server, giving up" ColorEnd); 899 | #endif 900 | psvr->rttinit = 0; /* reinit in case we're called again */ 901 | errno = ETIMEDOUT; 902 | goto error_ret; 903 | } 904 | #ifdef SU_DEBUG_RTT 905 | err_msg(ColorRed " seq %4d timeout, retransmitting %d" ColorEnd, 906 | sendhdr.seq, ++retransmit); 907 | #endif 908 | goto sendagain; 909 | } else { 910 | errno = ret; 911 | ERR_RET(" su_serv_send_recv_act unknown error[%d]", ret); 912 | goto error_ret; 913 | } 914 | 915 | /* calculate & store new RTT estimator values */ 916 | rtt_stop(&psvr->rttinfo, rtt_ts(&psvr->rttinfo) - precvhdr->ts); 917 | 918 | if (--psvr->ackwaitnum == 0) { 919 | su_serv_list_empty(psvr, &psvr->ackrecvls); 920 | } 921 | pthread_mutex_unlock(&psvr->mutex); 922 | pthread_mutex_unlock(&psvr->lock); 923 | 924 | #ifdef SU_DEBUG_LIST 925 | log_msg("serv %x free node " ColorRed "%p"ColorEnd" seq %d", psvr, packet, sendhdr.seq); 926 | #endif 927 | 928 | free(packet); 929 | 930 | return(n); /* return size of received datagram */ 931 | 932 | error_ret: 933 | if (--psvr->ackwaitnum == 0) { 934 | su_serv_list_empty(psvr, &psvr->ackrecvls); 935 | } 936 | pthread_mutex_unlock(&psvr->mutex); 937 | pthread_mutex_unlock(&psvr->lock); 938 | return(-1); 939 | } 940 | 941 | void su_serv_reply_ignore_act(su_serv_t *psvr, frames_t* frame) 942 | { 943 | rb_key_cache_t key; 944 | memcpy(&key.destaddr, &frame->srcaddr, sizeof(SAUN)); 945 | key.destlen = frame->srclen; 946 | key.seq = frame->recvhdr.seq; 947 | key.sid = frame->recvhdr.sid; 948 | 949 | struct rb_node *cachenode; 950 | cache_t *frees; 951 | 952 | if ((cachenode = rb_search(&psvr->rbackcache, &key))) { 953 | frees = rb_entry(cachenode, cache_t, rbn); 954 | list_remove (&frees->frame.node); 955 | rb_erase (&frees->rbn, &psvr->rbackcache); 956 | free(frees); 957 | return; 958 | } 959 | } 960 | 961 | void su_serv_reply_ignore(su_serv_t *psvr, frames_t *frame) 962 | { 963 | if (psvr == 0 || frame == 0) { return; } 964 | pthread_mutex_lock(&psvr->cachelock); 965 | su_serv_reply_ignore_act(psvr, frame); 966 | pthread_mutex_unlock(&psvr->cachelock); 967 | } 968 | 969 | int su_serv_reply(su_serv_t *psvr, frames_t *frame, const void *outbuff, int outbytes) 970 | { 971 | if (psvr == 0 || frame == 0) { errno = EINVAL; return -1; } 972 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 973 | if ( (outbytes < 0) || 974 | (outbytes == 0 && outbuff) || 975 | (outbytes > 0 && !outbuff) ) 976 | { errno = EINVAL; return -1; } 977 | return su_serv_reply_act(psvr, frame, outbuff, outbytes); 978 | } 979 | 980 | int su_serv_reply_ack(su_serv_t *psvr, frames_t *frame) 981 | { 982 | if (psvr == 0 || frame == 0) { errno = EINVAL; return -1; } 983 | return su_serv_reply_act(psvr, frame, 0, 0); 984 | } 985 | 986 | int su_serv_send(su_serv_t *psvr, SA* destaddr, socklen_t destlen, const void *outbuff, int outbytes) 987 | { 988 | if (psvr == 0) { errno = EINVAL; return -1; } 989 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 990 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 991 | return su_serv_send_act(psvr, destaddr, destlen, outbuff, outbytes); 992 | } 993 | 994 | int su_serv_request(su_serv_t *psvr, SA *destaddr, socklen_t destlen, 995 | const void *outbuff, int outbytes, void *inbuff, int inbytes) 996 | { 997 | if (psvr == 0) { errno = EINVAL; return -1; } 998 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 999 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 1000 | if (inbytes <= 0 || inbuff== 0) { errno = EINVAL; return -1;} 1001 | return su_serv_send_recv_act(psvr, destaddr, destlen, outbuff, outbytes, inbuff, inbytes, 0); 1002 | } 1003 | 1004 | int su_serv_request_retry(su_serv_t *psvr, SA *destaddr, socklen_t destlen, 1005 | const void *outbuff, int outbytes, void *inbuff, int inbytes) 1006 | { 1007 | if (psvr == 0) { errno = EINVAL; return -1; } 1008 | if (outbytes > REALDATAMAX) { errno = EMSGSIZE; return -1; } 1009 | if (outbytes <= 0 || outbuff == 0) { errno = EINVAL; return -1;} 1010 | if (inbytes <= 0 || inbuff== 0) { errno = EINVAL; return -1;} 1011 | return su_serv_send_recv_act(psvr, destaddr, destlen, outbuff, outbytes, inbuff, inbytes, 1); 1012 | } 1013 | -------------------------------------------------------------------------------- /sarudp_serv.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_SARUDP_SERV_H__ 2 | #define __YH_SARUDP_SERV_H__ 3 | 4 | #include "sarudp_comm.h" 5 | 6 | typedef struct sar_udp_serv su_serv_t; 7 | typedef void cb_su_serv_receiver_t(su_serv_t *ps, frames_t* frame, char* buff, int len); 8 | 9 | /* SYN/ACK/Retransfer UDP serv manager */ 10 | struct sar_udp_serv { 11 | /* foreign host info */ 12 | int fd; 13 | SAUN servaddr; 14 | socklen_t servlen; 15 | uint16_t sid; /* zero */ 16 | uint32_t seq; 17 | struct rtt_info rttinfo; 18 | int retry; 19 | int retransmission; 20 | int rttinit; 21 | 22 | /* event driver */ 23 | fe_t fe; 24 | cb_su_serv_receiver_t * reliable_request_handle; 25 | cb_su_serv_receiver_t * ordinary_request_handle; 26 | 27 | pthread_t *tids; 28 | int run; 29 | int tnum; 30 | 31 | pthread_mutex_t mutex; /* Protect single line to send */ 32 | pthread_mutex_t lock; 33 | pthread_cond_t ackcond; 34 | pthread_cond_t syncond; 35 | 36 | int ackwaitnum; /* SU_RELIABLE Requester number */ 37 | 38 | /* frames_t list: foreign respnose */ 39 | struct list ackrecvls; /* SU_RELIABLE Reply of the foreign host */ 40 | 41 | /* frames_t list: foreign request */ 42 | struct list synrecvls; /* Receive foreign host the active request */ 43 | 44 | /* container cache_t: foreign reply result datas */ 45 | struct list lsackcache; /* The cache results for timeout check */ 46 | rb_root_t rbackcache; /* The cache results for re-syn search */ 47 | pthread_mutex_t cachelock; 48 | }; 49 | 50 | int su_serv_create(su_serv_t *psvr, const SA *saddr, socklen_t servlen, int nthread); 51 | void su_serv_destroy(su_serv_t *psvr); 52 | 53 | void su_serv_reliable_request_handle_install(su_serv_t *psvr, cb_su_serv_receiver_t* reliable_request_handle); 54 | void su_serv_ordinary_request_handle_install(su_serv_t *psvr, cb_su_serv_receiver_t* ordinary_request_handle); 55 | void su_serv_reliable_request_handle_uninstall(su_serv_t *psvr); 56 | void su_serv_ordinary_request_handle_uninstall(su_serv_t *psvr); 57 | 58 | int su_serv_send(su_serv_t *psar, SA*destaddr, socklen_t destlen, const void *outbuff, int outbytes); 59 | int su_serv_request(su_serv_t *psar, SA *destaddr, socklen_t destlen, const void *outbuff, int outbytes, void *inbuff, int inbytes); 60 | int su_serv_request_retry(su_serv_t *psar, SA *destaddr, socklen_t destlen, const void *outbuff, int outbytes, void *inbuff, int inbytes); 61 | 62 | int su_serv_reply(su_serv_t *psvr, frames_t *frame, const void *outbuff, int outbytes); 63 | int su_serv_reply_ack(su_serv_t *psvr, frames_t *frame); 64 | void su_serv_reply_ignore(su_serv_t *psvr, frames_t* frame); 65 | 66 | #endif /* __YH_SARUDP_SERV_H__ */ 67 | -------------------------------------------------------------------------------- /su_peer_client.c: -------------------------------------------------------------------------------- 1 | #include "sarudp_peer.h" 2 | #include "domain_parse.h" 3 | #include "wrapfunc.h" 4 | 5 | #include 6 | 7 | // handle SIGINT 8 | void sigint(int no); 9 | 10 | // handler reliable data come in 11 | void udpin_reliable(su_peer_t *psar, char *buff, int len); 12 | // handle ordinary data come in 13 | void udpin_ordinary(su_peer_t *psar, char *buff, int len); 14 | 15 | // test client ordinary 16 | void cli_su_peer_send(FILE *fp, su_peer_t *psar); 17 | 18 | // test client reliable 19 | void cli_su_peer_request_keyboard_input(FILE *fp, su_peer_t *psar); 20 | void cli_su_peer_request_random_recv_echo(su_peer_t *psar); 21 | 22 | int main(int argc, char **argv) 23 | { 24 | su_peer_t sar; 25 | char ip[256], errinfo[256]; 26 | int port; 27 | 28 | signal(SIGINT, sigint); 29 | 30 | if (argc != 2 && argc != 3) 31 | err_quit("usage: udpcli [Port Default 7]"); 32 | 33 | /* Targer address domain parse */ 34 | if (domain_parse(argv[1], ip, sizeof(ip), errinfo, sizeof(errinfo)) < 0) 35 | err_quit("Destination parse failed %s", errinfo); 36 | port = argc == 2 ? 7 : atoi(argv[2]); 37 | if (port <= 0 || port > 65535) 38 | err_quit("Port(1~65535) error: %s", argv[2]); 39 | log_msg("Destination %s:%d", ip, port); 40 | 41 | #if 1 42 | struct sockaddr_in servaddr; 43 | bzero(&servaddr, sizeof(servaddr)); 44 | servaddr.sin_family = PF_INET; 45 | servaddr.sin_port = htons(port); 46 | Inet_pton(AF_INET, ip, &servaddr.sin_addr); 47 | #else 48 | struct sockaddr_in6 servaddr; 49 | char ip6[INET6_ADDRSTRLEN]; 50 | bzero(&servaddr, sizeof(servaddr)); 51 | servaddr.sin6_family = PF_INET6; 52 | servaddr.sin6_port = htons(port); 53 | 54 | // IPv4 to IPv6 55 | snprintf(ip6, sizeof(ip6),"::ffff:%s", ip); 56 | log_msg("Target IPv6 %s", ip6); 57 | Inet_pton(AF_INET6, ip6, &servaddr.sin6_addr.s6_addr); 58 | #endif 59 | 60 | #if 1 61 | /* Using random free port */ 62 | if (su_peer_create(&sar, (SA*)&servaddr, sizeof(servaddr)) < 0) 63 | err_quit("su_peer_create error"); 64 | #else 65 | /* Using bind configure port */ 66 | if (su_peer_create_bind(&sar, 10000, (SA*)&servaddr, sizeof(servaddr)) < 0) 67 | err_sys("su_peer_create_bind error"); 68 | #endif 69 | 70 | /* Install the reliable request handler */ 71 | su_peer_reliable_request_handle_install(&sar, udpin_reliable); 72 | /* Install the ordinary request handler */ 73 | su_peer_ordinary_request_handle_install(&sar, udpin_ordinary); 74 | 75 | #if 1 76 | // send reliable data to target 77 | cli_su_peer_request_keyboard_input(stdin, &sar); 78 | //cli_su_peer_request_random_recv_echo(&sar); 79 | #else 80 | // send ordinary data to target 81 | cli_su_peer_send(stdin, &sar); 82 | #endif 83 | 84 | return 0; 85 | exit(0); 86 | } 87 | 88 | void udpin_reliable(su_peer_t *psar, char *buff, int len) 89 | { 90 | SAUN saddr; 91 | char ip[INET6_ADDRSTRLEN]; 92 | int port; 93 | 94 | su_peer_getsrcaddr(psar, &saddr); 95 | su_get_ip_port(&saddr, ip, sizeof(ip), &port); 96 | 97 | printf("reliable recv from %s:%d datagrams len %d " 98 | ColorGre "%s\n" ColorEnd, 99 | ip, port, len, buff); 100 | 101 | su_peer_reply(psar, buff, len); 102 | } 103 | void udpin_ordinary(su_peer_t *psar, char *buff, int len) 104 | { 105 | SAUN saddr; 106 | char ip[INET6_ADDRSTRLEN]; 107 | int port; 108 | 109 | su_peer_getsrcaddr(psar, &saddr); 110 | su_get_ip_port(&saddr, ip, sizeof(ip), &port); 111 | 112 | printf("ordinary recv from %s:%d datagram len %d " 113 | ColorGre "%s\n" ColorEnd, 114 | ip, port, len, buff); 115 | } 116 | 117 | void sigint(int no) 118 | { 119 | log_msg(ColorRed "\nSIGINT\n" ColorEnd); 120 | exit(0); 121 | } 122 | 123 | #define MAXLINE 4096 /* max text line length */ 124 | 125 | void cli_su_peer_request_keyboard_input(FILE *fp, su_peer_t *psar) 126 | { 127 | ssize_t n, ret; 128 | char sendline[MAXLINE], recvline[MAXLINE + 1]; 129 | char outline[MAXLINE + 128]; 130 | 131 | do { 132 | if (Fgets(sendline, MAXLINE, fp) == NULL) { 133 | fprintf(stdout, "\n"); 134 | return ; 135 | } 136 | 137 | ret = su_peer_request(psar, sendline, strlen(sendline), recvline, MAXLINE); 138 | if (ret < 0) 139 | err_ret("su_peer_send_recv error"); 140 | else if (ret > 0) { 141 | /* Foreign Host Receive successful and have a response */ 142 | recvline[ret] = 0; /* null terminate */ 143 | n = snprintf(outline, sizeof(outline), "\e[32m%s\e[m", recvline); 144 | write(2, outline, n); 145 | } else { 146 | fprintf(stdout, "Foreign Host Receive successful\n"); 147 | } 148 | } while (1); 149 | } 150 | 151 | void cli_su_peer_request_random_recv_echo(su_peer_t *psar) 152 | { 153 | ssize_t n, m; 154 | char sendline[MAXLINE], recvline[MAXLINE + 1] = {0}; 155 | 156 | srand(time(0)); 157 | 158 | do { 159 | n = snprintf(sendline, sizeof(sendline), "%05d", rand()%10000); 160 | m = n; 161 | log_msg("send request %d[%s]", n, sendline); 162 | n = su_peer_request(psar, sendline, n, recvline, MAXLINE); 163 | if (n < 0) { 164 | err_ret("su_peer_request error"); 165 | n = su_peer_request_retry(psar, sendline, strlen(sendline), recvline, MAXLINE); 166 | if (n < 0) { 167 | err_ret("su_peer_request_retry error"); 168 | break; 169 | } 170 | } 171 | 172 | recvline[n] = 0; /* null terminate */ 173 | log_msg("recv response %d[\e[32m%s\e[m]", n, recvline); 174 | 175 | if (memcmp(sendline, recvline, m) != 0) { 176 | err_quit("checkout data failure"); 177 | } 178 | log_msg("checkout data pass"); 179 | 180 | usleep(10 * 1000); // microsecond 181 | } while (1); 182 | } 183 | 184 | void cli_su_peer_send(FILE *fp, su_peer_t *psar) 185 | { 186 | ssize_t n; 187 | char sendline[MAXLINE]; 188 | 189 | do { 190 | if (Fgets(sendline, MAXLINE, fp) == NULL) { 191 | fprintf(stdout, "\n"); 192 | return ; 193 | } 194 | 195 | n = su_peer_send(psar, sendline, strlen(sendline)); 196 | if (n < 0) 197 | err_quit("su_peer_send error"); 198 | else 199 | log_msg("su_peer_send ok"); 200 | 201 | } while (1); 202 | } 203 | -------------------------------------------------------------------------------- /su_peer_server.c: -------------------------------------------------------------------------------- 1 | #include "sarudp_peer.h" 2 | #include "domain_parse.h" 3 | #include "wrapfunc.h" 4 | 5 | #include 6 | 7 | // test client ordinary 8 | void sar_cli_send(FILE *fp, su_peer_t *psar); 9 | // test client reliable 10 | void sar_cli_send_recv(FILE *fp, su_peer_t *psar); 11 | 12 | // handler reliable data come in 13 | void udpin_reliable(su_peer_t *psar, char *buff, int len); 14 | // handle ordinary data come in 15 | void udpin_ordinary(su_peer_t *psar, char *buff, int len); 16 | 17 | // handle SIGINT 18 | void sigint(int no); 19 | 20 | /* * 21 | * This program working promiscuous mode 22 | * Using macro 23 | * #define promiscuous_mode 24 | * compiling SARUDP Library 25 | * */ 26 | int main(int argc, char **argv) 27 | { 28 | su_peer_t sar; 29 | 30 | signal(SIGINT, sigint); 31 | 32 | if (argc != 1 && argc != 2) 33 | err_quit("usage: %s [Port Default 10000]", argv[0]); 34 | 35 | char *bindip; 36 | 37 | #if 1 38 | /* The address is not used as a client, can be arbitrarily set */ 39 | bindip = "127.0.0.1"; /* if define promiscuous_mode, only receive from 127.0.0.1 */ 40 | struct sockaddr_in servaddr; 41 | bzero(&servaddr, sizeof(servaddr)); 42 | servaddr.sin_family = AF_INET; 43 | servaddr.sin_port = htons(65535); 44 | Inet_pton(AF_INET, bindip, &servaddr.sin_addr); 45 | #else 46 | bindip = "::1"; 47 | struct sockaddr_in6 servaddr; 48 | bzero(&servaddr, sizeof(servaddr)); 49 | servaddr.sin6_family = AF_INET6; 50 | servaddr.sin6_port = htons(65535); 51 | //Inet_pton(AF_INET6, "::ffff:127.0.0.1", &servaddr.sin6_addr); // for test localhost IPv6 52 | Inet_pton(AF_INET6, bindip, &servaddr.sin6_addr); // for test localhost IPv6 53 | #endif 54 | 55 | #if 0 56 | if (su_peer_create(&sar, (SA*)&servaddr, sizeof(servaddr)) < 0) 57 | err_quit("su_peer_create error"); 58 | #else 59 | if (su_peer_create_bind(&sar, argc == 1 ? 10000 : atoi(argv[1]), 60 | (SA*)&servaddr, sizeof(servaddr)) < 0) 61 | err_sys("su_peer_create_bind error"); 62 | log_msg("sarudp bind and receive from %s:%s", bindip, argc == 1 ? "10000" : argv[1]); 63 | #endif 64 | 65 | su_peer_reliable_request_handle_install(&sar, udpin_reliable); 66 | su_peer_ordinary_request_handle_install(&sar, udpin_ordinary); 67 | 68 | #if 1 69 | while (1) 70 | pause(); 71 | #else 72 | sleep(30); 73 | su_peer_destroy(&sar); 74 | #endif 75 | 76 | exit(0); 77 | } 78 | 79 | void udpin_reliable(su_peer_t *psar, char *buff, int len) 80 | { 81 | static long long c=0; 82 | SAUN s; 83 | char ip[INET6_ADDRSTRLEN]; 84 | int port; 85 | 86 | su_peer_getsrcaddr(psar, &s); 87 | 88 | //su_get_ip_port(&s, ip, sizeof(ip), &port); // small ip address 89 | su_get_ip_port_f(&s, ip, sizeof(ip), &port); // fulll ip address 90 | 91 | printf("reliable recv from %s:%d datagram len %d\n", ip, port, len); 92 | printf("reliable recv len %d datagrams " 93 | ColorGre "%s" ColorEnd " count = %llu\n", 94 | len, buff, c+=len); 95 | 96 | int n; 97 | #if 1 98 | n = su_peer_reply(psar, buff, len); 99 | #else 100 | n = su_peer_reply_ack(psar); 101 | #endif 102 | if (n < 0) { 103 | ERR_RET("su_peer_reply error"); 104 | } 105 | } 106 | void udpin_ordinary(su_peer_t *psar, char *buff, int len) 107 | { 108 | static long long c=0; 109 | SAUN s; 110 | char ip[INET6_ADDRSTRLEN]; 111 | int port; 112 | 113 | su_peer_getsrcaddr(psar, &s); 114 | 115 | //su_get_ip_port(&s, ip, sizeof(ip), &port); // small ip address 116 | su_get_ip_port_f(&s, ip, sizeof(ip), &port); // fulll ip address 117 | 118 | printf("ordinary recv from %s:%d datagrams len %d\n", ip, port, len); 119 | printf("ordinary recv len %d datagrams " 120 | ColorYel "%s" ColorEnd " count = %llu\n", 121 | len, buff, c+=len); 122 | 123 | //su_peer_reply(psar, buff, len); // call is invalid, ordinary packet don't handle reply 124 | 125 | // response data (echo) 126 | if (su_peer_send(psar, buff, len) != len) { // call is valid 127 | err_ret("su_peer_send error"); 128 | } 129 | } 130 | 131 | void sigint(int no) 132 | { 133 | log_msg(ColorRed "\nSIGINT\n" ColorEnd); 134 | exit(0); 135 | } 136 | -------------------------------------------------------------------------------- /su_serv_server.c: -------------------------------------------------------------------------------- 1 | #include "domain_parse.h" 2 | #include "wrapfunc.h" 3 | 4 | #include "sarudp_peer.h" 5 | #include "sarudp_serv.h" 6 | 7 | #include "yhdaemon.h" 8 | #include "yharguments.h" 9 | 10 | #include 11 | 12 | 13 | // handle SIGINT 14 | void sigint(int no); 15 | 16 | void reliable_data_in(su_serv_t *psar, frames_t *frame, char *buff, int len); 17 | void ordinary_data_in(su_serv_t *psar, frames_t *frame, char *buff, int len); 18 | 19 | int main(int argc, char **argv) 20 | { 21 | su_serv_t svr; 22 | 23 | signal(SIGINT, sigint); 24 | 25 | if (argc == 1) { 26 | usage(argc, argv); 27 | exit(1); 28 | } 29 | 30 | arguments(argc, argv); 31 | 32 | if (daemond) 33 | daemon_init(0, 0, 0, 0); 34 | 35 | #if 0 36 | struct sockaddr_in servaddr; 37 | bzero(&servaddr, sizeof(servaddr)); 38 | servaddr.sin_family = AF_INET; 39 | servaddr.sin_port = htons(port); 40 | Inet_pton(AF_INET, "0.0.0.0", &servaddr.sin_addr); 41 | #else 42 | struct sockaddr_in6 servaddr; 43 | bzero(&servaddr, sizeof(servaddr)); 44 | servaddr.sin6_family = AF_INET6; 45 | servaddr.sin6_port = htons(port); 46 | Inet_pton(AF_INET6, "::", &servaddr.sin6_addr); 47 | #endif 48 | 49 | if (su_serv_create(&svr, (SA*)&servaddr, sizeof(servaddr), 10) < 0) 50 | err_sys("su_serv_create error"); 51 | 52 | log_msg("serv %x sarudp listen port %d", &svr, port); 53 | 54 | su_serv_reliable_request_handle_install(&svr, reliable_data_in); 55 | su_serv_ordinary_request_handle_install(&svr, ordinary_data_in); 56 | 57 | #if 1 58 | /* Service forever */ 59 | while (1) 60 | pause(); 61 | #else 62 | /* After 30 seconds to stop the service */ 63 | sleep(30); 64 | su_serv_destroy(&svr); 65 | #endif 66 | 67 | exit(0); 68 | } 69 | 70 | void sigint(int no) 71 | { 72 | log_msg(ColorRed "\nSIGINT\n" ColorEnd); 73 | exit(0); 74 | } 75 | void reliable_data_in(su_serv_t *psar, frames_t *frame, char *buff, int len) 76 | { 77 | char ipbuff[INET6_ADDRSTRLEN]; 78 | int port; 79 | 80 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 81 | 82 | log_msg("reliable recv from %s:%d datagrams len %d " ColorGre"%s"ColorEnd, 83 | ipbuff, port, len, buff); 84 | 85 | int n; 86 | #if 1 87 | n = su_serv_reply(psar, frame, buff, len); 88 | #else 89 | n = su_serv_reply_ack(psar, frame); 90 | #endif 91 | if (n < 0) { 92 | ERR_RET("su_peer_reply error"); 93 | } 94 | } 95 | void ordinary_data_in(su_serv_t *psar, frames_t *frame, char *buff, int len) 96 | { 97 | char ipbuff[INET6_ADDRSTRLEN]; 98 | int port; 99 | 100 | su_get_ip_port(&frame->srcaddr, ipbuff, sizeof(ipbuff), &port); 101 | 102 | log_msg("ordinary recv from %s:%d datagrams len %d " ColorGre"%s"ColorEnd, 103 | ipbuff, port, len, buff); 104 | 105 | //su_serv_reply(psar, frame, buff, len); // call is invalid, ordinary packet don't handle reply 106 | su_serv_send(psar, (SA*)&frame->srcaddr, frame->srclen, buff, len); // call is valid 107 | } 108 | -------------------------------------------------------------------------------- /unprtt.h: -------------------------------------------------------------------------------- 1 | #ifndef __unp_rtt_h 2 | #define __unp_rtt_h 3 | 4 | #include 5 | #include 6 | 7 | struct rtt_info { 8 | float rtt_rtt; /* most recent measured RTT, seconds */ 9 | float rtt_srtt; /* smoothed RTT estimator, seconds */ 10 | float rtt_rttvar; /* smoothed mean deviation, seconds */ 11 | float rtt_rto; /* current RTO to use, seconds */ 12 | int rtt_nrexmt; /* #times retransmitted: 0, 1, 2, ... */ 13 | uint32_t rtt_base; /* #sec since 1/1/1970 at start */ 14 | uint8_t rtt_retry; 15 | }; 16 | 17 | #define RTT_RXTMIN 2 /* min retransmit timeout value, seconds */ 18 | #define RTT_RXTMAX 60 /* max retransmit timeout value, seconds */ 19 | #define RTT_MAXNREXMT 4 /* max #times to retransmit */ 20 | #define RTT_MAXRTO 12 21 | 22 | /* function prototypes */ 23 | void rtt_debug(struct rtt_info *); 24 | void rtt_init(struct rtt_info *, uint8_t); 25 | void rtt_newpack(struct rtt_info *); 26 | int rtt_start(struct rtt_info *); 27 | void rtt_stop(struct rtt_info *, uint32_t); 28 | int rtt_timeout(struct rtt_info *); 29 | uint32_t rtt_ts(struct rtt_info *); 30 | 31 | extern int rtt_d_flag; /* can be set nonzero for addl info */ 32 | 33 | #endif /* __unp_rtt_h */ 34 | -------------------------------------------------------------------------------- /wrapfunc.c: -------------------------------------------------------------------------------- 1 | #include "wrapfunc.h" 2 | #include "error.h" 3 | #include "sarudp_peer.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | const char * 10 | Inet_ntop(int family, const void *addrptr, char *strptr, size_t len) 11 | { 12 | const char *ptr; 13 | 14 | if (strptr == NULL) /* check for old code */ 15 | err_quit("NULL 3rd argument to inet_ntop"); 16 | if ( (ptr = inet_ntop(family, addrptr, strptr, len)) == NULL) 17 | err_sys("inet_ntop error"); /* sets errno */ 18 | return(ptr); 19 | } 20 | 21 | void 22 | Inet_pton(int family, const char *strptr, void *addrptr) 23 | { 24 | int n; 25 | 26 | if ( (n = inet_pton(family, strptr, addrptr)) < 0) 27 | err_sys("inet_pton error for %s", strptr); /* errno set */ 28 | else if (n == 0) 29 | err_quit("inet_pton error for %s", strptr); /* errno not set */ 30 | 31 | /* nothing to return */ 32 | } 33 | 34 | void 35 | Gettimeofday(struct timeval *tv, void *foo) 36 | { 37 | if (gettimeofday(tv, foo) == -1) 38 | err_sys("gettimeofday error"); 39 | return; 40 | } 41 | 42 | char * 43 | Fgets(char *ptr, int n, FILE *stream) 44 | { 45 | char *rptr; 46 | 47 | if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream)) 48 | err_sys("fgets error"); 49 | 50 | return (rptr); 51 | } 52 | 53 | void 54 | Sendmsg(int fd, const struct msghdr *msg, int flags) 55 | { 56 | unsigned int i; 57 | ssize_t nbytes; 58 | 59 | nbytes = 0; /* must first figure out what return value should be */ 60 | for (i = 0; i < msg->msg_iovlen; i++) 61 | nbytes += msg->msg_iov[i].iov_len; 62 | 63 | if (sendmsg(fd, msg, flags) != nbytes) 64 | err_sys("sendmsg error"); 65 | } 66 | -------------------------------------------------------------------------------- /wrapfunc.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_WRAPFUNC_H__ 2 | #define __YH_WRAPFUNC_H__ 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | void Gettimeofday(struct timeval *, void *); 15 | 16 | void Fclose(FILE *); 17 | FILE *Fdopen(int, const char *); 18 | char *Fgets(char *, int, FILE *); 19 | FILE *Fopen(const char *, const char *); 20 | void Fputs(const char *, FILE *); 21 | 22 | const char *Inet_ntop(int, const void *, char *, size_t); 23 | void Inet_pton(int, const char *, void *); 24 | 25 | void Sendmsg(int, const struct msghdr *, int); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif /* __YH_WRAPFUNC_H__ */ 32 | 33 | 34 | -------------------------------------------------------------------------------- /yharguments.c: -------------------------------------------------------------------------------- 1 | #include "yharguments.h" 2 | #include "yherror.h" 3 | 4 | int port = -1; 5 | int daemond = 0; 6 | int optp; 7 | 8 | static struct option opt[] = { 9 | {"port", 1, 0, 'p'}, 10 | {"daemon", 0, 0, 'd'}, 11 | {"help", 0, 0, 'h'}, 12 | {0,0,0,0} 13 | }; 14 | void usage(int argc, char **argv) 15 | { 16 | err_msg("usage: %s [port] [option[=value]]...", argv[0]); 17 | err_msg(" -p, --port=number Service port(range 1~65535), like [port]"); 18 | err_msg(" but the priority is higher than [port]"); 19 | err_msg(" -d, --daemon Daemon mode"); 20 | err_msg(" -h, --help Usage help"); 21 | } 22 | 23 | void port_check(int argc, char **argv, int port, char *strport) 24 | { 25 | if (port <= 0) { 26 | err_msg("bad parameter: port %s", strport); 27 | usage(argc, argv); 28 | exit(1); 29 | } 30 | } 31 | 32 | void arguments(int argc, char **argv) 33 | { 34 | char c; 35 | opterr = 1; 36 | while ((c = getopt_long(argc,argv,"p:dh", opt, 0)) != -1) { 37 | switch (c) { 38 | case 'p': 39 | port = atoi(optarg); 40 | port_check(argc, argv, port, optarg); 41 | optp = 1; 42 | break; 43 | case 'd': 44 | daemond = 1; 45 | break; 46 | case 'h': 47 | usage(argc, argv); 48 | exit(0); 49 | case '?': 50 | err_quit("Try '%s --help' for more information.", argv[0]); 51 | default : 52 | usage(argc, argv); 53 | exit(1); 54 | } 55 | } 56 | if (optp == 0) { 57 | port = atoi(argv[argc-1]); 58 | port_check(argc, argv, port, argv[argc-1]); 59 | optp = 1; 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /yharguments.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_ARGUMENTS_H__ 2 | #define __YH_ARGUMENTS_H__ 3 | 4 | #include "error.h" 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | extern int port, daemond; 11 | 12 | #ifdef __cplusplus 13 | extern "C" 14 | { 15 | #endif 16 | 17 | 18 | void arguments(int argc, char **argv); 19 | void usage(int argc, char **argv); 20 | 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | #endif 26 | -------------------------------------------------------------------------------- /yhdaemon.c: -------------------------------------------------------------------------------- 1 | #include "yhdaemon.h" 2 | 3 | 4 | extern int daemon_proc; /* defined in yh error.c */ 5 | 6 | 7 | typedef void (*sighandler_t)(int); 8 | 9 | sighandler_t 10 | Signal(int signo, sighandler_t func) /* for our signal() function */ 11 | { 12 | sighandler_t sigfunc; 13 | 14 | if ( (sigfunc = signal(signo, func)) == SIG_ERR) 15 | err_sys("signal error"); 16 | return(sigfunc); 17 | } 18 | 19 | pid_t 20 | Fork(void) 21 | { 22 | pid_t pid; 23 | 24 | if ( (pid = fork()) == -1) 25 | err_sys("fork error"); 26 | return(pid); 27 | } 28 | int 29 | Open(const char *pathname, int flags) 30 | { 31 | int fd; 32 | fd = open(pathname, flags); 33 | if (fd < 0) 34 | err_sys("open error"); 35 | return fd; 36 | } 37 | void 38 | Dup2(int fd1, int fd2) 39 | { 40 | if (dup2(fd1, fd2) == -1) 41 | err_sys("dup2 error"); 42 | } 43 | 44 | void 45 | Close(int fd) 46 | { 47 | if (close(fd) < 0) 48 | err_sys("close error"); 49 | } 50 | 51 | void 52 | daemon_init(const char *pname, int facility, int nochdir, int noclose) 53 | { 54 | pid_t pid; 55 | 56 | if ( (pid = Fork()) != 0) 57 | exit(0); /* parent terminates */ 58 | 59 | /* 41st child continues */ 60 | setsid(); /* become session leader */ 61 | 62 | Signal(SIGHUP, SIG_IGN); 63 | if ( (pid = Fork()) != 0) 64 | exit(0); /* 1st child terminates */ 65 | 66 | /* 42nd child continues */ 67 | if (nochdir == 0) 68 | chdir("/"); /* change working directory */ 69 | 70 | umask(0); /* clear our file mode creation mask */ 71 | 72 | if (noclose == 0) { 73 | int fd = Open("/dev/null", O_RDWR); 74 | Dup2(fd, 0); 75 | Dup2(fd, 1); 76 | Dup2(fd, 2); 77 | if (fd > 2) 78 | Close(fd); 79 | } 80 | 81 | daemon_proc = 1; /* for our err_XXX() functions */ 82 | 83 | openlog(pname, LOG_PID, facility); 84 | } 85 | -------------------------------------------------------------------------------- /yhdaemon.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_YHDAEMON_H__ 2 | #define __YH_YHDAEMON_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "yherror.h" 14 | 15 | #ifdef __cplusplus 16 | extern "C" 17 | { 18 | #endif 19 | 20 | #pragma pack(push) 21 | #pragma pack(1) 22 | #pragma pack(pop) 23 | 24 | 25 | // If nochdir is zero, daemon_init() changes the calling process's current working directory to the root directory ("/"); 26 | // otherwise, the current working directory is left unchanged. 27 | // If noclose is zero, daemon() redirects standard input, standard output and standard error to /dev/null; 28 | // otherwise, no changes are made to these file descriptors. 29 | void daemon_init(const char *pname, int facility, int nochdir, int noclose); 30 | 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | #endif /* __YH_YHDAEMON_H__ */ 36 | -------------------------------------------------------------------------------- /yherror.c: -------------------------------------------------------------------------------- 1 | #include "yherror.h" 2 | 3 | 4 | int daemon_proc; /* set nonzero by daemon_init() */ 5 | 6 | static void err_doit(int, int, const char *, va_list); 7 | 8 | /* Nonfatal error related to a system call. 9 | * Print a message and return. */ 10 | 11 | /* $$.ix [err_ret]~function,~source~code$$ */ 12 | void 13 | err_ret(const char *fmt, ...) 14 | { 15 | va_list ap; 16 | 17 | va_start(ap, fmt); 18 | err_doit(1, LOG_INFO, fmt, ap); 19 | va_end(ap); 20 | return; 21 | } 22 | 23 | /* Fatal error related to a system call. 24 | * Print a message and terminate. */ 25 | 26 | /* $$.ix [err_sys]~function,~source~code$$ */ 27 | void 28 | err_sys(const char *fmt, ...) 29 | { 30 | va_list ap; 31 | 32 | va_start(ap, fmt); 33 | err_doit(1, LOG_ERR, fmt, ap); 34 | va_end(ap); 35 | exit(1); 36 | } 37 | 38 | /* Fatal error related to a system call. 39 | * Print a message, dump core, and terminate. */ 40 | 41 | /* $$.ix [err_dump]~function,~source~code$$ */ 42 | void 43 | err_dump(const char *fmt, ...) 44 | { 45 | va_list ap; 46 | 47 | va_start(ap, fmt); 48 | err_doit(1, LOG_ERR, fmt, ap); 49 | va_end(ap); 50 | abort(); /* dump core and terminate */ 51 | exit(1); /* shouldn't get here */ 52 | } 53 | 54 | /* Nonfatal error unrelated to a system call. 55 | * Print a message and return. */ 56 | 57 | /* $$.ix [err_msg]~function,~source~code$$ */ 58 | void 59 | err_msg(const char *fmt, ...) 60 | { 61 | va_list ap; 62 | 63 | va_start(ap, fmt); 64 | err_doit(0, LOG_INFO, fmt, ap); 65 | va_end(ap); 66 | return; 67 | } 68 | 69 | /* Fatal error unrelated to a system call. 70 | * Print a message and terminate. */ 71 | 72 | /* $$.ix [err_quit]~function,~source~code$$ */ 73 | void 74 | err_quit(const char *fmt, ...) 75 | { 76 | va_list ap; 77 | 78 | va_start(ap, fmt); 79 | err_doit(0, LOG_ERR, fmt, ap); 80 | va_end(ap); 81 | exit(1); 82 | } 83 | 84 | /* Print a message and return to caller. 85 | * Caller specifies "errnoflag" and "level". */ 86 | 87 | /* $$.ix [err_doit]~function,~source~code$$ */ 88 | static void 89 | err_doit(int errnoflag, int level, const char *fmt, va_list ap) 90 | { 91 | int errno_save, n; 92 | char buf[YH_ERROR_MAXLINE]; 93 | 94 | errno_save = errno; /* value caller might want printed */ 95 | //#ifdef HAVE_VSNPRINTF 96 | vsnprintf(buf, sizeof(buf), fmt, ap); /* this is safe */ 97 | //#else 98 | //vsprintf(buf, fmt, ap); /* this is not safe */ 99 | //#endif 100 | n = strlen(buf); 101 | if (errnoflag) 102 | snprintf(buf+n, sizeof(buf)-n, ": %s", strerror(errno_save)); 103 | strcat(buf, "\n"); 104 | 105 | if (daemon_proc) { 106 | syslog(level, buf, ""); 107 | } else { 108 | fflush(stdout); /* in case stdout and stderr are the same */ 109 | fputs(buf, stderr); 110 | fflush(stderr); 111 | } 112 | return; 113 | } 114 | -------------------------------------------------------------------------------- /yherror.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_ERROR_H__ 2 | #define __YH_ERROR_H__ 3 | 4 | #include /* ANSI C header file */ 5 | #include /* for syslog() */ 6 | 7 | #include /* ANSI C header file */ 8 | #include /* for syslog() */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #define YH_ERROR_MAXLINE 1024 15 | extern int daemon_proc; /* set nonzero by daemon_init() */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" 19 | { 20 | #endif 21 | 22 | #pragma pack(push) 23 | #pragma pack(1) 24 | #pragma pack(pop) 25 | 26 | 27 | /* Nonfatal error related to a system call. 28 | * Print a message and return. */ 29 | 30 | /* $$.ix [err_ret]~function,~source~code$$ */ 31 | void 32 | err_ret(const char *fmt, ...); 33 | 34 | /* Fatal error related to a system call. 35 | * Print a message and terminate. */ 36 | 37 | /* $$.ix [err_sys]~function,~source~code$$ */ 38 | void 39 | err_sys(const char *fmt, ...); 40 | 41 | 42 | /* Fatal error related to a system call. 43 | * Print a message, dump core, and terminate. */ 44 | 45 | /* $$.ix [err_dump]~function,~source~code$$ */ 46 | void 47 | err_dump(const char *fmt, ...); 48 | 49 | 50 | /* Nonfatal error unrelated to a system call. 51 | * Print a message and return. */ 52 | 53 | /* $$.ix [err_msg]~function,~source~code$$ */ 54 | void 55 | err_msg(const char *fmt, ...); 56 | #define log_msg(fmt, ...) err_msg(fmt, ##__VA_ARGS__) 57 | 58 | 59 | /* Fatal error unrelated to a system call. 60 | * Print a message and terminate. */ 61 | 62 | /* $$.ix [err_quit]~function,~source~code$$ */ 63 | void 64 | err_quit(const char *fmt, ...); 65 | 66 | #define ERR_LOG(errfunc, format, ...) \ 67 | do { \ 68 | errfunc("\e[7m%s:%d `%s'\e[m "format,__FILE__,__LINE__,__func__,##__VA_ARGS__);\ 69 | } while (0) 70 | 71 | #define ERR_MSG(s,...) ERR_LOG(err_msg,s,##__VA_ARGS__) 72 | #define ERR_RET(s,...) ERR_LOG(err_ret,s,##__VA_ARGS__) 73 | #define ERR_SYS(s,...) ERR_LOG(err_sys,s,##__VA_ARGS__) 74 | #define ERR_DUMP(s,...) ERR_LOG(err_dump,s,##__VA_ARGS__) 75 | #define ERR_QUIT(s,...) ERR_LOG(err_quit,s,##__VA_ARGS__) 76 | #define LOG_MSG(s,...) ERR_LOG(log_msg,s,##__VA_ARGS__) 77 | #define LOG_MARK() ERR_LOG(log_msg,"") 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | #endif /* __YH_ERROR_H__ */ 83 | -------------------------------------------------------------------------------- /yhevent.c: -------------------------------------------------------------------------------- 1 | #include "yhevent.h" 2 | 3 | static void fe_bind(fe_t *fe, em_t *em, int fd, int type) 4 | { 5 | fe->event.data.ptr = fe; 6 | fe->fd = fd; 7 | fe->em = em; 8 | fe->heap = type; 9 | } 10 | 11 | // 栈上的自动变量 fe_t 初始化时候 12 | // 绑定 em 和 fd, 设置堆标志 heap 为0 13 | // 这样防止 fe_del 时错误的调用 free 14 | void fe_init(fe_t *fe, em_t *em, int fd) 15 | { 16 | fe_bind(fe, em, fd, 0); 17 | } 18 | 19 | // 从堆上获取一个 fe_t, 在初始化的时候 20 | // 绑定 em 和 fd, 设置堆标志 heap 为1 21 | // 这样保证 fe_del 的时候 free 22 | fe_t * fe_new(em_t *em, int fd) 23 | { 24 | fe_t * fe = (fe_t*)calloc(1, sizeof(fe_t)); 25 | if (fe == 0) { 26 | err_ret("fe_new() calloc error[%d]", errno); 27 | return 0; 28 | } 29 | fe_bind(fe, em, fd, 1); 30 | return fe; 31 | } 32 | fe_t * Fe_new(em_t *em, int fd) 33 | { 34 | fe_t *fe = fe_new(em, fd); 35 | if (fe == 0) exit(1); 36 | return fe; 37 | } 38 | 39 | 40 | void fe_del(fe_t *fe) 41 | { 42 | if (fe == 0) return; 43 | fe_em_del(fe); 44 | if (fe->heap) free(fe); 45 | } 46 | void fe_set(fe_t *fe, int event, fe_cb_t cb) 47 | { 48 | switch (event) { 49 | case EPOLLIN : fe->in = cb; break; 50 | case EPOLLOUT : fe->out = cb; break; 51 | case EPOLLPRI : fe->pri = cb; break; 52 | case EPOLLRDHUP : fe->rdhup = cb; break; 53 | case EPOLLONESHOT : 54 | case EPOLLET : break; 55 | default: 56 | return; 57 | }; 58 | fe->event.events |= event; 59 | } 60 | void fe_unset(fe_t *fe, int event) 61 | { 62 | fe->event.events &= ~event; 63 | } 64 | int fe_em_add(fe_t* fe) 65 | { 66 | int ret = epoll_ctl(fe->em->epfd, EPOLL_CTL_ADD, fe->fd, &fe->event); 67 | if (ret < 0) 68 | err_ret("fe_em_add() epoll_ctl %d fd %d error[%d]" 69 | , fe->em->epfd, fe->fd, errno); 70 | return ret; 71 | } 72 | int fe_em_mod(fe_t* fe) 73 | { 74 | int ret = epoll_ctl(fe->em->epfd, EPOLL_CTL_MOD, fe->fd, &fe->event); 75 | if (ret < 0) 76 | err_ret("fe_em_mod() epoll_ctl %d fd %d error[%d]" 77 | , fe->em->epfd, fe->fd, errno); 78 | return ret; 79 | } 80 | int fe_em_del(fe_t* fe) 81 | { 82 | int ret = epoll_ctl(fe->em->epfd, EPOLL_CTL_DEL, fe->fd, &fe->event); 83 | if (ret < 0) 84 | err_ret("fe_em_del() epoll_ctl %d fd %d error[%d]" 85 | , fe->em->epfd, fe->fd, errno); 86 | return ret; 87 | } 88 | void Fe_em_add(fe_t* fe) 89 | { 90 | if (fe_em_add(fe) < 0) exit(1); 91 | } 92 | void Fe_em_mod(fe_t* fe) 93 | { 94 | if (fe_em_mod(fe) < 0) exit(1); 95 | } 96 | void Fe_em_del(fe_t* fe) 97 | { 98 | if (fe_em_del(fe) < 0) exit(1); 99 | } 100 | int setfd_nonblock(int fd) 101 | { 102 | int status; 103 | if ((status = fcntl(fd, F_GETFL)) < 0) { 104 | err_ret("setfd_nonblock() fcntl F_GETFL error[%d]", errno); 105 | return -1; 106 | } 107 | status |= O_NONBLOCK; 108 | if (fcntl(fd, F_SETFL, status) < 0) { 109 | err_ret("setfd_nonblock() fcntl F_SETFL error[%d]", errno); 110 | return -1; 111 | } 112 | return 0; 113 | } 114 | int setsock_rcvtimeo(int fd, int second, int microsecond) 115 | { 116 | struct timeval rcv_timeo = {second, microsecond}; 117 | if (setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,&rcv_timeo,sizeof(rcv_timeo))< 0) { 118 | err_ret("setsock_rcvtimeo() setsockopt SO_RCVTIMEO error[%d]", errno); 119 | return -1; 120 | } 121 | return 0; 122 | } 123 | void Setfd_nonblock(int fd) 124 | { 125 | if ( setfd_nonblock(fd) < 0 ) exit(1); 126 | } 127 | void Setsock_rcvtimeo(int fd, int second, int microsecond) 128 | { 129 | if ( setsock_rcvtimeo(fd, second, microsecond) < 0 ) exit(1); 130 | } 131 | /* create epoll manager */ 132 | em_t* em_open(int maxfds, int timeout, 133 | em_cb_t before, em_cbn_t events, em_cb_t after) 134 | { 135 | em_t *em = 0; 136 | if (maxfds <= 0) { errno = EINVAL; return 0; } 137 | em = (em_t*)calloc(1, sizeof(em_t) + 138 | (maxfds+1) * sizeof(struct epoll_event)); 139 | if (em == 0) { /*errno = ENOMEM;*/ return 0; } 140 | em->timeout = timeout; 141 | em->maxfds = maxfds; 142 | em->before = before; 143 | em->event = events; 144 | em->after = after; 145 | em->run = 0; 146 | if ( (em->epfd = epoll_create(maxfds) ) < 0 ) goto err_out; 147 | if ( (errno = pthread_mutex_init(&em->lock, 0)) != 0 ) goto err_out; 148 | return em; 149 | err_out: 150 | if (em->epfd >= 0) { close(em->epfd); } 151 | if (em != 0) { free(em); } 152 | return 0; 153 | } 154 | em_t* Em_open(int maxfds, int timeout, em_cb_t before, 155 | em_cbn_t events, em_cb_t after) 156 | { 157 | em_t *em; 158 | if ((em = em_open(maxfds, timeout, before, events, after)) == 0) 159 | { err_ret("Em_open() em_open error[%d]", errno); exit(1); } 160 | return em; 161 | } 162 | static void * em_thread(void *p) 163 | { 164 | em_t *em = (em_t*)p; 165 | int n, nfds; 166 | void *ptr; 167 | fe_t *fe = 0; 168 | 169 | while (em->run) { 170 | if (em->before) em->before(em); 171 | 172 | nfds = epoll_wait(em->epfd, em->evlist, em->maxfds, em->timeout); 173 | if (em->event) em->event(em, nfds); 174 | 175 | for (n = 0; n < nfds; ++n) { 176 | ptr = em->evlist[n].data.ptr; 177 | if (ptr == 0) continue; 178 | fe = (fe_t*)ptr; 179 | if ( em->evlist[n].events & EPOLLIN && fe->in) 180 | fe->in (fe); 181 | else if (em->evlist[n].events & EPOLLOUT && fe->out) 182 | fe->out(fe); 183 | else if (em->evlist[n].events & EPOLLPRI && fe->pri) 184 | fe->pri(fe); 185 | else if (em->evlist[n].events & EPOLLRDHUP && fe->rdhup) 186 | fe->rdhup(fe); 187 | else { 188 | if(em->evlist[n].events & EPOLLIN ) 189 | log_msg("Unhandled EPOLLIN %x fd %d", fe, fe->fd); 190 | else if(em->evlist[n].events & EPOLLOUT) 191 | log_msg("Unhandled EPOLLOUT %x fd %d", fe, fe->fd); 192 | else if(em->evlist[n].events & EPOLLPRI) 193 | log_msg("Unhandled EPOLLPRI %x fd %d", fe, fe->fd); 194 | else if(em->evlist[n].events & EPOLLRDHUP) 195 | log_msg("Unhandled EPOLLRDHUP %x fd %d", fe, fe->fd); 196 | else 197 | log_msg("Unhandled events[0x%x] %x fd %d", 198 | em->evlist[n].events, fe, fe->fd); 199 | } 200 | } 201 | 202 | if (em->after) em->after(em); 203 | } 204 | return (void*)0; 205 | } 206 | int em_run(em_t *em, int n) 207 | { 208 | pthread_t tid; 209 | pthread_attr_t attr; 210 | 211 | pthread_attr_init(&attr); 212 | pthread_attr_setstacksize(&attr, 1024*1024); //set stack size 1M 213 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 214 | 215 | pthread_mutex_lock(&em->lock); 216 | if (em->run) { 217 | pthread_mutex_unlock(&em->lock); 218 | return 0; 219 | } 220 | em->run = 1; 221 | pthread_mutex_unlock(&em->lock); 222 | 223 | int i; 224 | for (i = 0; i < n; i++) { 225 | if ((errno = pthread_create(&tid, &attr, em_thread, em)) != 0) { 226 | err_ret("em_run() pthread_create error[%d]", errno); 227 | return -1; 228 | } 229 | } 230 | pthread_attr_destroy(&attr); 231 | return 0; 232 | } 233 | void Em_run(em_t *em, int n) 234 | { 235 | if (em_run(em, n) < 0) exit(1); 236 | } 237 | int em_set_timeout(em_t *em, int timeout) 238 | { 239 | int old = em->timeout; 240 | em->timeout = timeout; 241 | return old; 242 | } 243 | 244 | int close_all_fd(void) 245 | { 246 | DIR *dir; 247 | struct dirent *entry, _entry; 248 | int retval, rewind, fd; 249 | dir = opendir("/dev/fd"); 250 | if (dir == NULL) 251 | return -1; 252 | rewind = 0; 253 | while (1) { 254 | retval = readdir_r(dir, &_entry, &entry); 255 | if (retval != 0) { 256 | errno = -retval; 257 | retval = -1; 258 | break; 259 | } 260 | if (entry == NULL) { 261 | if (!rewind) 262 | break; 263 | rewinddir(dir); 264 | rewind = 0; 265 | continue; 266 | } 267 | if (entry->d_name[0] == '.') 268 | continue; 269 | fd = atoi(entry->d_name); 270 | if (dirfd(dir) == fd) 271 | continue; 272 | #ifdef MYPERF 273 | if (fd == 1) 274 | continue; 275 | #endif 276 | retval = close(fd); 277 | if (retval != 0) 278 | break; 279 | rewind = 1; 280 | } 281 | closedir(dir); 282 | return retval; 283 | } 284 | -------------------------------------------------------------------------------- /yhevent.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_YHEPOLL_H__ 2 | #define __YH_YHEPOLL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "yherror.h" 16 | 17 | typedef struct fd_event fd_event_t, fe_t; 18 | typedef struct epoll_manager epoll_manager_t, em_t; 19 | 20 | typedef void fe_cb_t(fe_t * fe); 21 | typedef void em_cb_t(const em_t * const em); 22 | typedef void em_cbn_t(const em_t * const em, int n); 23 | 24 | /////////////////////////////////////////////////////////////////////////////// 25 | #ifndef offsetof 26 | #define offsetof(type, member) \ 27 | (size_t)&(((type *)0)->member) 28 | #endif 29 | 30 | #ifndef container_of 31 | #define container_of(ptr, type, member) \ 32 | ({\ 33 | const typeof(((type *)0)->member) * __mptr = (ptr);\ 34 | (type *)((char *)__mptr - offsetof(type, member)); \ 35 | }) 36 | #endif 37 | 38 | #ifndef struct_entry 39 | #define struct_entry(ptr, type, member) container_of(ptr, type, member) 40 | #endif 41 | 42 | #ifndef _REENTRANT 43 | #define _REENTRANT 44 | #endif 45 | /////////////////////////////////////////////////////////////////////////////// 46 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * 47 | * 关于fd 在epoll_wait 中返回后的状态 48 | * EPOLLIN :文件描述符可以读(包括对端SOCKET正常关闭); 49 | * EPOLLOUT:文件描述符可以写; 50 | * EPOLLPRI:文件描述符有紧急的数据可读(有带外数据); 51 | * EPOLLERR:文件描述符发生错误; 52 | * EPOLLHUP:文件描述符被挂断; 53 | * EPOLLRDHUP:对端关闭; 54 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * 55 | * * fd event object * * * * * * * * * * * * * * * * * */ 56 | // event.events = EPOLLxxx | ...; event.data.ptr = fd_event address; 57 | struct fd_event { 58 | int fd; // file descriptor 59 | struct epoll_event event; 60 | em_t *em; // epoll manager 61 | void *ptr; // user data ptr, user alloc/free 62 | 63 | unsigned int heap; // heap flag is !0 alloc, stack flag is 0 64 | 65 | // event callback: 66 | fe_cb_t * in; 67 | fe_cb_t * out; 68 | fe_cb_t * pri; 69 | fe_cb_t * rdhup; 70 | }; 71 | 72 | /* * epoll manager object */ 73 | struct epoll_manager 74 | { 75 | pthread_mutex_t lock; // safe lock 76 | em_cb_t * before; // epoll_wait before 77 | em_cbn_t * event; // epoll_wait after,Before the event processing 78 | em_cb_t * after; // After the completion of the event processing 79 | int run; // epoll manager thread control 80 | int epfd; // epoll_wait par1 epfd 81 | int timeout; // epoll_wait par4 timeout 82 | int maxfds; // epoll_wait par3 maxevents 83 | struct epoll_event evlist[]; // epoll_wait par2 events 84 | }; 85 | 86 | 87 | #ifdef __cplusplus 88 | extern "C" 89 | { 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | em_t* em_open(int maxfds, int timeout, 94 | em_cb_t before=0, em_cbn_t events=0, em_cb_t after=0); 95 | em_t* Em_open(int maxfds, int timeout, 96 | em_cb_t before=0, em_cbn_t events=0, em_cb_t after=0); 97 | #else 98 | em_t* em_open(int maxfds, int timeout, em_cb_t before, 99 | em_cbn_t events, em_cb_t after); 100 | em_t* Em_open(int maxfds, int timeout, em_cb_t before, 101 | em_cbn_t events, em_cb_t after); 102 | #endif 103 | void Em_run(em_t *em, int n); 104 | int em_run(em_t *em, int n); 105 | int em_set_timeout(em_t *em, int timeout); 106 | 107 | // 调用 epoll_ctl 执行 ADD MOD DEL 108 | // 返回 epoll_ctl的返回值 109 | // 出错时打印出错消息, 返回epoll_ctl的返回码 110 | int fe_em_add(fe_t* fe); 111 | int fe_em_mod(fe_t* fe); 112 | int fe_em_del(fe_t* fe); 113 | 114 | // 调用 epoll_ctl 执行 ADD MOD DEL 115 | // 出错时打印出错消息并且退出程序 116 | void Fe_em_add(fe_t* fe); 117 | void Fe_em_mod(fe_t* fe); 118 | void Fe_em_del(fe_t* fe); 119 | 120 | int setfd_nonblock(int fd); 121 | void Setfd_nonblock(int fd); 122 | int setsock_rcvtimeo(int fd, int second, int microsecond); 123 | void Setsock_rcvtimeo(int fd, int second, int microsecond); 124 | int close_all_fd(void); 125 | 126 | fe_t * fe_new(em_t *em, int fd); 127 | fe_t * Fe_new(em_t *em, int fd); 128 | void fe_init(fe_t *fe, em_t *em, int fd); 129 | void fe_del (fe_t *p); 130 | 131 | #ifdef __cplusplus 132 | void fe_set(fe_t *fh, int event, fe_cb_t cb = 0); 133 | #else 134 | void fe_set(fe_t *fh, int event, fe_cb_t cb); 135 | #endif 136 | 137 | void fe_unset(fe_t *fe, int event); 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* __YH_YHEPOLL_H__ */ 144 | -------------------------------------------------------------------------------- /yhrbtree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "yhrbtree.h" 7 | 8 | #include 9 | 10 | #define AUTHOR "Yuan Hong" 11 | #define VERSION "RBTree shared library version 3.1" 12 | 13 | const char * rbtree_author = AUTHOR; 14 | const char * rbtree_version = VERSION; 15 | 16 | /* 17 | Container Of Red Black Trees 18 | (C) 2011 Hong Yuan 19 | */ 20 | 21 | inline 22 | static const void * default_getkey (const void * pdata ) 23 | { 24 | return pdata; 25 | } 26 | 27 | inline 28 | struct rb_node_data* get_node_entry(void *data_field) 29 | { 30 | return rb_entry(data_field, struct rb_node_data, data); 31 | } 32 | 33 | inline 34 | int get_node_data_size(void *data_field) 35 | { 36 | return get_node_entry(data_field)->size; 37 | } 38 | 39 | inline 40 | void * get_data_pointer(struct rb_node_data *rnd) 41 | { 42 | return rnd->data; 43 | } 44 | 45 | inline 46 | int get_data_size(struct rb_node_data *rnd) 47 | { 48 | return rnd->size; 49 | } 50 | 51 | inline 52 | static void * cmp_init_error() 53 | { 54 | printf("Error: No define callback function no defined of comparison.\n"); 55 | printf(" Must define and write it\n"); 56 | printf(" Generic container version 3.0\n"); 57 | abort(); 58 | return (void*)0; 59 | } 60 | 61 | /* 62 | * Initializing rbtree root 63 | */ 64 | inline 65 | void rbt_init(struct rb_root *root, getkey_func_t * getkey, cmp_func_t *cmp) 66 | { 67 | *root = RB_ROOT; 68 | //assert(cmp != 0); // cmp not is null to pass 69 | //root->cmp = cmp; 70 | root->cmp = ( 0 == cmp ? cmp_init_error() : cmp ); 71 | root->getkey = ( 0 == getkey ? default_getkey : getkey ); 72 | } 73 | 74 | /* 75 | * stack alloc rbtree node-data 76 | */ 77 | struct rb_node_data *rbt_node_new(size_t size) 78 | { 79 | struct rb_node_data *node = 80 | calloc(1, sizeof(struct rb_node_data) + size); 81 | if (node) 82 | node->size = size; 83 | return node; 84 | } 85 | 86 | /* 87 | * free rbtree node-data 88 | */ 89 | void rbt_node_free(struct rb_node_data *node) 90 | { 91 | if (node) 92 | free(node); 93 | } 94 | 95 | /* 96 | * Search key node from rbtree 97 | * Never attempt to modify the key value content 98 | * This will destroy the structure of the Red-Black tree 99 | * You must copy a object processing 100 | */ 101 | inline 102 | struct rb_node_data *rbt_search(struct rb_root *root, const void* key) 103 | { 104 | struct rb_node *node = root->rb_node; 105 | 106 | while (node) 107 | { 108 | struct rb_node_data *this = 109 | rb_entry(node, struct rb_node_data, rb_node); 110 | 111 | int result = root->cmp(key, root->getkey(this->data)); 112 | 113 | if (result < 0) 114 | node = node->rb_left; 115 | else if (result > 0) 116 | node = node->rb_right; 117 | else 118 | return this; 119 | } 120 | return 0; 121 | } 122 | 123 | /* 124 | * Insert node into rbtree 125 | */ 126 | inline 127 | int rbt_insert(struct rb_root *root, struct rb_node_data *new_node) 128 | { 129 | struct rb_node **now = &(root->rb_node); 130 | struct rb_node *parent = 0; 131 | 132 | /* Figure out where to put now node */ 133 | while (*now) 134 | { 135 | struct rb_node_data *this = 136 | rb_entry(*now, struct rb_node_data, rb_node); 137 | 138 | int result = 139 | root->cmp(root->getkey(new_node->data) 140 | , root->getkey(this->data)); 141 | 142 | parent = *now; 143 | 144 | if (result < 0) 145 | now = &((*now)->rb_left); 146 | else if (result > 0) 147 | now = &((*now)->rb_right); 148 | else 149 | return -1; // the key is already exists 150 | } 151 | 152 | /* Add new node and rebalance tree. */ 153 | rb_link_node(&(new_node->rb_node), parent, now); 154 | rb_insert_color(&(new_node->rb_node), root); 155 | 156 | return 0; 157 | } 158 | 159 | 160 | /* 161 | * Delete the key node from rbtree 162 | * delete node from rbtree, return deleted node pointer 163 | */ 164 | inline 165 | struct rb_node_data *rbt_delete(struct rb_root *root, const void *key) 166 | { 167 | struct rb_node_data *find = rbt_search(root, key); 168 | if (!find) 169 | return 0; 170 | rb_erase(&find->rb_node, root); 171 | return find; 172 | } 173 | 174 | /* 175 | * Erase the node from rbtree, return deleted node pointer 176 | * *** use with caution, node must exist in rbtree *** 177 | * *** example: *** 178 | struct rb_node_data *node; 179 | node = rbt_search(&root, key); 180 | if (node) 181 | { 182 | // use node 183 | // action code 184 | rbt_erase(&root, node); 185 | rbt_node_free(node); 186 | node = NULL; 187 | } 188 | */ 189 | inline 190 | void rbt_erase(struct rb_root *root, struct rb_node_data *node) 191 | { 192 | rb_erase(&node->rb_node, root); 193 | } 194 | 195 | /* 196 | * Replace the key node from rbtree for new rb_node_data 197 | * replace node from rbtree, return old node pointer 198 | */ 199 | inline 200 | struct rb_node_data * rbt_replace(struct rb_root *root, 201 | struct rb_node_data *current_node) 202 | { 203 | struct rb_node_data *old_node = 204 | rbt_search(root, root->getkey(current_node->data)); 205 | if (!old_node) 206 | return 0; 207 | rb_replace_node(&(old_node->rb_node), 208 | ¤t_node->rb_node, root); 209 | return old_node; 210 | } 211 | 212 | /* 213 | * Traversal of the node processing 214 | */ 215 | inline 216 | static int default_action(void *pn, void *pe) 217 | { 218 | return 1; 219 | } 220 | 221 | /* 222 | * node : leaf node 223 | * pndata : node data 224 | * pedata : external data 225 | * action : callback function pointer 226 | * succ_ret : action successful count 227 | */ 228 | inline static 229 | int rbt_inorder_aider(struct rb_node *node, void* pndata, void *pedata, 230 | int (*action) (void *pndata, void *pedata), int *succ_ret) 231 | { 232 | if (node == NULL) 233 | return 0; 234 | int count = rbt_inorder_aider(node->rb_left , 235 | /* external data for callback */ 236 | rb_entry(node->rb_left, 237 | struct rb_node_data, rb_node)->data 238 | /* external data for callback */ 239 | , pedata 240 | , action, succ_ret); 241 | if (action(pndata, pedata) && succ_ret) 242 | ++*succ_ret; 243 | ++count; 244 | count += rbt_inorder_aider(node->rb_right , 245 | /* only node data for callback */ 246 | rb_entry(node->rb_right, 247 | struct rb_node_data, rb_node)->data 248 | /* external data for callback */ 249 | , pedata 250 | , action, succ_ret); 251 | return count; 252 | } 253 | 254 | /* 255 | * Inorder Traversing the Red-Black tree 256 | * root : rbtree root 257 | * pedata : external data 258 | * action : callback function pointer 259 | * action_succ_ret : action successful count 260 | * 261 | * return-int : node count 262 | */ 263 | inline 264 | int rbt_inorder(struct rb_root *root, void *pedata, 265 | int (*action) (void *pndata, void *pedata), int *action_succ_ret) 266 | { 267 | if (action == NULL) 268 | action = default_action; // true 269 | if (root == NULL) 270 | return 0; 271 | if (action_succ_ret) 272 | *action_succ_ret = 0; 273 | return rbt_inorder_aider(root->rb_node 274 | /* only node data for callback */ 275 | , rb_entry(root->rb_node, 276 | struct rb_node_data, rb_node)->data 277 | // external data for callback 278 | , pedata 279 | , action, action_succ_ret); 280 | } 281 | 282 | static inline 283 | int rbt_clear_aider(struct rb_node *node, void* pndata, void *pedata, 284 | int (*action) (void *pndata, void *pedata), int *succ_ret) 285 | { 286 | if (node == NULL) 287 | return 0; 288 | int count = rbt_clear_aider(node->rb_left 289 | , rb_entry(node->rb_left, 290 | struct rb_node_data, rb_node)->data 291 | , pedata 292 | , action, succ_ret); 293 | count += rbt_clear_aider(node->rb_right 294 | , rb_entry(node->rb_right, 295 | struct rb_node_data, rb_node)->data 296 | , pedata 297 | , action, succ_ret); 298 | if (action(pndata, pedata) && succ_ret) 299 | (*succ_ret) ++; 300 | ++count; 301 | //void *p = rb_entry(node, struct rb_node_data, rb_node); 302 | free(rb_entry(node, struct rb_node_data, rb_node)); 303 | //printf("free %p\n", p); 304 | return count; 305 | } 306 | 307 | /* 308 | * clear the rbtree 309 | */ 310 | inline 311 | int rbt_clear(struct rb_root *root, void *pedata, 312 | int (*action)(void *pndata, void *pedata), int *action_succ_ret) 313 | { 314 | 315 | if (action == NULL) 316 | action = default_action; // return true 317 | if (root == NULL) 318 | return 0; 319 | int count; 320 | if (action_succ_ret != 0) 321 | *action_succ_ret = 0; 322 | count = rbt_clear_aider(root->rb_node 323 | , rb_entry(root->rb_node, 324 | struct rb_node_data, rb_node)->data 325 | , pedata 326 | , action, action_succ_ret); 327 | root->rb_node = NULL; 328 | return count; /* the clear node count */ 329 | } 330 | 331 | /* 332 | * first node [Leftmost node] 333 | */ 334 | inline 335 | struct rb_node_data * rbt_node_first(struct rb_root *root) 336 | { 337 | struct rb_node * node = rb_first(root); 338 | if (node == NULL) 339 | return NULL; 340 | return rb_entry(node, struct rb_node_data, rb_node); 341 | } 342 | 343 | /* 344 | * first data of node 345 | */ 346 | inline 347 | void * rbt_data_first(struct rb_root *root) 348 | { 349 | struct rb_node_data *node_data; 350 | node_data = rbt_node_first(root); 351 | if (node_data == NULL) 352 | return NULL; 353 | return node_data->data; 354 | } 355 | 356 | /* 357 | * last node [Rightmost node] 358 | */ 359 | inline 360 | struct rb_node_data * rbt_node_last(struct rb_root *root) 361 | { 362 | struct rb_node * node = rb_last(root); 363 | if (node == NULL) 364 | return NULL; 365 | return rb_entry(node, struct rb_node_data, rb_node); 366 | } 367 | 368 | /* 369 | * last data of node 370 | */ 371 | inline 372 | void * rbt_data_last(struct rb_root *root) 373 | { 374 | struct rb_node_data *node_data; 375 | node_data = rbt_node_last(root); 376 | if (node_data == NULL) 377 | return NULL; 378 | return node_data->data; 379 | } 380 | 381 | /* 382 | * next node 383 | */ 384 | inline 385 | struct rb_node_data *rbt_node_next(struct rb_node_data *data_node) 386 | { 387 | struct rb_node* node; 388 | node = rb_next(&data_node->rb_node); 389 | if (node == NULL) 390 | return NULL; 391 | return rb_entry(node, struct rb_node_data, rb_node); 392 | 393 | } 394 | 395 | /* 396 | * next data of node 397 | */ 398 | inline 399 | void *rbt_data_next(struct rb_node_data *data_node) 400 | { 401 | struct rb_node_data* rnd; 402 | rnd = rbt_node_next(data_node); 403 | if (rnd == NULL) 404 | return NULL; 405 | return rnd->data; 406 | } 407 | 408 | /* 409 | * prev data of node 410 | */ 411 | inline 412 | struct rb_node_data *rbt_node_prev(struct rb_node_data *data_node) 413 | { 414 | struct rb_node* node; 415 | node = rb_prev(&data_node->rb_node); 416 | if (node == NULL) 417 | return NULL; 418 | return rb_entry(node, struct rb_node_data, rb_node); 419 | } 420 | 421 | /* 422 | * prev data of node 423 | */ 424 | inline 425 | void *rbt_data_prev(struct rb_node_data *data_node) 426 | { 427 | struct rb_node_data* rnd; 428 | rnd = rbt_node_prev(data_node); 429 | if (rnd == NULL) 430 | return NULL; 431 | return rnd->data; 432 | } 433 | 434 | // rbtree.c source codes 435 | // rbtree.c 436 | // {{{ 437 | // rbtree.c 438 | 439 | /* 440 | Red Black Trees 441 | (C) 1999 Andrea Arcangeli 442 | (C) 2002 David Woodhouse 443 | 444 | This program is free software; you can redistribute it and/or modify 445 | it under the terms of the GNU General Public License as published by 446 | the Free Software Foundation; either version 2 of the License, or 447 | (at your option) any later version. 448 | 449 | This program is distributed in the hope that it will be useful, 450 | but WITHOUT ANY WARRANTY; without even the implied warranty of 451 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 452 | GNU General Public License for more details. 453 | 454 | You should have received a copy of the GNU General Public License 455 | along with this program; if not, write to the Free Software 456 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 457 | 458 | linux/lib/rbtree.c 459 | */ 460 | 461 | //#include "rbtree.h" 462 | 463 | static void __rb_rotate_left(struct rb_node *node, struct rb_root *root) 464 | { 465 | struct rb_node *right = node->rb_right; 466 | struct rb_node *parent = rb_parent(node); 467 | 468 | if ((node->rb_right = right->rb_left)) 469 | rb_set_parent(right->rb_left, node); 470 | right->rb_left = node; 471 | 472 | rb_set_parent(right, parent); 473 | 474 | if (parent) 475 | { 476 | if (node == parent->rb_left) 477 | parent->rb_left = right; 478 | else 479 | parent->rb_right = right; 480 | } 481 | else 482 | root->rb_node = right; 483 | rb_set_parent(node, right); 484 | } 485 | 486 | static void __rb_rotate_right(struct rb_node *node, struct rb_root *root) 487 | { 488 | struct rb_node *left = node->rb_left; 489 | struct rb_node *parent = rb_parent(node); 490 | 491 | if ((node->rb_left = left->rb_right)) 492 | rb_set_parent(left->rb_right, node); 493 | left->rb_right = node; 494 | 495 | rb_set_parent(left, parent); 496 | 497 | if (parent) 498 | { 499 | if (node == parent->rb_right) 500 | parent->rb_right = left; 501 | else 502 | parent->rb_left = left; 503 | } 504 | else 505 | root->rb_node = left; 506 | rb_set_parent(node, left); 507 | } 508 | 509 | void rb_insert_color(struct rb_node *node, struct rb_root *root) 510 | { 511 | struct rb_node *parent, *gparent; 512 | 513 | while ((parent = rb_parent(node)) && rb_is_red(parent)) 514 | { 515 | gparent = rb_parent(parent); 516 | 517 | if (parent == gparent->rb_left) 518 | { 519 | { 520 | register struct rb_node *uncle = gparent->rb_right; 521 | if (uncle && rb_is_red(uncle)) 522 | { 523 | rb_set_black(uncle); 524 | rb_set_black(parent); 525 | rb_set_red(gparent); 526 | node = gparent; 527 | continue; 528 | } 529 | } 530 | 531 | if (parent->rb_right == node) 532 | { 533 | register struct rb_node *tmp; 534 | __rb_rotate_left(parent, root); 535 | tmp = parent; 536 | parent = node; 537 | node = tmp; 538 | } 539 | 540 | rb_set_black(parent); 541 | rb_set_red(gparent); 542 | __rb_rotate_right(gparent, root); 543 | } else { 544 | { 545 | register struct rb_node *uncle = gparent->rb_left; 546 | if (uncle && rb_is_red(uncle)) 547 | { 548 | rb_set_black(uncle); 549 | rb_set_black(parent); 550 | rb_set_red(gparent); 551 | node = gparent; 552 | continue; 553 | } 554 | } 555 | 556 | if (parent->rb_left == node) 557 | { 558 | register struct rb_node *tmp; 559 | __rb_rotate_right(parent, root); 560 | tmp = parent; 561 | parent = node; 562 | node = tmp; 563 | } 564 | 565 | rb_set_black(parent); 566 | rb_set_red(gparent); 567 | __rb_rotate_left(gparent, root); 568 | } 569 | } 570 | 571 | rb_set_black(root->rb_node); 572 | } 573 | //EXPORT_SYMBOL(rb_insert_color); 574 | 575 | static void __rb_erase_color(struct rb_node *node, struct rb_node *parent, 576 | struct rb_root *root) 577 | { 578 | struct rb_node *other; 579 | 580 | while ((!node || rb_is_black(node)) && node != root->rb_node) 581 | { 582 | if (parent->rb_left == node) 583 | { 584 | other = parent->rb_right; 585 | if (rb_is_red(other)) 586 | { 587 | rb_set_black(other); 588 | rb_set_red(parent); 589 | __rb_rotate_left(parent, root); 590 | other = parent->rb_right; 591 | } 592 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 593 | (!other->rb_right || rb_is_black(other->rb_right))) 594 | { 595 | rb_set_red(other); 596 | node = parent; 597 | parent = rb_parent(node); 598 | } 599 | else 600 | { 601 | if (!other->rb_right || rb_is_black(other->rb_right)) 602 | { 603 | rb_set_black(other->rb_left); 604 | rb_set_red(other); 605 | __rb_rotate_right(other, root); 606 | other = parent->rb_right; 607 | } 608 | rb_set_color(other, rb_color(parent)); 609 | rb_set_black(parent); 610 | rb_set_black(other->rb_right); 611 | __rb_rotate_left(parent, root); 612 | node = root->rb_node; 613 | break; 614 | } 615 | } 616 | else 617 | { 618 | other = parent->rb_left; 619 | if (rb_is_red(other)) 620 | { 621 | rb_set_black(other); 622 | rb_set_red(parent); 623 | __rb_rotate_right(parent, root); 624 | other = parent->rb_left; 625 | } 626 | if ((!other->rb_left || rb_is_black(other->rb_left)) && 627 | (!other->rb_right || rb_is_black(other->rb_right))) 628 | { 629 | rb_set_red(other); 630 | node = parent; 631 | parent = rb_parent(node); 632 | } 633 | else 634 | { 635 | if (!other->rb_left || rb_is_black(other->rb_left)) 636 | { 637 | rb_set_black(other->rb_right); 638 | rb_set_red(other); 639 | __rb_rotate_left(other, root); 640 | other = parent->rb_left; 641 | } 642 | rb_set_color(other, rb_color(parent)); 643 | rb_set_black(parent); 644 | rb_set_black(other->rb_left); 645 | __rb_rotate_right(parent, root); 646 | node = root->rb_node; 647 | break; 648 | } 649 | } 650 | } 651 | if (node) 652 | rb_set_black(node); 653 | } 654 | 655 | void rb_erase(struct rb_node *node, struct rb_root *root) 656 | { 657 | struct rb_node *child, *parent; 658 | int color; 659 | 660 | if (!node->rb_left) 661 | child = node->rb_right; 662 | else if (!node->rb_right) 663 | child = node->rb_left; 664 | else 665 | { 666 | struct rb_node *old = node, *left; 667 | 668 | node = node->rb_right; 669 | while ((left = node->rb_left) != NULL) 670 | node = left; 671 | 672 | if (rb_parent(old)) { 673 | if (rb_parent(old)->rb_left == old) 674 | rb_parent(old)->rb_left = node; 675 | else 676 | rb_parent(old)->rb_right = node; 677 | } else 678 | root->rb_node = node; 679 | 680 | child = node->rb_right; 681 | parent = rb_parent(node); 682 | color = rb_color(node); 683 | 684 | if (parent == old) { 685 | parent = node; 686 | } else { 687 | if (child) 688 | rb_set_parent(child, parent); 689 | parent->rb_left = child; 690 | 691 | node->rb_right = old->rb_right; 692 | rb_set_parent(old->rb_right, node); 693 | } 694 | 695 | node->rb_parent_color = old->rb_parent_color; 696 | node->rb_left = old->rb_left; 697 | rb_set_parent(old->rb_left, node); 698 | 699 | goto color; 700 | } 701 | 702 | parent = rb_parent(node); 703 | color = rb_color(node); 704 | 705 | if (child) 706 | rb_set_parent(child, parent); 707 | if (parent) 708 | { 709 | if (parent->rb_left == node) 710 | parent->rb_left = child; 711 | else 712 | parent->rb_right = child; 713 | } 714 | else 715 | root->rb_node = child; 716 | 717 | color: 718 | if (color == RB_BLACK) 719 | __rb_erase_color(child, parent, root); 720 | } 721 | //EXPORT_SYMBOL(rb_erase); 722 | 723 | static void rb_augment_path(struct rb_node *node, rb_augment_f func, void *data) 724 | { 725 | struct rb_node *parent; 726 | 727 | up: 728 | func(node, data); 729 | parent = rb_parent(node); 730 | if (!parent) 731 | return; 732 | 733 | if (node == parent->rb_left && parent->rb_right) 734 | func(parent->rb_right, data); 735 | else if (parent->rb_left) 736 | func(parent->rb_left, data); 737 | 738 | node = parent; 739 | goto up; 740 | } 741 | 742 | /* 743 | * after inserting @node into the tree, update the tree to account for 744 | * both the new entry and any damage done by rebalance 745 | */ 746 | void rb_augment_insert(struct rb_node *node, rb_augment_f func, void *data) 747 | { 748 | if (node->rb_left) 749 | node = node->rb_left; 750 | else if (node->rb_right) 751 | node = node->rb_right; 752 | 753 | rb_augment_path(node, func, data); 754 | } 755 | 756 | /* 757 | * before removing the node, find the deepest node on the rebalance path 758 | * that will still be there after @node gets removed 759 | */ 760 | struct rb_node *rb_augment_erase_begin(struct rb_node *node) 761 | { 762 | struct rb_node *deepest; 763 | 764 | if (!node->rb_right && !node->rb_left) 765 | deepest = rb_parent(node); 766 | else if (!node->rb_right) 767 | deepest = node->rb_left; 768 | else if (!node->rb_left) 769 | deepest = node->rb_right; 770 | else { 771 | deepest = rb_next(node); 772 | if (deepest->rb_right) 773 | deepest = deepest->rb_right; 774 | else if (rb_parent(deepest) != node) 775 | deepest = rb_parent(deepest); 776 | } 777 | 778 | return deepest; 779 | } 780 | 781 | /* 782 | * after removal, update the tree to account for the removed entry 783 | * and any rebalance damage. 784 | */ 785 | void rb_augment_erase_end(struct rb_node *node, rb_augment_f func, void *data) 786 | { 787 | if (node) 788 | rb_augment_path(node, func, data); 789 | } 790 | 791 | /* 792 | * This function returns the first node (in sort order) of the tree. 793 | */ 794 | struct rb_node *rb_first(const struct rb_root *root) 795 | { 796 | struct rb_node *n; 797 | 798 | n = root->rb_node; 799 | if (!n) 800 | return NULL; 801 | while (n->rb_left) 802 | n = n->rb_left; 803 | return n; 804 | } 805 | //EXPORT_SYMBOL(rb_first); 806 | 807 | struct rb_node *rb_last(const struct rb_root *root) 808 | { 809 | struct rb_node *n; 810 | 811 | n = root->rb_node; 812 | if (!n) 813 | return NULL; 814 | while (n->rb_right) 815 | n = n->rb_right; 816 | return n; 817 | } 818 | //EXPORT_SYMBOL(rb_last); 819 | 820 | struct rb_node *rb_next(const struct rb_node *node) 821 | { 822 | struct rb_node *parent; 823 | 824 | if (rb_parent(node) == node) 825 | return NULL; 826 | 827 | /* If we have a right-hand child, go down and then left as far 828 | as we can. */ 829 | if (node->rb_right) { 830 | node = node->rb_right; 831 | while (node->rb_left) 832 | node=node->rb_left; 833 | return (struct rb_node *)node; 834 | } 835 | 836 | /* No right-hand children. Everything down and left is 837 | smaller than us, so any 'next' node must be in the general 838 | direction of our parent. Go up the tree; any time the 839 | ancestor is a right-hand child of its parent, keep going 840 | up. First time it's a left-hand child of its parent, said 841 | parent is our 'next' node. */ 842 | while ((parent = rb_parent(node)) && node == parent->rb_right) 843 | node = parent; 844 | 845 | return parent; 846 | } 847 | //EXPORT_SYMBOL(rb_next); 848 | 849 | struct rb_node *rb_prev(const struct rb_node *node) 850 | { 851 | struct rb_node *parent; 852 | 853 | if (rb_parent(node) == node) 854 | return NULL; 855 | 856 | /* If we have a left-hand child, go down and then right as far 857 | as we can. */ 858 | if (node->rb_left) { 859 | node = node->rb_left; 860 | while (node->rb_right) 861 | node=node->rb_right; 862 | return (struct rb_node *)node; 863 | } 864 | 865 | /* No left-hand children. Go up till we find an ancestor which 866 | is a right-hand child of its parent */ 867 | while ((parent = rb_parent(node)) && node == parent->rb_left) 868 | node = parent; 869 | 870 | return parent; 871 | } 872 | //EXPORT_SYMBOL(rb_prev); 873 | 874 | void rb_replace_node(struct rb_node *victim, struct rb_node *new, 875 | struct rb_root *root) 876 | { 877 | struct rb_node *parent = rb_parent(victim); 878 | 879 | /* Set the surrounding nodes to point to the replacement */ 880 | if (parent) { 881 | if (victim == parent->rb_left) 882 | parent->rb_left = new; 883 | else 884 | parent->rb_right = new; 885 | } else { 886 | root->rb_node = new; 887 | } 888 | if (victim->rb_left) 889 | rb_set_parent(victim->rb_left, new); 890 | if (victim->rb_right) 891 | rb_set_parent(victim->rb_right, new); 892 | 893 | /* Copy the pointers/colour from the victim to the replacement */ 894 | *new = *victim; 895 | } 896 | //EXPORT_SYMBOL(rb_replace_node); 897 | 898 | // rbtree.c 899 | // }}} 900 | // rbtree.c 901 | // rbtree.c source codes 902 | -------------------------------------------------------------------------------- /yhrbtree.h: -------------------------------------------------------------------------------- 1 | #ifndef __RCYH_YHRBTREE_H__ 2 | #define __RCYH_YHRBTREE_H__ 3 | #ifdef __cplusplus 4 | extern "C" 5 | { 6 | #endif 7 | #pragma pack(push) 8 | #pragma pack(4) 9 | #pragma pack(pop) 10 | 11 | /* 12 | Container Of Red Black Trees 13 | (C) 2011 Hong Yuan 14 | */ 15 | 16 | 17 | /**********************************************************/ 18 | #ifndef offsetof 19 | #define offsetof(type, member) \ 20 | (size_t)&(((type *)0)->member) 21 | #endif 22 | 23 | #ifndef container_of 24 | #define container_of(ptr, type, member) \ 25 | ({\ 26 | const typeof(((type *)0)->member) * __mptr = (ptr);\ 27 | (type *)((char *)__mptr - offsetof(type, member)); \ 28 | }) 29 | #endif 30 | /**********************************************************/ 31 | 32 | // rbtree.h header codes 33 | // rbtree.h 34 | // {{{ 35 | // rbtree.h 36 | 37 | /* This is linux/include/linux/rbtree.h */ 38 | 39 | /* 40 | Red Black Trees 41 | (C) 1999 Andrea Arcangeli 42 | 43 | This program is free software; you can redistribute it and/or modify 44 | it under the terms of the GNU General Public License as published by 45 | the Free Software Foundation; either version 2 of the License, or 46 | (at your option) any later version. 47 | 48 | This program is distributed in the hope that it will be useful, 49 | but WITHOUT ANY WARRANTY; without even the implied warranty of 50 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51 | GNU General Public License for more details. 52 | 53 | You should have received a copy of the GNU General Public License 54 | along with this program; if not, write to the Free Software 55 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 56 | 57 | linux/include/linux/rbtree.h 58 | 59 | To use rbtrees you'll have to implement your own insert and search cores. 60 | This will avoid us to use callbacks and to drop drammatically performances. 61 | I know it's not the cleaner way, but in C (not in C++) to get 62 | performances and genericity... 63 | 64 | Some example of insert and search follows here. The search is a plain 65 | normal search over an ordered tree. The insert instead must be implemented 66 | in two steps: First, the code must insert the element in order as a red leaf 67 | in the tree, and then the support library function rb_insert_color() must 68 | be called. Such function will do the not trivial work to rebalance the 69 | rbtree, if necessary. 70 | 71 | ----------------------------------------------------------------------- 72 | static inline struct page * rb_search_page_cache(struct inode * inode, 73 | unsigned long offset) 74 | { 75 | struct rb_node * n = inode->i_rb_page_cache.rb_node; 76 | struct page * page; 77 | 78 | while (n) 79 | { 80 | page = rb_entry(n, struct page, rb_page_cache); 81 | 82 | if (offset < page->offset) 83 | n = n->rb_left; 84 | else if (offset > page->offset) 85 | n = n->rb_right; 86 | else 87 | return page; 88 | } 89 | return NULL; 90 | } 91 | 92 | static inline struct page * __rb_insert_page_cache(struct inode * inode, 93 | unsigned long offset, 94 | struct rb_node * node) 95 | { 96 | struct rb_node ** p = &inode->i_rb_page_cache.rb_node; 97 | struct rb_node * parent = NULL; 98 | struct page * page; 99 | 100 | while (*p) 101 | { 102 | parent = *p; 103 | page = rb_entry(parent, struct page, rb_page_cache); 104 | 105 | if (offset < page->offset) 106 | p = &(*p)->rb_left; 107 | else if (offset > page->offset) 108 | p = &(*p)->rb_right; 109 | else 110 | return page; 111 | } 112 | 113 | rb_link_node(node, parent, p); 114 | 115 | return NULL; 116 | } 117 | 118 | static inline struct page * rb_insert_page_cache(struct inode * inode, 119 | unsigned long offset, 120 | struct rb_node * node) 121 | { 122 | struct page * ret; 123 | if ((ret = __rb_insert_page_cache(inode, offset, node))) 124 | goto out; 125 | rb_insert_color(node, &inode->i_rb_page_cache); 126 | out: 127 | return ret; 128 | } 129 | ----------------------------------------------------------------------- 130 | */ 131 | 132 | #ifndef _LINUX_RBTREE_H 133 | #define _LINUX_RBTREE_H 134 | 135 | #include 136 | 137 | struct rb_node 138 | { 139 | unsigned long rb_parent_color; 140 | #define RB_RED 0 141 | #define RB_BLACK 1 142 | struct rb_node *rb_right; 143 | struct rb_node *rb_left; 144 | } __attribute__((aligned(sizeof(long)))); 145 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 146 | 147 | 148 | /* Callback of generic container */ 149 | typedef const int cmp_func_t(const void * pkey1, const void * pkey2); 150 | typedef const void* getkey_func_t(const void * pdata); 151 | 152 | /* 153 | * Generic container: 154 | * Root of Red Black Trees 155 | * Manager information 156 | */ 157 | typedef struct rb_root 158 | { 159 | /* 160 | * Root of Red Black Trees 161 | */ 162 | struct rb_node *rb_node; 163 | /* 164 | * callback of comparison function for node 165 | */ 166 | cmp_func_t *cmp; 167 | /* 168 | * callback of get key value for node 169 | */ 170 | getkey_func_t *getkey; 171 | } rb_root_t; 172 | 173 | 174 | #define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3)) 175 | #define rb_color(r) ((r)->rb_parent_color & 1) 176 | #define rb_is_red(r) (!rb_color(r)) 177 | #define rb_is_black(r) rb_color(r) 178 | #define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0) 179 | #define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0) 180 | 181 | static 182 | inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) 183 | { 184 | rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p; 185 | } 186 | static 187 | inline void rb_set_color(struct rb_node *rb, int color) 188 | { 189 | rb->rb_parent_color = (rb->rb_parent_color & ~1) | color; 190 | } 191 | 192 | #define RB_ROOT (struct rb_root) { NULL, } 193 | #define rb_entry(ptr, type, member) container_of(ptr, type, member) 194 | 195 | #define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL) 196 | #define RB_EMPTY_NODE(node) (rb_parent(node) == node) 197 | #define RB_CLEAR_NODE(node) (rb_set_parent(node, node)) 198 | 199 | extern void rb_insert_color(struct rb_node *, struct rb_root *); 200 | extern void rb_erase(struct rb_node *, struct rb_root *); 201 | 202 | typedef void (*rb_augment_f)(struct rb_node *node, void *data); 203 | 204 | extern void rb_augment_insert(struct rb_node *node, 205 | rb_augment_f func, void *data); 206 | extern struct rb_node *rb_augment_erase_begin(struct rb_node *node); 207 | extern void rb_augment_erase_end(struct rb_node *node, 208 | rb_augment_f func, void *data); 209 | 210 | /* Find logical next and previous nodes in a tree */ 211 | extern struct rb_node *rb_next(const struct rb_node *); 212 | extern struct rb_node *rb_prev(const struct rb_node *); 213 | extern struct rb_node *rb_first(const struct rb_root *); 214 | extern struct rb_node *rb_last(const struct rb_root *); 215 | 216 | /* Fast replacement of a single node without remove/rebalance/add/rebalance */ 217 | extern void rb_replace_node(struct rb_node *victim, struct rb_node *_new, 218 | struct rb_root *root); 219 | 220 | static 221 | inline void rb_link_node(struct rb_node * node, struct rb_node * parent, 222 | struct rb_node ** rb_link) 223 | { 224 | node->rb_parent_color = (unsigned long )parent; 225 | node->rb_left = node->rb_right = NULL; 226 | 227 | *rb_link = node; 228 | } 229 | 230 | #endif /* _LINUX_RBTREE_H */ 231 | 232 | // rbtree.h 233 | // }}} 234 | // rbtree.h 235 | // rbtree.h header codes 236 | 237 | 238 | 239 | /* 240 | * Generic container: 241 | * Leaf node of Red Black Trees 242 | * Node information and data 243 | */ 244 | typedef struct rb_node_data 245 | { 246 | struct rb_node rb_node; 247 | unsigned long size; 248 | unsigned char data[]; 249 | }rb_node_t; 250 | typedef rb_node_t rb_node_data_t; 251 | typedef rb_node_t rb_nd_t; 252 | 253 | /* 254 | * Initializing rbtree root 255 | */ 256 | void rbt_init(struct rb_root *root, getkey_func_t * getkey , cmp_func_t *cmp); 257 | /* 258 | * stack alloc rbtree node-data 259 | */ 260 | 261 | struct rb_node_data *rbt_node_new(size_t size); 262 | /* 263 | * free rbtree node-data 264 | */ 265 | void rbt_node_free(struct rb_node_data *node); 266 | 267 | /* 268 | * node field location 269 | */ 270 | struct rb_node_data* get_node_entry_from(void *data_field); 271 | int get_node_data_size(void *data_field); 272 | 273 | void * get_data_pointer(struct rb_node_data *rnd); 274 | int get_data_size(struct rb_node_data *rnd); 275 | 276 | /* 277 | * Search key node from rbtree 278 | */ 279 | struct rb_node_data * 280 | rbt_search(struct rb_root *root, const void* key); 281 | 282 | /* 283 | * Insert key node into rbtree 284 | */ 285 | int rbt_insert(struct rb_root *root, struct rb_node_data *cont); 286 | 287 | /* 288 | * Delete the key node from rbtree 289 | * delete node from rbtree, return node pointer 290 | */ 291 | struct rb_node_data * 292 | rbt_delete(struct rb_root *root, const void *key); 293 | 294 | /* 295 | * Erase the node from rbtree, return deleted node pointer 296 | * *** use with caution, node must exist in rbtree *** 297 | * *** example: *** 298 | struct rb_node_data *node; 299 | node = rbt_search(&root, key); 300 | if (node) 301 | { 302 | // use node 303 | // action code 304 | rbt_erase(&root, node); 305 | rbt_node_free(node); 306 | node = NULL; 307 | } 308 | * 309 | */ 310 | void rbt_erase(struct rb_root *root, struct rb_node_data *node); 311 | 312 | /* 313 | * Replace the key node from rbtree for new rb_node_data 314 | * replace node from rbtree, return old node pointer 315 | */ 316 | struct rb_node_data * rbt_replace(struct rb_root *root, 317 | struct rb_node_data *current_node); 318 | 319 | /* 320 | * Traversing the rbtree, all the node data call action 321 | */ 322 | int rbt_inorder(struct rb_root *root, void *pedata, 323 | int (*action)(void *pndata, void *pedata), int *action_succ_ret); 324 | 325 | /* 326 | * clear the rbtree 327 | * callback the action before the free of the node data 328 | */ 329 | int rbt_clear(struct rb_root *root, void *pedata, 330 | int (*action)(void *pndata, void *pedata), int *action_succ_ret); 331 | 332 | /* 333 | * Get first and last node from rbtree 334 | */ 335 | struct rb_node_data * rbt_node_first(struct rb_root *root); 336 | struct rb_node_data * rbt_node_last(struct rb_root *root); 337 | 338 | /* 339 | * Get first and last data of node from rbtree 340 | */ 341 | void * rbt_data_first(struct rb_root *root); 342 | void * rbt_data_last(struct rb_root *root); 343 | 344 | /* 345 | * Get next and prev node from rbtree 346 | */ 347 | struct rb_node_data 348 | *rbt_node_next(struct rb_node_data *data_node); 349 | struct rb_node_data 350 | *rbt_node_prev(struct rb_node_data *data_node); 351 | 352 | /* 353 | * Get next and prev data of node from rbtree 354 | */ 355 | void *rbt_data_next(struct rb_node_data *data_node); 356 | void *rbt_data_prev(struct rb_node_data *data_node); 357 | 358 | 359 | 360 | #ifdef __cplusplus 361 | } 362 | #endif 363 | #endif /* __RCYH_YHRBTREE_H__ */ 364 | -------------------------------------------------------------------------------- /yhtime.c: -------------------------------------------------------------------------------- 1 | #include "yhtime.h" 2 | 3 | void maketimeout_minutes(struct timespec *tsp, long minutes) 4 | { 5 | struct timeval now; 6 | gettimeofday(&now, NULL); 7 | tsp->tv_sec = now.tv_sec + minutes * 60; 8 | tsp->tv_nsec = now.tv_usec * 1000; 9 | } 10 | void maketimeout_seconds(struct timespec *tsp, long seconds) 11 | { 12 | struct timeval now; 13 | gettimeofday(&now, NULL); 14 | tsp->tv_sec = now.tv_sec + seconds; 15 | tsp->tv_nsec = now.tv_usec * 1000; 16 | } 17 | void maketimeout_milliseconds(struct timespec *tsp, long millisconds) 18 | { 19 | struct timeval now; 20 | gettimeofday(&now, NULL); 21 | tsp->tv_sec = now.tv_sec + millisconds / 1000; 22 | tsp->tv_nsec = now.tv_usec * 1000 + millisconds % 1000 * 1000000; 23 | } 24 | void maketimeout_microsecond(struct timespec *tsp, long microsecond) 25 | { 26 | struct timeval now; 27 | gettimeofday(&now, NULL); 28 | tsp->tv_sec = now.tv_sec + microsecond / 1000000; 29 | tsp->tv_nsec = now.tv_usec * 1000 + microsecond % 1000000 * 1000; 30 | } 31 | void maketimeout_nanoseconds(struct timespec *tsp, long nanoseconds) 32 | { 33 | struct timeval now; 34 | gettimeofday(&now, NULL); 35 | tsp->tv_sec = now.tv_sec + nanoseconds / 1000000000UL; 36 | tsp->tv_nsec = now.tv_usec * 1000 + nanoseconds % 1000000000UL; 37 | } 38 | 39 | void maketimeout_min(struct timespec *tsp, long minutes) 40 | { 41 | maketimeout_minutes(tsp, minutes); 42 | } 43 | void maketimeout_sec(struct timespec *tsp, long seconds) 44 | { 45 | maketimeout_seconds(tsp, seconds); 46 | } 47 | void maketimeout_msec(struct timespec *tsp, long millisconds) 48 | { 49 | maketimeout_milliseconds(tsp, millisconds); 50 | } 51 | void maketimeout_usec(struct timespec *tsp, long microsecond) 52 | { 53 | maketimeout_microsecond(tsp, microsecond); 54 | } 55 | void maketimeout_nsec(struct timespec *tsp, long nanoseconds) 56 | { 57 | maketimeout_nanoseconds(tsp, nanoseconds); 58 | } 59 | -------------------------------------------------------------------------------- /yhtime.h: -------------------------------------------------------------------------------- 1 | #ifndef __YH_YHTIME_H__ 2 | #define __YH_YHTIME_H__ 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" 9 | { 10 | #endif 11 | 12 | #pragma pack(push) 13 | #pragma pack(1) 14 | #pragma pack(pop) 15 | 16 | void maketimeout_minutes(struct timespec *tsp, long minutes); 17 | void maketimeout_seconds(struct timespec *tsp, long seconds); 18 | void maketimeout_milliseconds(struct timespec *tsp, long millisconds); 19 | void maketimeout_microsecond(struct timespec *tsp, long microsecond); 20 | void maketimeout_nanoseconds(struct timespec *tsp, long nanoseconds); 21 | 22 | void maketimeout_min(struct timespec *tsp, long minutes); 23 | void maketimeout_sec(struct timespec *tsp, long seconds); 24 | void maketimeout_msec(struct timespec *tsp, long millisconds); 25 | void maketimeout_usec(struct timespec *tsp, long microsecond); 26 | void maketimeout_nsec(struct timespec *tsp, long nanoseconds); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | #endif /* __YH_YHTIME_H__ */ 32 | --------------------------------------------------------------------------------