libevent: čtení ze soketu: funkční čtení a odpovídání na zprávy (rot13)
authorFrantišek Kučera <franta-hg@frantovo.cz>
Sat, 19 Nov 2016 19:29:54 +0100
changeset 31baa90e4359c8
parent 30 efa6fc19b006
child 32 0eaa8735a083
libevent: čtení ze soketu: funkční čtení a odpovídání na zprávy (rot13)
c++/domain-socket-bridge/domain-socket-bridge.c
     1.1 --- a/c++/domain-socket-bridge/domain-socket-bridge.c	Sat Nov 19 18:27:08 2016 +0100
     1.2 +++ b/c++/domain-socket-bridge/domain-socket-bridge.c	Sat Nov 19 19:29:54 2016 +0100
     1.3 @@ -18,19 +18,24 @@
     1.4  
     1.5  static const char PATH[] = "./roura";
     1.6  
     1.7 -static void listener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);
     1.8 +static void listener_cb(evutil_socket_t, short, void *);
     1.9  static void conn_read_cb(struct bufferevent *, void *);
    1.10  static void conn_write_cb(struct bufferevent *, void *);
    1.11  static void conn_event_cb(struct bufferevent *, short, void *);
    1.12  static void signal_cb(evutil_socket_t, short, void *);
    1.13  
    1.14 +static char rot13_char(char);
    1.15 +
    1.16  int main(int argc, char **argv) {
    1.17  	struct event_base *base;
    1.18 -	struct evconnlistener *listener;
    1.19 +	evutil_socket_t listener;
    1.20 +	struct event *listener_event;
    1.21  	struct event *signal_event;
    1.22  
    1.23  	struct sockaddr_un sun;
    1.24  
    1.25 +	setvbuf(stdout, NULL, _IONBF, 0);
    1.26 +
    1.27  	base = event_base_new();
    1.28  	if (!base) {
    1.29  		fprintf(stderr, "Could not initialize libevent!\n");
    1.30 @@ -41,16 +46,28 @@
    1.31  	sun.sun_family = AF_UNIX;
    1.32  	strcpy(sun.sun_path, PATH);
    1.33  
    1.34 -	listener = evconnlistener_new_bind(base, listener_cb, (void *) base,
    1.35 -			LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
    1.36 -			(struct sockaddr*) &sun,
    1.37 -			sizeof (sun));
    1.38 +	listener = socket(AF_UNIX, SOCK_STREAM, 0);
    1.39 +	evutil_make_socket_nonblocking(listener);
    1.40  
    1.41 -	if (!listener) {
    1.42 +	if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) {
    1.43  		fprintf(stderr, "Could not create domain socket: %s!\n", PATH);
    1.44  		return 1;
    1.45  	}
    1.46  
    1.47 +	if (listen(listener, 16) < 0) {
    1.48 +		fprintf(stderr, "Could not listen\n");
    1.49 +		return 1;
    1.50 +	}
    1.51 +
    1.52 +	listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base);
    1.53 +
    1.54 +	if (!listener_event) {
    1.55 +		fprintf(stderr, "Could not do event_new\n");
    1.56 +		return 1;
    1.57 +	}
    1.58 +
    1.59 +	event_add(listener_event, NULL);
    1.60 +
    1.61  	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base);
    1.62  
    1.63  	if (!signal_event || event_add(signal_event, NULL) < 0) {
    1.64 @@ -60,7 +77,7 @@
    1.65  
    1.66  	event_base_dispatch(base);
    1.67  
    1.68 -	evconnlistener_free(listener);
    1.69 +	event_free(listener_event);
    1.70  	event_free(signal_event);
    1.71  	event_base_free(base);
    1.72  
    1.73 @@ -71,12 +88,24 @@
    1.74  	return 0;
    1.75  }
    1.76  
    1.77 -static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) {
    1.78 +static void listener_cb(evutil_socket_t listener, short event, void *user_data) {
    1.79  	struct event_base *base = (event_base *) user_data;
    1.80  	struct bufferevent *bev;
    1.81  
    1.82 -	//bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); // zavírá spojení
    1.83 -	bev = bufferevent_socket_new(base, fd, 0); // nezavírá spojení
    1.84 +	struct sockaddr_storage ss;
    1.85 +	socklen_t slen = sizeof (ss);
    1.86 +	int fd = accept(listener, (struct sockaddr*) &ss, &slen);
    1.87 +	if (fd < 0) {
    1.88 +		fprintf(stderr, "Unable to accept(): %d", fd);
    1.89 +		return;
    1.90 +	} else if (fd > FD_SETSIZE) {
    1.91 +		close(fd);
    1.92 +		return;
    1.93 +	}
    1.94 +
    1.95 +	evutil_make_socket_nonblocking(fd);
    1.96 +
    1.97 +	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    1.98  	if (!bev) {
    1.99  		fprintf(stderr, "Error constructing bufferevent!");
   1.100  		event_base_loopbreak(base);
   1.101 @@ -99,26 +128,57 @@
   1.102  
   1.103  	size_t len = evbuffer_get_length(input);
   1.104  	char *data;
   1.105 +	/*
   1.106  	data = (char*) malloc(len);
   1.107  	evbuffer_copyout(input, data, len);
   1.108 +	 */
   1.109  
   1.110 -	printf("we got some data: %s / %d\n", data, memcmp(data, "exit", len));
   1.111 +	size_t n;
   1.112 +	int i;
   1.113 +	while ((data = evbuffer_readln(input, &n, EVBUFFER_EOL_LF))) {
   1.114 +		for (i = 0; i < n; ++i)
   1.115 +			data[i] = rot13_char(data[i]);
   1.116 +		evbuffer_add(output, data, n);
   1.117 +		evbuffer_add(output, "\n", 1);
   1.118 +		free(data);
   1.119 +	}
   1.120  
   1.121 +	printf("we got some data...\n");
   1.122 +
   1.123 +	/*
   1.124  	if (memcmp(data, "exit\n", len) == 0) {
   1.125  		struct timeval delay = {2, 123};
   1.126  		event_base_loopexit(base, &delay);
   1.127  	}
   1.128 +	 */
   1.129 +
   1.130 +	if (evbuffer_get_length(input) >= MAX_LINE) {
   1.131 +		/* Too long; just process what there is and go on so that the buffer
   1.132 +		 * doesn't grow infinitely long. */
   1.133 +		char buf[1024];
   1.134 +		while (evbuffer_get_length(input)) {
   1.135 +			int n = evbuffer_remove(input, buf, sizeof (buf));
   1.136 +			for (i = 0; i < n; ++i)
   1.137 +				buf[i] = rot13_char(buf[i]);
   1.138 +			evbuffer_add(output, buf, n);
   1.139 +		}
   1.140 +		evbuffer_add(output, "\n", 1);
   1.141 +	}
   1.142  
   1.143  	/* Copy all the data from the input buffer to the output buffer. */
   1.144 +	/*
   1.145  	evbuffer_add_buffer(output, input);
   1.146  	free(data);
   1.147 +	 */
   1.148  }
   1.149  
   1.150  static void conn_write_cb(struct bufferevent *bev, void *user_data) {
   1.151  	struct evbuffer *output = bufferevent_get_output(bev);
   1.152  	if (evbuffer_get_length(output) == 0) {
   1.153  		printf("flushed answer / %p\n", bev);
   1.154 +		/* nebudeme ukončovat spojení
   1.155  		bufferevent_free(bev);
   1.156 +		 */
   1.157  	}
   1.158  }
   1.159  
   1.160 @@ -141,3 +201,14 @@
   1.161  
   1.162  	event_base_loopexit(base, &delay);
   1.163  }
   1.164 +
   1.165 +static char rot13_char(char c) {
   1.166 +	/* We don't want to use isalpha here; setting the locale would change
   1.167 +	 * which characters are considered alphabetical. */
   1.168 +	if ((c >= 'a' && c <= 'm') || (c >= 'A' && c <= 'M'))
   1.169 +		return c + 13;
   1.170 +	else if ((c >= 'n' && c <= 'z') || (c >= 'N' && c <= 'Z'))
   1.171 +		return c - 13;
   1.172 +	else
   1.173 +		return c;
   1.174 +}