1 /* $NetBSD: hello-world.c,v 1.1.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