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