c++/domain-socket-bridge/domain-socket-bridge.c
changeset 40 ba40af6cf815
parent 39 988b56d4a7b8
     1.1 --- a/c++/domain-socket-bridge/domain-socket-bridge.c	Sun Nov 20 18:22:56 2016 +0100
     1.2 +++ b/c++/domain-socket-bridge/domain-socket-bridge.c	Sun Nov 20 20:39:08 2016 +0100
     1.3 @@ -3,6 +3,8 @@
     1.4  #include <stdio.h>
     1.5  #include <signal.h>
     1.6  #include <stdlib.h>
     1.7 +#include <string>
     1.8 +#include <regex>
     1.9  
    1.10  #include <event2/bufferevent.h>
    1.11  #include <event2/buffer.h>
    1.12 @@ -13,18 +15,23 @@
    1.13  #include <sys/un.h>
    1.14  #include <unistd.h>
    1.15  
    1.16 +using namespace std;
    1.17 +
    1.18  static const char MESSAGE[] = "Hello, World!\n";
    1.19  
    1.20  static const char PATH[] = "./roura";
    1.21  
    1.22 +static const string COMMAND_EXIT("exit\n");
    1.23 +
    1.24  static void listener_cb(evutil_socket_t, short, void *);
    1.25  static void conn_read_cb(struct bufferevent *, void *);
    1.26  static void conn_write_cb(struct bufferevent *, void *);
    1.27  static void conn_event_cb(struct bufferevent *, short, void *);
    1.28  static void signal_cb(evutil_socket_t, short, void *);
    1.29 -static void print_socket_info(int);
    1.30 +static void print_socket_info(int, int);
    1.31  
    1.32  int main(int argc, char **argv) {
    1.33 +	printf("%4s %8s\n", "*", "STARTED");
    1.34  	struct event_base *base;
    1.35  	evutil_socket_t listener;
    1.36  	struct event *listener_event;
    1.37 @@ -36,7 +43,7 @@
    1.38  
    1.39  	base = event_base_new();
    1.40  	if (!base) {
    1.41 -		fprintf(stderr, "Could not initialize libevent!\n");
    1.42 +		printf("%4s %8s %s\n", "*", "ERROR", "unable to initialize libevent");
    1.43  		return 1;
    1.44  	}
    1.45  
    1.46 @@ -48,22 +55,22 @@
    1.47  	evutil_make_socket_nonblocking(listener);
    1.48  
    1.49  	if (bind(listener, (struct sockaddr*) &sun, sizeof (sun)) < 0) {
    1.50 -		fprintf(stderr, "Could not create domain socket: %s!\n", PATH);
    1.51 +		printf("%4s %8s %s: %s\n", "*", "ERROR", "unable to create domain socket:", PATH);
    1.52  		return 1;
    1.53  	}
    1.54  
    1.55  	if (listen(listener, 16) < 0) {
    1.56 -		fprintf(stderr, "Could not listen\n");
    1.57 +		printf("%4s %8s %s\n", "*", "ERROR", "unable to listen");
    1.58  		return 1;
    1.59  	}
    1.60  
    1.61  	// identifikátor serverového soketu (v současnosti číslo FD)
    1.62 -	printf("Nasloucháme: sun_path = %s → socketId = %d\n", sun.sun_path, listener);
    1.63 +	printf("%4s %8s listening at: sun_path = %s → socketId = %d\n", "*", "SOCKET", sun.sun_path, listener);
    1.64  
    1.65  	listener_event = event_new(base, listener, EV_READ | EV_PERSIST, listener_cb, (void*) base);
    1.66  
    1.67  	if (!listener_event) {
    1.68 -		fprintf(stderr, "Could not do event_new\n");
    1.69 +		printf("%4s %8s %s\n", "*", "ERROR", "unable to do event_new()");
    1.70  		return 1;
    1.71  	}
    1.72  
    1.73 @@ -72,7 +79,7 @@
    1.74  	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *) base);
    1.75  
    1.76  	if (!signal_event || event_add(signal_event, NULL) < 0) {
    1.77 -		fprintf(stderr, "Could not create/add a signal event!\n");
    1.78 +		printf("%4s %8s %s\n", "*", "ERROR", "unable to create/add a signal event");
    1.79  		return 1;
    1.80  	}
    1.81  
    1.82 @@ -86,7 +93,7 @@
    1.83  	// TODO: co když soket někdo přesune a místo něj dá jiný soubor?
    1.84  	unlink(PATH);
    1.85  
    1.86 -	printf("done\n");
    1.87 +	printf("%4s %8s\n", "*", "FINISHED");
    1.88  	return 0;
    1.89  }
    1.90  
    1.91 @@ -97,42 +104,45 @@
    1.92  	struct sockaddr_storage ss;
    1.93  	socklen_t slen = sizeof (ss);
    1.94  	int fd = accept(listener, (struct sockaddr*) &ss, &slen);
    1.95 +
    1.96 +	// identifikátor navázaného spojení (v současnosti číslo FD)
    1.97 +	int * connectionId = (int*) malloc(sizeof (fd));
    1.98 +	*connectionId = fd;
    1.99 +
   1.100  	if (fd < 0) {
   1.101 -		fprintf(stderr, "Unable to accept(): %d", fd);
   1.102 +		printf("%4d %8s %s\n", *connectionId, "ERROR", "unable to accept()");
   1.103  		return;
   1.104  	} else if (fd > FD_SETSIZE) {
   1.105  		// FD_SETSIZE = 1024 -- Proč? Co když bude spojení víc?
   1.106 -		fprintf(stderr, "fd (%d) > FD_SETSIZE (%d)", fd, FD_SETSIZE);
   1.107 +		printf("%4d %8s fd (%d) > FD_SETSIZE (%d)\n", *connectionId, "ERROR", fd, FD_SETSIZE);
   1.108  		close(fd);
   1.109  		return;
   1.110  	}
   1.111  
   1.112  	evutil_make_socket_nonblocking(fd);
   1.113  
   1.114 -	print_socket_info(fd);
   1.115  
   1.116  	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
   1.117  	if (!bev) {
   1.118 -		fprintf(stderr, "Error constructing bufferevent!");
   1.119 +		printf("%4d %8s %s\n", *connectionId, "ERROR", "constructing bufferevent");
   1.120  		event_base_loopbreak(base);
   1.121  		return;
   1.122  	}
   1.123  
   1.124 -	// identifikátor navázaného spojení (v současnosti číslo FD)
   1.125 -	int * connectionId = (int*) malloc(sizeof (fd));
   1.126 -	*connectionId = fd;
   1.127 +
   1.128  
   1.129  
   1.130  	bufferevent_setcb(bev, conn_read_cb, conn_write_cb, conn_event_cb, (void*) connectionId);
   1.131  	bufferevent_enable(bev, EV_READ | EV_WRITE);
   1.132  
   1.133 -	printf("někdo se k nám připojil! socketId = %d → connectionId = %d / bev = %p\n", listener, *connectionId, bev);
   1.134 +	printf("%4d %8s somebody has connected: socketId = %d → connectionId = %d\n", *connectionId, "CONN", listener, *connectionId);
   1.135 +	print_socket_info(*connectionId, fd);
   1.136  
   1.137  	bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
   1.138  }
   1.139  
   1.140  static void conn_read_cb(struct bufferevent *bev, void *user_data) {
   1.141 -	printf("conn_read_cb: connectionId = %d\n", *((int*) user_data));
   1.142 +	int connectionId = *((int*) user_data);
   1.143  
   1.144  	/* This callback is invoked when there is data to read on bev. */
   1.145  	struct evbuffer *input = bufferevent_get_input(bev);
   1.146 @@ -142,11 +152,15 @@
   1.147  	size_t len = evbuffer_get_length(input);
   1.148  	char *data = (char*) malloc(len);
   1.149  	evbuffer_copyout(input, data, len);
   1.150 -	printf("we got some data: %s\n", data);
   1.151  
   1.152 -	if (memcmp(data, "exit\n", len) == 0) {
   1.153 +
   1.154 +	string dataFormated(data);
   1.155 +	dataFormated = regex_replace(dataFormated, regex("\\n"), "\\n");
   1.156 +	printf("%4d %8s '%s'\n", connectionId, "IN", dataFormated.c_str());
   1.157 +
   1.158 +	if (COMMAND_EXIT.compare(data) == 0) {
   1.159  		struct timeval delay = {2, 123};
   1.160 -		printf("Klient říká, že máme končit; ukončuji program během %ld sekund a %ld mikrosekund.\n", delay.tv_sec, delay.tv_usec);
   1.161 +		printf("%4d %8s client asks us to terminate; finishing in %ld sesonds and %ld microseconds\n", connectionId, "EXIT", delay.tv_sec, delay.tv_usec);
   1.162  		event_base_loopexit(base, &delay);
   1.163  	}
   1.164  
   1.165 @@ -157,28 +171,36 @@
   1.166  }
   1.167  
   1.168  static void conn_write_cb(struct bufferevent *bev, void *user_data) {
   1.169 -	printf("conn_write_cb: connectionId = %d\n", *((int*) user_data));
   1.170 +	int connectionId = *((int*) user_data);
   1.171  
   1.172  	struct evbuffer *output = bufferevent_get_output(bev);
   1.173  	if (evbuffer_get_length(output) == 0) {
   1.174 -		printf("flushed answer / %p\n", bev);
   1.175 +		printf("%4d %8s\n", connectionId, "FLUSH");
   1.176  		/* nebudeme ukončovat spojení
   1.177  		bufferevent_free(bev);
   1.178  		 */
   1.179 +	} else {
   1.180 +		// FIXME: sem to nikdy nepřijde
   1.181 +		size_t len = evbuffer_get_length(output);
   1.182 +		char *data = (char*) malloc(len);
   1.183 +		evbuffer_copyout(output, data, len);
   1.184 +		printf("%4d %8s '%s'\n", connectionId, "OUT", data);
   1.185 +		free(data);
   1.186  	}
   1.187  }
   1.188  
   1.189  static void conn_event_cb(struct bufferevent *bev, short events, void *user_data) {
   1.190  	int connectionId = *((int*) user_data);
   1.191 -	printf("conn_event_cb: connectionId = %d\n", connectionId);
   1.192  
   1.193  	if (events & BEV_EVENT_EOF) {
   1.194 -		printf("Connection closed: connectionId = %d\n", connectionId);
   1.195 +		printf("%4d %8s\n", connectionId, "CLOSE");
   1.196  	} else if (events & BEV_EVENT_ERROR) {
   1.197 -		printf("Got an error on the connectionId = %d: %s\n", connectionId, strerror(errno));
   1.198 +		printf("%4d %8s %s\n", connectionId, "ERROR", strerror(errno));
   1.199 +	} else {
   1.200 +		printf("%4d %8s\n", connectionId, "OTHER");
   1.201 +		// None of the other events can happen here, since we haven't enabled timeouts
   1.202  	}
   1.203  
   1.204 -	// None of the other events can happen here, since we haven't enabled timeouts
   1.205  	bufferevent_free(bev);
   1.206  	free(user_data);
   1.207  }
   1.208 @@ -187,16 +209,16 @@
   1.209  	struct event_base *base = (event_base *) user_data;
   1.210  	struct timeval delay = {2, 123};
   1.211  
   1.212 -	printf("Zachycen SIGINT (Ctrl+C); ukončuji program během %ld sekund a %ld mikrosekund.\n", delay.tv_sec, delay.tv_usec);
   1.213 +	printf("\n%4s %8s got SIGINT (Ctrl+C); finishing in %ld sesonds and %ld microseconds\n", "*", "SIGNAL", delay.tv_sec, delay.tv_usec);
   1.214  
   1.215  	event_base_loopexit(base, &delay);
   1.216  }
   1.217  
   1.218 -static void print_socket_info(int fd) {
   1.219 +static void print_socket_info(int connectionId, int fd) {
   1.220  	struct ucred cr;
   1.221  	unsigned int cl = sizeof (cr);
   1.222  
   1.223  	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl) == 0) {
   1.224 -		printf("připojený klient: pid=%d, uid=%d, gid=%d\n", cr.pid, cr.uid, cr.gid);
   1.225 +		printf("%4d %8s client identification: pid=%d, uid=%d, gid=%d\n", connectionId, "CONN", cr.pid, cr.uid, cr.gid);
   1.226  	}
   1.227  }
   1.228 \ No newline at end of file