diff -r efa6fc19b006 -r baa90e4359c8 c++/domain-socket-bridge/domain-socket-bridge.c --- a/c++/domain-socket-bridge/domain-socket-bridge.c Sat Nov 19 18:27:08 2016 +0100 +++ b/c++/domain-socket-bridge/domain-socket-bridge.c Sat Nov 19 19:29:54 2016 +0100 @@ -18,19 +18,24 @@ static const char PATH[] = "./roura"; -static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *); +static void listener_cb(evutil_socket_t, short, void *); static void conn_read_cb(struct bufferevent *, void *); static void conn_write_cb(struct bufferevent *, void *); static void conn_event_cb(struct bufferevent *, short, void *); static void signal_cb(evutil_socket_t, short, void *); +static char rot13_char(char); + int main(int argc, char **argv) { struct event_base *base; - struct evconnlistener *listener; + evutil_socket_t listener; + struct event *listener_event; struct event *signal_event; struct sockaddr_un sun; + setvbuf(stdout, NULL, _IONBF, 0); + base = event_base_new(); if (!base) { fprintf(stderr, "Could not initialize libevent!\n"); @@ -41,16 +46,28 @@ sun.sun_family = AF_UNIX; strcpy(sun.sun_path, PATH); - listener = evconnlistener_new_bind(base, listener_cb, (void *) base, - LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1, - (struct sockaddr*) &sun, - sizeof (sun)); + listener = socket(AF_UNIX, SOCK_STREAM, 0); + evutil_make_socket_nonblocking(listener); - if (!listener) { + if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) { fprintf(stderr, "Could not create domain socket: %s!\n", PATH); return 1; } + if (listen(listener, 16) < 0) { + fprintf(stderr, "Could not listen\n"); + return 1; + } + + listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base); + + if (!listener_event) { + fprintf(stderr, "Could not do event_new\n"); + return 1; + } + + event_add(listener_event, NULL); + signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base); if (!signal_event || event_add(signal_event, NULL) < 0) { @@ -60,7 +77,7 @@ event_base_dispatch(base); - evconnlistener_free(listener); + event_free(listener_event); event_free(signal_event); event_base_free(base); @@ -71,12 +88,24 @@ return 0; } -static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) { +static void listener_cb(evutil_socket_t listener, short event, void *user_data) { struct event_base *base = (event_base *) user_data; struct bufferevent *bev; - //bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); // zavírá spojení - bev = bufferevent_socket_new(base, fd, 0); // nezavírá spojení + struct sockaddr_storage ss; + socklen_t slen = sizeof (ss); + int fd = accept(listener, (struct sockaddr*) &ss, &slen); + if (fd < 0) { + fprintf(stderr, "Unable to accept(): %d", fd); + return; + } else if (fd > FD_SETSIZE) { + close(fd); + return; + } + + evutil_make_socket_nonblocking(fd); + + bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); if (!bev) { fprintf(stderr, "Error constructing bufferevent!"); event_base_loopbreak(base); @@ -99,26 +128,57 @@ size_t len = evbuffer_get_length(input); char *data; + /* data = (char*) malloc(len); evbuffer_copyout(input, data, len); + */ - printf("we got some data: %s / %d\n", data, memcmp(data, "exit", len)); + size_t n; + int i; + while ((data = evbuffer_readln(input, &n, EVBUFFER_EOL_LF))) { + for (i = 0; i < n; ++i) + data[i] = rot13_char(data[i]); + evbuffer_add(output, data, n); + evbuffer_add(output, "\n", 1); + free(data); + } + printf("we got some data...\n"); + + /* if (memcmp(data, "exit\n", len) == 0) { struct timeval delay = {2, 123}; event_base_loopexit(base, &delay); } + */ + + if (evbuffer_get_length(input) >= MAX_LINE) { + /* Too long; just process what there is and go on so that the buffer + * doesn't grow infinitely long. */ + char buf[1024]; + while (evbuffer_get_length(input)) { + int n = evbuffer_remove(input, buf, sizeof (buf)); + for (i = 0; i < n; ++i) + buf[i] = rot13_char(buf[i]); + evbuffer_add(output, buf, n); + } + evbuffer_add(output, "\n", 1); + } /* Copy all the data from the input buffer to the output buffer. */ + /* evbuffer_add_buffer(output, input); free(data); + */ } static void conn_write_cb(struct bufferevent *bev, void *user_data) { struct evbuffer *output = bufferevent_get_output(bev); if (evbuffer_get_length(output) == 0) { printf("flushed answer / %p\n", bev); + /* nebudeme ukončovat spojení bufferevent_free(bev); + */ } } @@ -141,3 +201,14 @@ event_base_loopexit(base, &delay); } + +static char rot13_char(char c) { + /* We don't want to use isalpha here; setting the locale would change + * which characters are considered alphabetical. */ + if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M')) + return c + 13; + else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z')) + return c - 13; + else + return c; +}