-
Notifications
You must be signed in to change notification settings - Fork 2
/
tcp-non-blocking-libevent-echo-server.c
116 lines (100 loc) · 2.66 KB
/
tcp-non-blocking-libevent-echo-server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/event.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_LINE 16384
void on_read(struct bufferevent *bev, void *ctx)
{
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev);
char *line;
size_t n;
while ((line = evbuffer_readln(input, &n, EVBUFFER_EOL_LF)))
{
evbuffer_add(output, line, n);
evbuffer_add(output, "\n", 1);
free(line);
}
if (evbuffer_get_length(input) >= MAX_LINE)
{
/* line is too long */
char buf[1024];
while (evbuffer_get_length(input))
{
int n = evbuffer_remove(input, buf, sizeof(buf));
evbuffer_add(output, buf, n);
}
evbuffer_add(output, "\n", 1);
}
}
void on_error(struct bufferevent *bev, short error, void *ctx)
{
if (error & BEV_EVENT_EOF)
{
}
else if (error & BEV_EVENT_ERROR)
{
}
else if (error & BEV_EVENT_TIMEOUT)
{
}
bufferevent_free(bev);
}
void on_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = (struct event_base *)arg;
struct sockaddr_storage ss;
socklen_t slen = sizeof(ss);
int fd = accept(listener, (struct sockaddr *)&ss, &slen);
if (fd < 0)
{
perror("accept");
}
else if (fd > FD_SETSIZE)
{
close(fd);
}
else
{
evutil_make_socket_nonblocking(fd);
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
bufferevent_setcb(bev, on_read, NULL, on_error, NULL);
bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE);
bufferevent_enable(bev, EV_READ | EV_WRITE);
}
}
int main(int argc, char **argv)
{
evutil_socket_t listener = socket(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(listener);
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(40713);
if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
perror("bind");
return 1;
}
if (listen(listener, 16) < 0)
{
perror("listen");
return 1;
}
struct event_base *base = event_base_new();
base = event_base_new();
if (!base)
return 1;
struct event *listener_event = event_new(base, listener, EV_READ | EV_PERSIST, on_accept, (void *)base);
event_add(listener_event, NULL);
event_base_dispatch(base);
return 0;
}