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