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