Home | History | Annotate | Line # | Download | only in sample
hello-world.c revision 1.1
      1 /*	$NetBSD: hello-world.c,v 1.1 2013/04/11 16:43:31 christos Exp $	*/
      2 /*
      3   This exmple program provides a trivial server program that listens for TCP
      4   connections on port 9995.  When they arrive, it writes a short message to
      5   each client connection, and closes each connection once it is flushed.
      6 
      7   Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
      8 */
      9 
     10 
     11 #include <string.h>
     12 #include <errno.h>
     13 #include <stdio.h>
     14 #include <signal.h>
     15 #ifndef WIN32
     16 #include <netinet/in.h>
     17 # ifdef _XOPEN_SOURCE_EXTENDED
     18 #  include <arpa/inet.h>
     19 # endif
     20 #include <sys/socket.h>
     21 #endif
     22 
     23 #include <event2/bufferevent.h>
     24 #include <event2/buffer.h>
     25 #include <event2/listener.h>
     26 #include <event2/util.h>
     27 #include <event2/event.h>
     28 
     29 static const char MESSAGE[] = "Hello, World!\n";
     30 
     31 static const int PORT = 9995;
     32 
     33 static void listener_cb(struct evconnlistener *, evutil_socket_t,
     34     struct sockaddr *, int socklen, void *);
     35 static void conn_writecb(struct bufferevent *, void *);
     36 static void conn_eventcb(struct bufferevent *, short, void *);
     37 static void signal_cb(evutil_socket_t, short, void *);
     38 
     39 int
     40 main(int argc, char **argv)
     41 {
     42 	struct event_base *base;
     43 	struct evconnlistener *listener;
     44 	struct event *signal_event;
     45 
     46 	struct sockaddr_in sin;
     47 #ifdef WIN32
     48 	WSADATA wsa_data;
     49 	WSAStartup(0x0201, &wsa_data);
     50 #endif
     51 
     52 	base = event_base_new();
     53 	if (!base) {
     54 		fprintf(stderr, "Could not initialize libevent!\n");
     55 		return 1;
     56 	}
     57 
     58 	memset(&sin, 0, sizeof(sin));
     59 	sin.sin_family = AF_INET;
     60 	sin.sin_port = htons(PORT);
     61 
     62 	listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
     63 	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
     64 	    (struct sockaddr*)&sin,
     65 	    sizeof(sin));
     66 
     67 	if (!listener) {
     68 		fprintf(stderr, "Could not create a listener!\n");
     69 		return 1;
     70 	}
     71 
     72 	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
     73 
     74 	if (!signal_event || event_add(signal_event, NULL)<0) {
     75 		fprintf(stderr, "Could not create/add a signal event!\n");
     76 		return 1;
     77 	}
     78 
     79 	event_base_dispatch(base);
     80 
     81 	evconnlistener_free(listener);
     82 	event_free(signal_event);
     83 	event_base_free(base);
     84 
     85 	printf("done\n");
     86 	return 0;
     87 }
     88 
     89 static void
     90 listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
     91     struct sockaddr *sa, int socklen, void *user_data)
     92 {
     93 	struct event_base *base = user_data;
     94 	struct bufferevent *bev;
     95 
     96 	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
     97 	if (!bev) {
     98 		fprintf(stderr, "Error constructing bufferevent!");
     99 		event_base_loopbreak(base);
    100 		return;
    101 	}
    102 	bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);
    103 	bufferevent_enable(bev, EV_WRITE);
    104 	bufferevent_disable(bev, EV_READ);
    105 
    106 	bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
    107 }
    108 
    109 static void
    110 conn_writecb(struct bufferevent *bev, void *user_data)
    111 {
    112 	struct evbuffer *output = bufferevent_get_output(bev);
    113 	if (evbuffer_get_length(output) == 0) {
    114 		printf("flushed answer\n");
    115 		bufferevent_free(bev);
    116 	}
    117 }
    118 
    119 static void
    120 conn_eventcb(struct bufferevent *bev, short events, void *user_data)
    121 {
    122 	if (events & BEV_EVENT_EOF) {
    123 		printf("Connection closed.\n");
    124 	} else if (events & BEV_EVENT_ERROR) {
    125 		printf("Got an error on the connection: %s\n",
    126 		    strerror(errno));/*XXX win32*/
    127 	}
    128 	/* None of the other events can happen here, since we haven't enabled
    129 	 * timeouts */
    130 	bufferevent_free(bev);
    131 }
    132 
    133 static void
    134 signal_cb(evutil_socket_t sig, short events, void *user_data)
    135 {
    136 	struct event_base *base = user_data;
    137 	struct timeval delay = { 2, 0 };
    138 
    139 	printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
    140 
    141 	event_base_loopexit(base, &delay);
    142 }
    143