├── .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 |
--------------------------------------------------------------------------------