Skip to content

Commit 62d4ad8

Browse files
committed
1 parent 29dd926 commit 62d4ad8

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

test/test.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ AM_LDFLAGS = -lz -lpthread -L${top_srcdir}/.libs -lev
88
check_PROGRAMS = \
99
test/test_eof \
1010
test/test_timeout
11+
test/test_tcp_reset
1112

1213
TESTS = $(check_PROGRAMS)
1314

1415
test_test_eof_SOURCES = test/test_eof.c
1516
test_test_timeout_SOURCES = test/test_timeout.c
17+
test_test_tcp_reset_SOURCES = test/test_tcp_reset.c

test/test_tcp_reset.c

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/* read/write and timeout */
2+
#include <netdb.h>
3+
#include <stddef.h>
4+
#include <stdio.h>
5+
#include <stdlib.h>
6+
#include <sys/file.h>
7+
#include <sys/socket.h>
8+
#include <sys/stat.h>
9+
#include <sys/types.h>
10+
#include <unistd.h>
11+
#include <errno.h>
12+
13+
#include <ev.h>
14+
15+
#define GO_LABEL(code, label) \
16+
do { \
17+
rc = (code); \
18+
goto label; \
19+
} while (0);
20+
21+
int rc = 0;
22+
23+
typedef struct {
24+
ev_io watcher;
25+
ev_timer timer;
26+
} io_t;
27+
28+
int ignore_sigpipe() {
29+
struct sigaction sa, osa;
30+
sa.sa_handler = SIG_IGN;
31+
sigemptyset(&sa.sa_mask);
32+
sa.sa_flags = 0;
33+
return sigaction(SIGPIPE, &sa, &osa);
34+
}
35+
36+
/*
37+
* sock_type - 0, SOCK_STREAM, SOCK_DGRAM
38+
* family - AF_UNSPEC Allow IPv4 or IPv6,
39+
* return getaddrinfo result code
40+
*/
41+
int getaddrinfo_all(const char *host, const char *service, int sock_type,
42+
int protocol, int family, struct addrinfo *result) {
43+
struct addrinfo hints;
44+
45+
memset(&hints, 0, sizeof(struct addrinfo));
46+
hints.ai_family = family;
47+
hints.ai_socktype = sock_type;
48+
hints.ai_protocol = protocol;
49+
hints.ai_flags =
50+
AI_PASSIVE; /* Don't return IPv6 addresses on loopback if IPv4 exists */
51+
52+
return getaddrinfo(host, service, &hints, &result);
53+
}
54+
55+
int set_nonblock(int fd) {
56+
int flags;
57+
if ((flags = fcntl(fd, F_GETFL, 0)) == -1)
58+
flags = 0;
59+
return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
60+
}
61+
62+
/* another callback, this time for a time-out */
63+
static void timeout_cb(EV_P_ ev_timer *w, int revents) {
64+
io_t *client = (io_t *) (((char *) w) - offsetof(io_t, timer));
65+
ev_timer_stop(EV_A_ w);
66+
puts("timeout");
67+
if (rc == 0)
68+
rc = -1;
69+
/* close socket */
70+
close(client->watcher.fd);
71+
}
72+
73+
static void connect_cb(EV_P_ ev_io *w, int revents) {
74+
io_t *client = (io_t *) (((char *) w) - offsetof(io_t, watcher));
75+
ssize_t n;
76+
ev_io_stop(EV_A_ w);
77+
if ((n = read(w->fd, client->buf, sizeof(client->buf))) > 0) {
78+
if (rc == -1)
79+
rc = 1;
80+
ev_io_start(EV_A_ w);
81+
} else {
82+
close(w->fd);
83+
printf("close reader: %zd, revents: %d\n", n, revents);
84+
ev_break(EV_A_ EVBREAK_ALL);
85+
}
86+
}
87+
88+
int main(int argc, char *argv[]) {
89+
int fd;
90+
io_t client;
91+
92+
int s;
93+
char *host = "127.0.0.1";
94+
char *service = "20150";
95+
struct addrinfo *address;
96+
97+
ignore_sigpipe();
98+
99+
if ((getaddrinfo_i(host, service, SOCK_STREAM, AF_UNSPEC, &address)) != 0) {
100+
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
101+
exit(EXIT_FAILURE);
102+
GO_LABEL(-1, EXIT);
103+
}
104+
if ((fd = socket(address->ai_family, address->ai_socktype,
105+
address->ai_protocol)) == -1) {
106+
fprintf(stderr, "connect failed. %s\n", strerror(errno));
107+
freeaddrinfo(address);
108+
GO_LABEL(-1, EXIT);
109+
}
110+
if (connect(fd, address->ai_addr, address->ai_addrlen) == -1) {
111+
fprintf(stderr, "connect failed. %s\n", strerror(errno));
112+
freeaddrinfo(address);
113+
GO_LABEL(-1, EXIT);
114+
}
115+
freeaddrinfo(address);
116+
117+
set_nonblock(fd);
118+
119+
return 0;
120+
121+
rc = -1;
122+
123+
struct ev_loop *loop = EV_DEFAULT;
124+
125+
/* start watcher */
126+
ev_io_init(&client.watcher, connect_cb, fd, EV_WRITE);
127+
ev_io_start(loop, &client.watcher);
128+
129+
/* initialise a timer watcher, then start non-repeating 5.0 second timeout
130+
*/
131+
ev_timer_init(&client.timer, timeout_cb, .2, 0.);
132+
ev_timer_start(loop, &client.timer);
133+
134+
ev_run(loop, 0);
135+
EXIT:
136+
return rc;
137+
}

0 commit comments

Comments
 (0)