xref: /netbsd-src/external/bsd/libevent/dist/sample/hello-world.c (revision 657871a79c9a2060a6255a242fa1a1ef76b56ec6)
1*657871a7Schristos /*	$NetBSD: hello-world.c,v 1.1.1.3 2021/04/07 02:43:15 christos Exp $	*/
26ecf6635Schristos /*
3805a1ce9Schristos   This example program provides a trivial server program that listens for TCP
46ecf6635Schristos   connections on port 9995.  When they arrive, it writes a short message to
56ecf6635Schristos   each client connection, and closes each connection once it is flushed.
66ecf6635Schristos 
76ecf6635Schristos   Where possible, it exits cleanly in response to a SIGINT (ctrl-c).
86ecf6635Schristos */
96ecf6635Schristos 
106ecf6635Schristos 
116ecf6635Schristos #include <string.h>
126ecf6635Schristos #include <errno.h>
136ecf6635Schristos #include <stdio.h>
146ecf6635Schristos #include <signal.h>
15805a1ce9Schristos #ifndef _WIN32
166ecf6635Schristos #include <netinet/in.h>
176ecf6635Schristos # ifdef _XOPEN_SOURCE_EXTENDED
186ecf6635Schristos #  include <arpa/inet.h>
196ecf6635Schristos # endif
206ecf6635Schristos #include <sys/socket.h>
216ecf6635Schristos #endif
226ecf6635Schristos 
236ecf6635Schristos #include <event2/bufferevent.h>
246ecf6635Schristos #include <event2/buffer.h>
256ecf6635Schristos #include <event2/listener.h>
266ecf6635Schristos #include <event2/util.h>
276ecf6635Schristos #include <event2/event.h>
286ecf6635Schristos 
296ecf6635Schristos static const char MESSAGE[] = "Hello, World!\n";
306ecf6635Schristos 
316ecf6635Schristos static const int PORT = 9995;
326ecf6635Schristos 
336ecf6635Schristos static void listener_cb(struct evconnlistener *, evutil_socket_t,
346ecf6635Schristos     struct sockaddr *, int socklen, void *);
356ecf6635Schristos static void conn_writecb(struct bufferevent *, void *);
366ecf6635Schristos static void conn_eventcb(struct bufferevent *, short, void *);
376ecf6635Schristos static void signal_cb(evutil_socket_t, short, void *);
386ecf6635Schristos 
396ecf6635Schristos int
main(int argc,char ** argv)406ecf6635Schristos main(int argc, char **argv)
416ecf6635Schristos {
426ecf6635Schristos 	struct event_base *base;
436ecf6635Schristos 	struct evconnlistener *listener;
446ecf6635Schristos 	struct event *signal_event;
456ecf6635Schristos 
46*657871a7Schristos 	struct sockaddr_in sin = {0};
47805a1ce9Schristos #ifdef _WIN32
486ecf6635Schristos 	WSADATA wsa_data;
496ecf6635Schristos 	WSAStartup(0x0201, &wsa_data);
506ecf6635Schristos #endif
516ecf6635Schristos 
526ecf6635Schristos 	base = event_base_new();
536ecf6635Schristos 	if (!base) {
546ecf6635Schristos 		fprintf(stderr, "Could not initialize libevent!\n");
556ecf6635Schristos 		return 1;
566ecf6635Schristos 	}
576ecf6635Schristos 
586ecf6635Schristos 	sin.sin_family = AF_INET;
596ecf6635Schristos 	sin.sin_port = htons(PORT);
606ecf6635Schristos 
616ecf6635Schristos 	listener = evconnlistener_new_bind(base, listener_cb, (void *)base,
626ecf6635Schristos 	    LEV_OPT_REUSEABLE|LEV_OPT_CLOSE_ON_FREE, -1,
636ecf6635Schristos 	    (struct sockaddr*)&sin,
646ecf6635Schristos 	    sizeof(sin));
656ecf6635Schristos 
666ecf6635Schristos 	if (!listener) {
676ecf6635Schristos 		fprintf(stderr, "Could not create a listener!\n");
686ecf6635Schristos 		return 1;
696ecf6635Schristos 	}
706ecf6635Schristos 
716ecf6635Schristos 	signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base);
726ecf6635Schristos 
736ecf6635Schristos 	if (!signal_event || event_add(signal_event, NULL)<0) {
746ecf6635Schristos 		fprintf(stderr, "Could not create/add a signal event!\n");
756ecf6635Schristos 		return 1;
766ecf6635Schristos 	}
776ecf6635Schristos 
786ecf6635Schristos 	event_base_dispatch(base);
796ecf6635Schristos 
806ecf6635Schristos 	evconnlistener_free(listener);
816ecf6635Schristos 	event_free(signal_event);
826ecf6635Schristos 	event_base_free(base);
836ecf6635Schristos 
846ecf6635Schristos 	printf("done\n");
856ecf6635Schristos 	return 0;
866ecf6635Schristos }
876ecf6635Schristos 
886ecf6635Schristos static void
listener_cb(struct evconnlistener * listener,evutil_socket_t fd,struct sockaddr * sa,int socklen,void * user_data)896ecf6635Schristos listener_cb(struct evconnlistener *listener, evutil_socket_t fd,
906ecf6635Schristos     struct sockaddr *sa, int socklen, void *user_data)
916ecf6635Schristos {
926ecf6635Schristos 	struct event_base *base = user_data;
936ecf6635Schristos 	struct bufferevent *bev;
946ecf6635Schristos 
956ecf6635Schristos 	bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
966ecf6635Schristos 	if (!bev) {
976ecf6635Schristos 		fprintf(stderr, "Error constructing bufferevent!");
986ecf6635Schristos 		event_base_loopbreak(base);
996ecf6635Schristos 		return;
1006ecf6635Schristos 	}
1016ecf6635Schristos 	bufferevent_setcb(bev, NULL, conn_writecb, conn_eventcb, NULL);
1026ecf6635Schristos 	bufferevent_enable(bev, EV_WRITE);
1036ecf6635Schristos 	bufferevent_disable(bev, EV_READ);
1046ecf6635Schristos 
1056ecf6635Schristos 	bufferevent_write(bev, MESSAGE, strlen(MESSAGE));
1066ecf6635Schristos }
1076ecf6635Schristos 
1086ecf6635Schristos static void
conn_writecb(struct bufferevent * bev,void * user_data)1096ecf6635Schristos conn_writecb(struct bufferevent *bev, void *user_data)
1106ecf6635Schristos {
1116ecf6635Schristos 	struct evbuffer *output = bufferevent_get_output(bev);
1126ecf6635Schristos 	if (evbuffer_get_length(output) == 0) {
1136ecf6635Schristos 		printf("flushed answer\n");
1146ecf6635Schristos 		bufferevent_free(bev);
1156ecf6635Schristos 	}
1166ecf6635Schristos }
1176ecf6635Schristos 
1186ecf6635Schristos static void
conn_eventcb(struct bufferevent * bev,short events,void * user_data)1196ecf6635Schristos conn_eventcb(struct bufferevent *bev, short events, void *user_data)
1206ecf6635Schristos {
1216ecf6635Schristos 	if (events & BEV_EVENT_EOF) {
1226ecf6635Schristos 		printf("Connection closed.\n");
1236ecf6635Schristos 	} else if (events & BEV_EVENT_ERROR) {
1246ecf6635Schristos 		printf("Got an error on the connection: %s\n",
1256ecf6635Schristos 		    strerror(errno));/*XXX win32*/
1266ecf6635Schristos 	}
1276ecf6635Schristos 	/* None of the other events can happen here, since we haven't enabled
1286ecf6635Schristos 	 * timeouts */
1296ecf6635Schristos 	bufferevent_free(bev);
1306ecf6635Schristos }
1316ecf6635Schristos 
1326ecf6635Schristos static void
signal_cb(evutil_socket_t sig,short events,void * user_data)1336ecf6635Schristos signal_cb(evutil_socket_t sig, short events, void *user_data)
1346ecf6635Schristos {
1356ecf6635Schristos 	struct event_base *base = user_data;
1366ecf6635Schristos 	struct timeval delay = { 2, 0 };
1376ecf6635Schristos 
1386ecf6635Schristos 	printf("Caught an interrupt signal; exiting cleanly in two seconds.\n");
1396ecf6635Schristos 
1406ecf6635Schristos 	event_base_loopexit(base, &delay);
1416ecf6635Schristos }
142