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