7 #include <event2/bufferevent.h>
8 #include <event2/buffer.h>
9 #include <event2/listener.h>
10 #include <event2/util.h>
11 #include <event2/event.h>
15 #define MAX_LINE 16384
17 static const char MESSAGE[] = "Hello, World!\n";
19 static const char PATH[] = "./roura";
21 static void listener_cb(evutil_socket_t, short, void *);
22 static void conn_read_cb(struct bufferevent *, void *);
23 static void conn_write_cb(struct bufferevent *, void *);
24 static void conn_event_cb(struct bufferevent *, short, void *);
25 static void signal_cb(evutil_socket_t, short, void *);
27 static char rot13_char(char);
29 int main(int argc, char **argv) {
30 struct event_base *base;
31 evutil_socket_t listener;
32 struct event *listener_event;
33 struct event *signal_event;
35 struct sockaddr_un sun;
37 setvbuf(stdout, NULL, _IONBF, 0);
39 base = event_base_new();
41 fprintf(stderr, "Could not initialize libevent!\n");
45 memset(&sun, 0, sizeof (sun));
46 sun.sun_family = AF_UNIX;
47 strcpy(sun.sun_path, PATH);
49 listener = socket(AF_UNIX, SOCK_STREAM, 0);
50 evutil_make_socket_nonblocking(listener);
52 if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) {
53 fprintf(stderr, "Could not create domain socket: %s!\n", PATH);
57 if (listen(listener, 16) < 0) {
58 fprintf(stderr, "Could not listen\n");
62 listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base);
64 if (!listener_event) {
65 fprintf(stderr, "Could not do event_new\n");
69 event_add(listener_event, NULL);
71 signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base);
73 if (!signal_event || event_add(signal_event, NULL) < 0) {
74 fprintf(stderr, "Could not create/add a signal event!\n");
78 event_base_dispatch(base);
80 event_free(listener_event);
81 event_free(signal_event);
82 event_base_free(base);
84 // smažeme soket na disku / soubor -- jinak by program příště spadl na evconnlistener_new_bind()
91 static void listener_cb(evutil_socket_t listener, short event, void *user_data) {
92 struct event_base *base = (event_base *) user_data;
93 struct bufferevent *bev;
95 struct sockaddr_storage ss;
96 socklen_t slen = sizeof (ss);
97 int fd = accept(listener, (struct sockaddr*) &ss, &slen);
99 fprintf(stderr, "Unable to accept(): %d", fd);
101 } else if (fd > FD_SETSIZE) {
106 evutil_make_socket_nonblocking(fd);
108 bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
110 fprintf(stderr, "Error constructing bufferevent!");
111 event_base_loopbreak(base);
114 bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, NULL);
115 bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE);
116 bufferevent_enable(bev, EV_READ | EV_WRITE);
118 printf("někdo se k nám připojil! / %p\n", bev);
120 bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
123 static void conn_read_cb(struct bufferevent *bev, void *user_data) {
124 /* This callback is invoked when there is data to read on bev. */
125 struct evbuffer *input = bufferevent_get_input(bev);
126 struct evbuffer *output = bufferevent_get_output(bev);
127 struct event_base *base = (event_base *) user_data;
129 size_t len = evbuffer_get_length(input);
132 data = (char*) malloc(len);
133 evbuffer_copyout(input, data, len);
138 while ((data = evbuffer_readln(input, &n, EVBUFFER_EOL_LF))) {
139 for (i = 0; i < n; ++i)
140 data[i] = rot13_char(data[i]);
141 evbuffer_add(output, data, n);
142 evbuffer_add(output, "\n", 1);
146 printf("we got some data...\n");
149 if (memcmp(data, "exit\n", len) == 0) {
150 struct timeval delay = {2, 123};
151 event_base_loopexit(base, &delay);
155 if (evbuffer_get_length(input) >= MAX_LINE) {
156 /* Too long; just process what there is and go on so that the buffer
157 * doesn't grow infinitely long. */
159 while (evbuffer_get_length(input)) {
160 int n = evbuffer_remove(input, buf, sizeof (buf));
161 for (i = 0; i < n; ++i)
162 buf[i] = rot13_char(buf[i]);
163 evbuffer_add(output, buf, n);
165 evbuffer_add(output, "\n", 1);
168 /* Copy all the data from the input buffer to the output buffer. */
170 evbuffer_add_buffer(output, input);
175 static void conn_write_cb(struct bufferevent *bev, void *user_data) {
176 struct evbuffer *output = bufferevent_get_output(bev);
177 if (evbuffer_get_length(output) == 0) {
178 printf("flushed answer / %p\n", bev);
179 /* nebudeme ukončovat spojení
180 bufferevent_free(bev);
185 static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
186 if (events & BEV_EVENT_EOF) {
187 printf("Connection closed.\n");
188 } else if (events & BEV_EVENT_ERROR) {
189 printf("Got an error on the connection: %s\n", strerror(errno));
192 // None of the other events can happen here, since we haven't enabled timeouts
193 bufferevent_free(bev);
196 static void signal_cb(evutil_socket_t sig, short events, void *user_data) {
197 struct event_base *base = (event_base *) user_data;
198 struct timeval delay = {2, 123};
200 printf("Zachycen SIGINT (Ctrl+C); ukončuji program během %ld sekund a %ld mikrosekund.\n", delay.tv_sec, delay.tv_usec);
202 event_base_loopexit(base, &delay);
205 static char rot13_char(char c) {
206 /* We don't want to use isalpha here; setting the locale would change
207 * which characters are considered alphabetical. */
208 if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
210 else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))