c++/domain-socket-bridge/domain-socket-bridge.c
author František Kučera <franta-hg@frantovo.cz>
Fri, 18 Nov 2016 23:07:02 +0100
changeset 29 9c0f52aa4772
parent 28 1fec66105b8e
child 30 efa6fc19b006
permissions -rw-r--r--
libevent: unixové sokety místo TCP
     1 #include <string.h>
     2 #include <errno.h>
     3 #include <stdio.h>
     4 #include <signal.h>
     5 
     6 #include <event2/bufferevent.h>
     7 #include <event2/buffer.h>
     8 #include <event2/listener.h>
     9 #include <event2/util.h>
    10 #include <event2/event.h>
    11 #include <sys/un.h>
    12 #include <unistd.h>
    13 
    14 static const char MESSAGE[] = "Hello, World!\n";
    15 
    16 static const char PATH[] = "./roura";
    17 
    18 static void listener_cb(struct evconnlistener *, evutil_socket_t,
    19 		struct sockaddr *, int socklen, void *);
    20 static void conn_write_cb(struct bufferevent *, void *);
    21 static void conn_event_cb(struct bufferevent *, short, void *);
    22 static void signal_cb(evutil_socket_t, short, void *);
    23 
    24 int main(int argc, char **argv) {
    25 	struct event_base *base;
    26 	struct evconnlistener *listener;
    27 	struct event *signal_event;
    28 
    29 	struct sockaddr_un sun;
    30 
    31 	base = event_base_new();
    32 	if (!base) {
    33 		fprintf(stderr, "Could not initialize libevent!\n");
    34 		return 1;
    35 	}
    36 
    37 	memset(&sun, 0, sizeof (sun));
    38 	sun.sun_family = AF_UNIX;
    39 	strcpy(sun.sun_path, PATH);
    40 
    41 	listener = evconnlistener_new_bind(base, listener_cb, (void *) base,
    42 			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
    43 			(struct sockaddr*) &sun,
    44 			sizeof (sun));
    45 
    46 	if (!listener) {
    47 		fprintf(stderr, "Could not create domain socket: %s!\n", PATH);
    48 		return 1;
    49 	}
    50 
    51 	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base);
    52 
    53 	if (!signal_event || event_add(signal_event, NULL) < 0) {
    54 		fprintf(stderr, "Could not create/add a signal event!\n");
    55 		return 1;
    56 	}
    57 
    58 	event_base_dispatch(base);
    59 
    60 	evconnlistener_free(listener);
    61 	event_free(signal_event);
    62 	event_base_free(base);
    63 	
    64 	// smažeme soket na disku / soubor -- jinak by program příště spadl na evconnlistener_new_bind()
    65 	unlink(PATH);
    66 
    67 	printf("done\n");
    68 	return 0;
    69 }
    70 
    71 static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) {
    72 	struct event_base *base = (event_base *) user_data;
    73 	struct bufferevent *bev;
    74 
    75 	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); // zavírá spojení
    76 	//bev = bufferevent_socket_new(base, fd, 0); // nezavírá spojení
    77 	if (!bev) {
    78 		fprintf(stderr, "Error constructing bufferevent!");
    79 		event_base_loopbreak(base);
    80 		return;
    81 	}
    82 	bufferevent_setcb(bev, NULL, conn_write_cb, conn_event_cb, NULL);
    83 	bufferevent_enable(bev, EV_WRITE);
    84 	bufferevent_disable(bev, EV_READ);
    85 
    86 	printf("někdo se k nám připojil! / %p\n", bev);
    87 
    88 	bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
    89 }
    90 
    91 static void conn_write_cb(struct bufferevent *bev, void *user_data) {
    92 	struct evbuffer *output = bufferevent_get_output(bev);
    93 	if (evbuffer_get_length(output) == 0) {
    94 		printf("flushed answer / %p\n", bev);
    95 		bufferevent_free(bev);
    96 	}
    97 }
    98 
    99 static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
   100 	if (events & BEV_EVENT_EOF) {
   101 		printf("Connection closed.\n");
   102 	} else if (events & BEV_EVENT_ERROR) {
   103 		printf("Got an error on the connection: %s\n",
   104 				strerror(errno));
   105 	}
   106 
   107 	// None of the other events can happen here, since we haven't enabled timeouts
   108 	bufferevent_free(bev);
   109 }
   110 
   111 static void signal_cb(evutil_socket_t sig, short events, void *user_data) {
   112 	struct event_base *base = (event_base *) user_data;
   113 	struct timeval delay = {2, 123};
   114 
   115 	printf("Zachycen SIGINT (Ctrl+C); ukončuji program během %ld sekund a %ld mikrosekund.\n", delay.tv_sec, delay.tv_usec);
   116 
   117 	event_base_loopexit(base, &delay);
   118 }