c++/domain-socket-bridge/domain-socket-bridge.c
author František Kučera <franta-hg@frantovo.cz>
Sat, 19 Nov 2016 18:27:08 +0100
changeset 30 efa6fc19b006
parent 29 9c0f52aa4772
child 31 baa90e4359c8
permissions -rw-r--r--
libevent: čtení ze soketu: první část
     1 #include <string.h>
     2 #include <errno.h>
     3 #include <stdio.h>
     4 #include <signal.h>
     5 #include <stdlib.h>
     6 
     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>
    12 #include <sys/un.h>
    13 #include <unistd.h>
    14 
    15 #define MAX_LINE 16384
    16 
    17 static const char MESSAGE[] = "Hello, World!\n";
    18 
    19 static const char PATH[] = "./roura";
    20 
    21 static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, 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 *);
    26 
    27 int main(int argc, char **argv) {
    28 	struct event_base *base;
    29 	struct evconnlistener *listener;
    30 	struct event *signal_event;
    31 
    32 	struct sockaddr_un sun;
    33 
    34 	base = event_base_new();
    35 	if (!base) {
    36 		fprintf(stderr, "Could not initialize libevent!\n");
    37 		return 1;
    38 	}
    39 
    40 	memset(&sun, 0, sizeof (sun));
    41 	sun.sun_family = AF_UNIX;
    42 	strcpy(sun.sun_path, PATH);
    43 
    44 	listener = evconnlistener_new_bind(base, listener_cb, (void *) base,
    45 			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
    46 			(struct sockaddr*) &sun,
    47 			sizeof (sun));
    48 
    49 	if (!listener) {
    50 		fprintf(stderr, "Could not create domain socket: %s!\n", PATH);
    51 		return 1;
    52 	}
    53 
    54 	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base);
    55 
    56 	if (!signal_event || event_add(signal_event, NULL) < 0) {
    57 		fprintf(stderr, "Could not create/add a signal event!\n");
    58 		return 1;
    59 	}
    60 
    61 	event_base_dispatch(base);
    62 
    63 	evconnlistener_free(listener);
    64 	event_free(signal_event);
    65 	event_base_free(base);
    66 
    67 	// smažeme soket na disku / soubor -- jinak by program příště spadl na evconnlistener_new_bind()
    68 	unlink(PATH);
    69 
    70 	printf("done\n");
    71 	return 0;
    72 }
    73 
    74 static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) {
    75 	struct event_base *base = (event_base *) user_data;
    76 	struct bufferevent *bev;
    77 
    78 	//bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); // zavírá spojení
    79 	bev = bufferevent_socket_new(base, fd, 0); // nezavírá spojení
    80 	if (!bev) {
    81 		fprintf(stderr, "Error constructing bufferevent!");
    82 		event_base_loopbreak(base);
    83 		return;
    84 	}
    85 	bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, NULL);
    86 	bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE);
    87 	bufferevent_enable(bev, EV_READ | EV_WRITE);
    88 
    89 	printf("někdo se k nám připojil! / %p\n", bev);
    90 
    91 	bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
    92 }
    93 
    94 static void conn_read_cb(struct bufferevent *bev, void *user_data) {
    95 	/* This callback is invoked when there is data to read on bev. */
    96 	struct evbuffer *input = bufferevent_get_input(bev);
    97 	struct evbuffer *output = bufferevent_get_output(bev);
    98 	struct event_base *base = (event_base *) user_data;
    99 
   100 	size_t len = evbuffer_get_length(input);
   101 	char *data;
   102 	data = (char*) malloc(len);
   103 	evbuffer_copyout(input, data, len);
   104 
   105 	printf("we got some data: %s / %d\n", data, memcmp(data, "exit", len));
   106 
   107 	if (memcmp(data, "exit\n", len) == 0) {
   108 		struct timeval delay = {2, 123};
   109 		event_base_loopexit(base, &delay);
   110 	}
   111 
   112 	/* Copy all the data from the input buffer to the output buffer. */
   113 	evbuffer_add_buffer(output, input);
   114 	free(data);
   115 }
   116 
   117 static void conn_write_cb(struct bufferevent *bev, void *user_data) {
   118 	struct evbuffer *output = bufferevent_get_output(bev);
   119 	if (evbuffer_get_length(output) == 0) {
   120 		printf("flushed answer / %p\n", bev);
   121 		bufferevent_free(bev);
   122 	}
   123 }
   124 
   125 static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
   126 	if (events & BEV_EVENT_EOF) {
   127 		printf("Connection closed.\n");
   128 	} else if (events & BEV_EVENT_ERROR) {
   129 		printf("Got an error on the connection: %s\n", strerror(errno));
   130 	}
   131 
   132 	// None of the other events can happen here, since we haven't enabled timeouts
   133 	bufferevent_free(bev);
   134 }
   135 
   136 static void signal_cb(evutil_socket_t sig, short events, void *user_data) {
   137 	struct event_base *base = (event_base *) user_data;
   138 	struct timeval delay = {2, 123};
   139 
   140 	printf("Zachycen SIGINT (Ctrl+C); ukončuji program během %ld sekund a %ld mikrosekund.\n", delay.tv_sec, delay.tv_usec);
   141 
   142 	event_base_loopexit(base, &delay);
   143 }