static int http_connect(const char *address, u_short port) { /* Stupid code for connecting */ #ifdef WIN32 struct hostent *he; struct sockaddr_in sin; #else struct addrinfo ai, *aitop; char strport[NI_MAXSERV]; #endif struct sockaddr *sa; int slen; int fd; #ifdef WIN32 if (!(he = gethostbyname(address))) { event_warn("gethostbyname"); } memcpy(&sin.sin_addr, he->h_addr_list[0], he->h_length); sin.sin_family = AF_INET; sin.sin_port = htons(port); slen = sizeof(struct sockaddr_in); sa = (struct sockaddr*)&sin; #else memset(&ai, 0, sizeof (ai)); ai.ai_family = AF_INET; ai.ai_socktype = SOCK_STREAM; snprintf(strport, sizeof (strport), "%d", port); if (getaddrinfo(address, strport, &ai, &aitop) != 0) { event_warn("getaddrinfo"); return (-1); } sa = aitop->ai_addr; slen = aitop->ai_addrlen; #endif fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) event_err(1, "socket failed"); if (connect(fd, sa, slen) == -1) event_err(1, "connect failed"); #ifndef WIN32 freeaddrinfo(aitop); #endif return (fd); }
int evsignal_init(struct event_base *base) { int i; /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. */ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, base->sig.ev_signal_pair) == -1) { event_err(1, "%s: socketpair", __func__); return -1; } base->sig.sh_old = NULL; base->sig.sh_old_max = 0; base->sig.evsignal_caught = 0; memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); /* initialize the queues for all events */ for (i = 0; i < NSIG; ++i) TAILQ_INIT(&base->sig.evsigevents[i]); event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal); base->sig.ev_signal.ev_base = base; base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; return 0; }
/* Callback for when the signal handler write a byte to our signaling socket */ static void evsignal_cb(int fd, short what, void *arg) { static char signals[1]; ssize_t n; n = recv(fd, signals, sizeof(signals), 0); if (n == -1) { if (errno != EAGAIN) event_err(1, "%s: read", __func__); } }
/* Callback for when the signal handler write a byte to our signaling socket */ static void evsignal_cb(int fd, short what, void *arg) { static char signals[1]; #ifdef WIN32 SSIZE_T n; #else ssize_t n; #endif n = recv(fd, signals, sizeof(signals), 0); if (n == -1) event_err(1, "%s: read", __func__); }
/** * This function will be called by libevent when there is a connection * ready to be accepted. */ void on_accept(int fd, short ev, void *arg) { int client_fd; struct sockaddr_in client_addr; int client_len = sizeof(client_addr); struct client *client; static maxfd = 30000; client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd == -1) { event_warn("accept failed, errno %d", WSAGetLastError()); return; } if( client_fd > maxfd + 1000 ) { maxfd = client_fd; printf( "maxfd %d\n", maxfd ); } setsockopt( client_fd, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, (char *)&fd, sizeof(fd) ); /* Set the client socket to non-blocking mode. */ if (setnonblock(client_fd) < 0) event_warn("failed to set client socket non-blocking"); /* We¡¯ve accepted a new client, allocate a client object to * maintain the state of this client. */ client = (struct client*)calloc(1, sizeof(*client)); if (client == NULL) event_err(1, "malloc failed"); event_set(&client->ev_read, client_fd, EV_READ, on_read, client ); event_set(&client->ev_write, client_fd, EV_WRITE, on_write, client ); /* Setting up the event does not activate, add the event so it * becomes active. */ if( 0 != event_add(&client->ev_read, NULL) ) { close_client( client, client_fd ); } //printf("Accepted connection(%d) from %s\n", client_fd, inet_ntoa(client_addr.sin_addr)); }
int evsignal_init(struct event_base *base) { int i; /* * Our signal handler is going to write to one end of the socket * pair to wake up our event loop. The event loop then scans for * signals that got delivered. */ if (evutil_socketpair( AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) { #ifdef WIN32 /* Make this nonfatal on win32, where sometimes people have localhost firewalled. */ event_warn("%s: socketpair", __func__); #else event_err(1, "%s: socketpair", __func__); #endif return -1; } FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]); FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]); base->sig.sh_old = NULL; base->sig.sh_old_max = 0; base->sig.evsignal_caught = 0; memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG); /* initialize the queues for all events */ for (i = 0; i < NSIG; ++i) TAILQ_INIT(&base->sig.evsigevents[i]); evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]); event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1], EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal); base->sig.ev_signal.ev_base = base; base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL; return 0; }
static void err_fn(void) { errno = ENOENT; event_err(5,"Couldn't open %s", "/very/bad/file"); }
static void test_evutil_log(void *ptr) { evutil_socket_t fd = -1; char buf[128]; event_set_log_callback(logfn); event_set_fatal_callback(fatalfn); #define RESET() do { \ logsev = exited = exitcode = 0; \ if (logmsg) free(logmsg); \ logmsg = NULL; \ } while (0) #define LOGEQ(sev,msg) do { \ tt_int_op(logsev,==,sev); \ tt_assert(logmsg != NULL); \ tt_str_op(logmsg,==,msg); \ } while (0) event_errx(2, "Fatal error; too many kumquats (%d)", 5); LOGEQ(_EVENT_LOG_ERR, "Fatal error; too many kumquats (5)"); tt_int_op(exitcode,==,2); RESET(); event_warnx("Far too many %s (%d)", "wombats", 99); LOGEQ(_EVENT_LOG_WARN, "Far too many wombats (99)"); tt_int_op(exited,==,0); RESET(); event_msgx("Connecting lime to coconut"); LOGEQ(_EVENT_LOG_MSG, "Connecting lime to coconut"); tt_int_op(exited,==,0); RESET(); event_debug(("A millisecond passed! We should log that!")); #ifdef USE_DEBUG LOGEQ(_EVENT_LOG_DEBUG, "A millisecond passed! We should log that!"); #else tt_int_op(logsev,==,0); tt_ptr_op(logmsg,==,NULL); #endif RESET(); /* Try with an errno. */ errno = ENOENT; event_warn("Couldn't open %s", "/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_WARN,buf); tt_int_op(exited, ==, 0); RESET(); errno = ENOENT; event_err(5,"Couldn't open %s", "/very/bad/file"); evutil_snprintf(buf, sizeof(buf), "Couldn't open /very/bad/file: %s",strerror(ENOENT)); LOGEQ(_EVENT_LOG_ERR,buf); tt_int_op(exitcode, ==, 5); RESET(); /* Try with a socket errno. */ fd = socket(AF_INET, SOCK_STREAM, 0); #ifdef WIN32 evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", evutil_socket_error_to_string(WSAEWOULDBLOCK)); EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else evutil_snprintf(buf, sizeof(buf), "Unhappy socket: %s", strerror(EAGAIN)); errno = EAGAIN; #endif event_sock_warn(fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_WARN, buf); tt_int_op(exited,==,0); RESET(); #ifdef WIN32 EVUTIL_SET_SOCKET_ERROR(WSAEWOULDBLOCK); #else errno = EAGAIN; #endif event_sock_err(200, fd, "Unhappy socket"); LOGEQ(_EVENT_LOG_ERR, buf); tt_int_op(exitcode,==,200); RESET(); #undef RESET #undef LOGEQ end: if (logmsg) free(logmsg); if (fd >= 0) EVUTIL_CLOSESOCKET(fd); }
int main(int argc, char **argv) { int listen_fd, nZero = 0; struct sockaddr_in listen_addr; int reuseaddr_on = 1; /* The socket accept event. */ struct event ev_accept; struct event_base * evbase = NULL; WSADATA wsaData; int err = WSAStartup( MAKEWORD( 2, 0 ), &wsaData ); if ( err != 0 ) { printf( "Couldn't find a useable winsock.dll.\n" ); return -1; } /* Initialize libevent. */ evbase = event_init(); printf( "method : %s\n", event_base_get_method (evbase) ); /* Create our listening socket. This is largely boiler plate * code that I¡¯ll abstract away in the future. */ listen_fd = socket(AF_INET, SOCK_STREAM, 0); if (listen_fd < 0) event_err(1, "listen failed"); if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseaddr_on, sizeof(reuseaddr_on)) == -1) event_err(1, "setsockopt failed"); memset(&listen_addr, 0, sizeof(listen_addr)); listen_addr.sin_family = AF_INET; listen_addr.sin_addr.s_addr = INADDR_ANY; listen_addr.sin_port = htons(SERVER_PORT); if (bind(listen_fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) event_err(1, "bind failed"); if (listen(listen_fd, 1024) < 0) event_err(1, "listen failed"); /* Set the socket to non-blocking, this is essential in event * based programming with libevent. */ if (setnonblock(listen_fd) < 0) event_err(1, "failed to set server socket to non-blocking"); // Disable send buffering on the socket. Setting SO_SNDBUF // to 0 causes winsock to stop bufferring sends and perform // sends directly from our buffers, thereby reducing CPU usage. nZero = 0; if (SOCKET_ERROR == setsockopt(listen_fd, SOL_SOCKET, SO_SNDBUF, (char *)&nZero, sizeof(nZero))) { printf("setsockopt(SNDBUF): %d\n", WSAGetLastError()); return -1; } // Disable receive buffering on the socket. Setting SO_RCVBUF // to 0 causes winsock to stop bufferring receive and perform // receives directly from our buffers, thereby reducing CPU usage. nZero = 0; if (SOCKET_ERROR == setsockopt(listen_fd, SOL_SOCKET, SO_RCVBUF, (char *)&nZero, sizeof(nZero))) { printf("setsockopt(SO_RCVBUF): %d\n", WSAGetLastError()); return(FALSE); } /* We now have a listening socket, we create a read event to * be notified when a client connects. */ event_set(&ev_accept, listen_fd, EV_ACCEPT|EV_READ|EV_PERSIST, on_accept, NULL); event_add(&ev_accept, NULL); /* Start the libevent event loop. */ event_dispatch(); return 0; }