# HG changeset patch # User František Kučera # Date 1479670830 -3600 # Node ID 2383ed4da5075b9c4f35c1be518173bea470bc7e # Parent ba40af6cf81565191238d548a07cb110641809e3 libevent: c++ diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/domain-socket-bridge.c --- a/c++/domain-socket-bridge/domain-socket-bridge.c Sun Nov 20 20:39:08 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std; - -static const char MESSAGE[] = "Hello, World!\n"; - -static const char PATH[] = "./roura"; - -static const string COMMAND_EXIT("exit\n"); - -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 void print_socket_info(int, int); - -int main(int argc, char **argv) { - printf("%4s %8s\n", "*", "STARTED"); - struct event_base *base; - 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) { - printf("%4s %8s %s\n", "*", "ERROR", "unable to initialize libevent"); - return 1; - } - - memset(&sun, 0, sizeof (sun)); - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, PATH); - - listener = socket(AF_UNIX, SOCK_STREAM, 0); - evutil_make_socket_nonblocking(listener); - - if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) { - printf("%4s %8s %s: %s\n", "*", "ERROR", "unable to create domain socket:", PATH); - return 1; - } - - if (listen(listener, 16) < 0) { - printf("%4s %8s %s\n", "*", "ERROR", "unable to listen"); - return 1; - } - - // identifikátor serverového soketu (v současnosti číslo FD) - printf("%4s %8s listening at: sun_path = %s → socketId = %d\n", "*", "SOCKET", sun.sun_path, listener); - - listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base); - - if (!listener_event) { - printf("%4s %8s %s\n", "*", "ERROR", "unable to do event_new()"); - 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) { - printf("%4s %8s %s\n", "*", "ERROR", "unable to create/add a signal event"); - return 1; - } - - event_base_dispatch(base); - - event_free(listener_event); - event_free(signal_event); - event_base_free(base); - - // smažeme soket na disku / soubor -- jinak by program příště spadl na bind() - // TODO: co když soket někdo přesune a místo něj dá jiný soubor? - unlink(PATH); - - printf("%4s %8s\n", "*", "FINISHED"); - return 0; -} - -static void listener_cb(evutil_socket_t listener, short event, void *user_data) { - struct event_base *base = (event_base *) user_data; - struct bufferevent *bev; - - struct sockaddr_storage ss; - socklen_t slen = sizeof (ss); - int fd = accept(listener, (struct sockaddr*) &ss, &slen); - - // identifikátor navázaného spojení (v současnosti číslo FD) - int * connectionId = (int*) malloc(sizeof (fd)); - *connectionId = fd; - - if (fd < 0) { - printf("%4d %8s %s\n", *connectionId, "ERROR", "unable to accept()"); - return; - } else if (fd > FD_SETSIZE) { - // FD_SETSIZE = 1024 -- Proč? Co když bude spojení víc? - printf("%4d %8s fd (%d) > FD_SETSIZE (%d)\n", *connectionId, "ERROR", fd, FD_SETSIZE); - close(fd); - return; - } - - evutil_make_socket_nonblocking(fd); - - - bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); - if (!bev) { - printf("%4d %8s %s\n", *connectionId, "ERROR", "constructing bufferevent"); - event_base_loopbreak(base); - return; - } - - - - - bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, (void*) connectionId); - bufferevent_enable(bev, EV_READ | EV_WRITE); - - printf("%4d %8s somebody has connected: socketId = %d → connectionId = %d\n", *connectionId, "CONN", listener, *connectionId); - print_socket_info(*connectionId, fd); - - bufferevent_write(bev, MESSAGE, strlen(MESSAGE)); -} - -static void conn_read_cb(struct bufferevent *bev, void *user_data) { - int connectionId = *((int*) user_data); - - /* This callback is invoked when there is data to read on bev. */ - struct evbuffer *input = bufferevent_get_input(bev); - struct evbuffer *output = bufferevent_get_output(bev); - struct event_base *base = bufferevent_get_base(bev); - - size_t len = evbuffer_get_length(input); - char *data = (char*) malloc(len); - evbuffer_copyout(input, data, len); - - - string dataFormated(data); - dataFormated = regex_replace(dataFormated, regex("\\n"), "\\n"); - printf("%4d %8s '%s'\n", connectionId, "IN", dataFormated.c_str()); - - if (COMMAND_EXIT.compare(data) == 0) { - struct timeval delay = {2, 123}; - printf("%4d %8s client asks us to terminate; finishing in %ld sesonds and %ld microseconds\n", connectionId, "EXIT", delay.tv_sec, delay.tv_usec); - event_base_loopexit(base, &delay); - } - - evbuffer_add(output, "echo: ", 6); - /* 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) { - int connectionId = *((int*) user_data); - - struct evbuffer *output = bufferevent_get_output(bev); - if (evbuffer_get_length(output) == 0) { - printf("%4d %8s\n", connectionId, "FLUSH"); - /* nebudeme ukončovat spojení - bufferevent_free(bev); - */ - } else { - // FIXME: sem to nikdy nepřijde - size_t len = evbuffer_get_length(output); - char *data = (char*) malloc(len); - evbuffer_copyout(output, data, len); - printf("%4d %8s '%s'\n", connectionId, "OUT", data); - free(data); - } -} - -static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) { - int connectionId = *((int*) user_data); - - if (events & BEV_EVENT_EOF) { - printf("%4d %8s\n", connectionId, "CLOSE"); - } else if (events & BEV_EVENT_ERROR) { - printf("%4d %8s %s\n", connectionId, "ERROR", strerror(errno)); - } else { - printf("%4d %8s\n", connectionId, "OTHER"); - // None of the other events can happen here, since we haven't enabled timeouts - } - - bufferevent_free(bev); - free(user_data); -} - -static void signal_cb(evutil_socket_t sig, short events, void *user_data) { - struct event_base *base = (event_base *) user_data; - struct timeval delay = {2, 123}; - - printf("\n%4s %8s got SIGINT (Ctrl+C); finishing in %ld sesonds and %ld microseconds\n", "*", "SIGNAL", delay.tv_sec, delay.tv_usec); - - event_base_loopexit(base, &delay); -} - -static void print_socket_info(int connectionId, int fd) { - struct ucred cr; - unsigned int cl = sizeof (cr); - - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0) { - printf("%4d %8s client identification: pid=%d, uid=%d, gid=%d\n", connectionId, "CONN", cr.pid, cr.uid, cr.gid); - } -} \ No newline at end of file diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/domain-socket-bridge.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/c++/domain-socket-bridge/domain-socket-bridge.cpp Sun Nov 20 20:40:30 2016 +0100 @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +static const char MESSAGE[] = "Hello, World!\n"; + +static const char PATH[] = "./roura"; + +static const string COMMAND_EXIT("exit\n"); + +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 void print_socket_info(int, int); + +int main(int argc, char **argv) { + printf("%4s %8s\n", "*", "STARTED"); + struct event_base *base; + 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) { + printf("%4s %8s %s\n", "*", "ERROR", "unable to initialize libevent"); + return 1; + } + + memset(&sun, 0, sizeof (sun)); + sun.sun_family = AF_UNIX; + strcpy(sun.sun_path, PATH); + + listener = socket(AF_UNIX, SOCK_STREAM, 0); + evutil_make_socket_nonblocking(listener); + + if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) { + printf("%4s %8s %s: %s\n", "*", "ERROR", "unable to create domain socket:", PATH); + return 1; + } + + if (listen(listener, 16) < 0) { + printf("%4s %8s %s\n", "*", "ERROR", "unable to listen"); + return 1; + } + + // identifikátor serverového soketu (v současnosti číslo FD) + printf("%4s %8s listening at: sun_path = %s → socketId = %d\n", "*", "SOCKET", sun.sun_path, listener); + + listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base); + + if (!listener_event) { + printf("%4s %8s %s\n", "*", "ERROR", "unable to do event_new()"); + 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) { + printf("%4s %8s %s\n", "*", "ERROR", "unable to create/add a signal event"); + return 1; + } + + event_base_dispatch(base); + + event_free(listener_event); + event_free(signal_event); + event_base_free(base); + + // smažeme soket na disku / soubor -- jinak by program příště spadl na bind() + // TODO: co když soket někdo přesune a místo něj dá jiný soubor? + unlink(PATH); + + printf("%4s %8s\n", "*", "FINISHED"); + return 0; +} + +static void listener_cb(evutil_socket_t listener, short event, void *user_data) { + struct event_base *base = (event_base *) user_data; + struct bufferevent *bev; + + struct sockaddr_storage ss; + socklen_t slen = sizeof (ss); + int fd = accept(listener, (struct sockaddr*) &ss, &slen); + + // identifikátor navázaného spojení (v současnosti číslo FD) + int * connectionId = (int*) malloc(sizeof (fd)); + *connectionId = fd; + + if (fd < 0) { + printf("%4d %8s %s\n", *connectionId, "ERROR", "unable to accept()"); + return; + } else if (fd > FD_SETSIZE) { + // FD_SETSIZE = 1024 -- Proč? Co když bude spojení víc? + printf("%4d %8s fd (%d) > FD_SETSIZE (%d)\n", *connectionId, "ERROR", fd, FD_SETSIZE); + close(fd); + return; + } + + evutil_make_socket_nonblocking(fd); + + + bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); + if (!bev) { + printf("%4d %8s %s\n", *connectionId, "ERROR", "constructing bufferevent"); + event_base_loopbreak(base); + return; + } + + + + + bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, (void*) connectionId); + bufferevent_enable(bev, EV_READ | EV_WRITE); + + printf("%4d %8s somebody has connected: socketId = %d → connectionId = %d\n", *connectionId, "CONN", listener, *connectionId); + print_socket_info(*connectionId, fd); + + bufferevent_write(bev, MESSAGE, strlen(MESSAGE)); +} + +static void conn_read_cb(struct bufferevent *bev, void *user_data) { + int connectionId = *((int*) user_data); + + /* This callback is invoked when there is data to read on bev. */ + struct evbuffer *input = bufferevent_get_input(bev); + struct evbuffer *output = bufferevent_get_output(bev); + struct event_base *base = bufferevent_get_base(bev); + + size_t len = evbuffer_get_length(input); + char *data = (char*) malloc(len); + evbuffer_copyout(input, data, len); + + + string dataFormated(data); + dataFormated = regex_replace(dataFormated, regex("\\n"), "\\n"); + printf("%4d %8s '%s'\n", connectionId, "IN", dataFormated.c_str()); + + if (COMMAND_EXIT.compare(data) == 0) { + struct timeval delay = {2, 123}; + printf("%4d %8s client asks us to terminate; finishing in %ld sesonds and %ld microseconds\n", connectionId, "EXIT", delay.tv_sec, delay.tv_usec); + event_base_loopexit(base, &delay); + } + + evbuffer_add(output, "echo: ", 6); + /* 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) { + int connectionId = *((int*) user_data); + + struct evbuffer *output = bufferevent_get_output(bev); + if (evbuffer_get_length(output) == 0) { + printf("%4d %8s\n", connectionId, "FLUSH"); + /* nebudeme ukončovat spojení + bufferevent_free(bev); + */ + } else { + // FIXME: sem to nikdy nepřijde + size_t len = evbuffer_get_length(output); + char *data = (char*) malloc(len); + evbuffer_copyout(output, data, len); + printf("%4d %8s '%s'\n", connectionId, "OUT", data); + free(data); + } +} + +static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) { + int connectionId = *((int*) user_data); + + if (events & BEV_EVENT_EOF) { + printf("%4d %8s\n", connectionId, "CLOSE"); + } else if (events & BEV_EVENT_ERROR) { + printf("%4d %8s %s\n", connectionId, "ERROR", strerror(errno)); + } else { + printf("%4d %8s\n", connectionId, "OTHER"); + // None of the other events can happen here, since we haven't enabled timeouts + } + + bufferevent_free(bev); + free(user_data); +} + +static void signal_cb(evutil_socket_t sig, short events, void *user_data) { + struct event_base *base = (event_base *) user_data; + struct timeval delay = {2, 123}; + + printf("\n%4s %8s got SIGINT (Ctrl+C); finishing in %ld sesonds and %ld microseconds\n", "*", "SIGNAL", delay.tv_sec, delay.tv_usec); + + event_base_loopexit(base, &delay); +} + +static void print_socket_info(int connectionId, int fd) { + struct ucred cr; + unsigned int cl = sizeof (cr); + + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0) { + printf("%4d %8s client identification: pid=%d, uid=%d, gid=%d\n", connectionId, "CONN", cr.pid, cr.uid, cr.gid); + } +} \ No newline at end of file diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/nbproject/Makefile-Debug.mk --- a/c++/domain-socket-bridge/nbproject/Makefile-Debug.mk Sun Nov 20 20:39:08 2016 +0100 +++ b/c++/domain-socket-bridge/nbproject/Makefile-Debug.mk Sun Nov 20 20:40:30 2016 +0100 @@ -62,10 +62,10 @@ ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} ${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/domain-socket-bridge ${OBJECTFILES} ${LDLIBSOPTIONS} -${OBJECTDIR}/domain-socket-bridge.o: domain-socket-bridge.c +${OBJECTDIR}/domain-socket-bridge.o: domain-socket-bridge.cpp ${MKDIR} -p ${OBJECTDIR} ${RM} "$@.d" - $(COMPILE.cc) -g `pkg-config --cflags libevent` -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/domain-socket-bridge.o domain-socket-bridge.c + $(COMPILE.cc) -g `pkg-config --cflags libevent` -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/domain-socket-bridge.o domain-socket-bridge.cpp # Subprojects .build-subprojects: diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/nbproject/Makefile-Release.mk --- a/c++/domain-socket-bridge/nbproject/Makefile-Release.mk Sun Nov 20 20:39:08 2016 +0100 +++ b/c++/domain-socket-bridge/nbproject/Makefile-Release.mk Sun Nov 20 20:40:30 2016 +0100 @@ -62,10 +62,10 @@ ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} ${LINK.cc} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/domain-socket-bridge ${OBJECTFILES} ${LDLIBSOPTIONS} -${OBJECTDIR}/domain-socket-bridge.o: domain-socket-bridge.c +${OBJECTDIR}/domain-socket-bridge.o: domain-socket-bridge.cpp ${MKDIR} -p ${OBJECTDIR} ${RM} "$@.d" - $(COMPILE.cc) -O2 `pkg-config --cflags libevent` -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/domain-socket-bridge.o domain-socket-bridge.c + $(COMPILE.cc) -O2 `pkg-config --cflags libevent` -std=c++11 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/domain-socket-bridge.o domain-socket-bridge.cpp # Subprojects .build-subprojects: diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/nbproject/configurations.xml --- a/c++/domain-socket-bridge/nbproject/configurations.xml Sun Nov 20 20:39:08 2016 +0100 +++ b/c++/domain-socket-bridge/nbproject/configurations.xml Sun Nov 20 20:40:30 2016 +0100 @@ -12,7 +12,7 @@ - domain-socket-bridge.c + domain-socket-bridge.cpp - + @@ -73,7 +73,7 @@ - + diff -r ba40af6cf815 -r 2383ed4da507 c++/domain-socket-bridge/nbproject/project.xml --- a/c++/domain-socket-bridge/nbproject/project.xml Sun Nov 20 20:39:08 2016 +0100 +++ b/c++/domain-socket-bridge/nbproject/project.xml Sun Nov 20 20:40:30 2016 +0100 @@ -4,8 +4,8 @@ domain-socket-bridge - c - + + cpp UTF-8