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