Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- *
- * Demonstrates problematic libevent behavior while trying to constrain size of output buffer
- *
- * Compile with:
- * gcc -Wall `pkg-config --cflags --libs libevent` -o server server.c
- *
- * Run with:
- * ./server
- *
- * In another terminal:
- * yes | nc localhost 6565
- *
- * Notice the output the server produces - and after a while the output callback is no longer called
- *
- * Mina Naguib, 2011
- */
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <event.h>
- #include <event2/bufferevent.h>
- #include <event2/listener.h>
- #define PORT 6565
- #define MAX_INPUT_BUFFER_SIZE 8192
- #define MAX_OUTPUT_BUFFER_SIZE 10240
- char *
- now() {
- time_t now = time(NULL);
- char *n = ctime(&now);
- char *temp;
- if ((temp = strchr(n, '\n'))) *temp = '\0';
- return n;
- }
- void
- handle_client_buffer_in(struct bufferevent *bev, void *hint) {
- struct evbuffer *input = bufferevent_get_input(bev);
- struct evbuffer *output = bufferevent_get_output(bev);
- size_t inlen = evbuffer_get_length(input), outlen = evbuffer_get_length(output);
- size_t len;
- char *line;
- char *response;
- printf("[%s] BEV IN CALLED. BEV LENGTHS: IN [%d] OUT [%d]\n", now(), (int)inlen, (int)outlen);
- if (outlen >= MAX_OUTPUT_BUFFER_SIZE) {
- // Libevent will make sure the input buffer doesn't keep growing, but it's up to us
- // to not write too much to the output buffer. We do that by refusing to drain the input buffer
- return;
- }
- while ((line = evbuffer_readln(input, &len, EVBUFFER_EOL_CRLF))) {
- free(line);
- response = "WELCOME TO MIAMI\n";
- len = strlen(response);
- evbuffer_add(output, response, len);
- }
- }
- void
- handle_client_buffer_out(struct bufferevent *bev, void *hint) {
- struct evbuffer *input = bufferevent_get_input(bev);
- struct evbuffer *output = bufferevent_get_output(bev);
- size_t inlen = evbuffer_get_length(input), outlen = evbuffer_get_length(output);
- printf("[%s] BEV OUT CALLED. BEV LENGTHS: IN [%d] OUT [%d]\n", now(), (int)inlen, (int)outlen);
- // We can now start reading again
- if (inlen > 0) handle_client_buffer_in(bev, hint);
- }
- void
- handle_client_buffer_evt(struct bufferevent *bev, short revents, void *hint) {
- if (revents & BEV_EVENT_ERROR) {
- printf("Client error: %s\n", strerror(errno));
- bufferevent_free(bev);
- }
- else if (revents & BEV_EVENT_TIMEOUT) {
- printf("Client timed out\n");
- bufferevent_free(bev);
- }
- else if (revents & BEV_EVENT_EOF) {
- printf("Client disconnected\n");
- bufferevent_free(bev);
- }
- else {
- printf("Spurious event from client: %d\n", revents);
- bufferevent_free(bev);
- }
- }
- void
- handle_new_client(struct evconnlistener *listener, evutil_socket_t client_fd, struct sockaddr *addr, int len, void *ptr) {
- struct bufferevent * bev;
- printf("Client connected\n");
- bev = bufferevent_socket_new(evconnlistener_get_base(listener), client_fd, BEV_OPT_CLOSE_ON_FREE);
- bufferevent_setcb(
- bev,
- handle_client_buffer_in,
- handle_client_buffer_out,
- handle_client_buffer_evt,
- NULL
- );
- bufferevent_setwatermark(bev, EV_READ, 0, MAX_INPUT_BUFFER_SIZE);
- bufferevent_enable(bev, EV_READ);
- }
- int main(int argc, char ** argv) {
- struct evconnlistener * server_listener;
- struct event_base *eb = NULL;
- struct sockaddr_in sa;
- eb = event_base_new();
- memset(&sa, 0, sizeof(sa));
- sa.sin_family = AF_INET;
- sa.sin_addr.s_addr = htonl(INADDR_ANY);
- sa.sin_port = htons(PORT);
- server_listener = evconnlistener_new_bind(
- eb,
- handle_new_client,
- NULL,
- LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
- -1,
- (struct sockaddr *)&sa,
- sizeof(sa)
- );
- if (server_listener != NULL) {
- printf("Server listening on port %d\n", PORT);
- event_base_dispatch(eb);
- return 0;
- }
- else {
- printf("Could not get server going...\n");
- return 1;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement