Created
June 24, 2013 15:37
-
-
Save pulsar-git/5850952 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* For sockaddr_in */ | |
#include <netinet/in.h> | |
/* For socket functions */ | |
#include <sys/socket.h> | |
/* For fcntl */ | |
#include <fcntl.h> | |
#include <event2/event.h> | |
#include <event2/buffer.h> | |
#include <event2/bufferevent.h> | |
#include <assert.h> | |
#include <unistd.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <errno.h> | |
#define TEST_IP (0x7f000001) | |
#define TEST_PORT (12345) | |
static struct timeval write_timeout={ | |
.tv_sec=2, | |
.tv_usec=0 | |
}; | |
static struct timeval read_timeout={ | |
.tv_sec=5, | |
.tv_usec=0 | |
}; | |
void | |
readcb(struct bufferevent *bev, void *ctx) | |
{ | |
struct evbuffer *input; | |
input = bufferevent_get_input(bev); | |
evbuffer_drain(input,evbuffer_get_length(input)); | |
} | |
void | |
errorcb(struct bufferevent *bev, short error, void *ctx) | |
{ | |
//printf("%s: %x\n",__PRETTY_FUNCTION__,error); | |
if(error & BEV_EVENT_TIMEOUT){ | |
if(error & BEV_EVENT_WRITING){ | |
printf("ERROR! should not get a write timeout"); | |
exit(EXIT_FAILURE); | |
} | |
if(error & BEV_EVENT_READING){ | |
printf("Only read timeout good!"); | |
exit(EXIT_SUCCESS); | |
} | |
} | |
} | |
struct bufferevent * | |
libevent_connect(struct event_base *base,uint32_t host,int port) | |
{ | |
struct sockaddr_in sin; | |
struct bufferevent *bev; | |
bev = bufferevent_socket_new(base, - 1, BEV_OPT_CLOSE_ON_FREE); | |
memset(&sin, 0, sizeof(sin)); | |
sin.sin_family = AF_INET; | |
sin.sin_addr.s_addr = htonl(host); | |
sin.sin_port = htons(port); | |
if (bufferevent_socket_connect(bev, | |
(struct sockaddr *)&sin, sizeof(sin)) < 0) { | |
/* Error starting connection */ | |
bufferevent_free(bev); | |
return NULL; | |
} | |
bufferevent_enable(bev, EV_READ|EV_WRITE); | |
return bev; | |
} | |
static enum bufferevent_filter_result | |
input_filter(struct evbuffer *src, struct evbuffer *dst, | |
ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) | |
{ | |
evbuffer_add_buffer(dst,src); | |
return BEV_OK; | |
} | |
static enum bufferevent_filter_result | |
output_filter(struct evbuffer *src, struct evbuffer *dst, | |
ev_ssize_t lim, enum bufferevent_flush_mode state, void *ctx) | |
{ | |
evbuffer_add_buffer(dst,src); | |
return BEV_OK; | |
} | |
void filter_check(struct bufferevent *bev) | |
{ | |
bev = bufferevent_filter_new(bev, input_filter, output_filter, | |
BEV_OPT_CLOSE_ON_FREE, NULL, NULL); | |
bufferevent_setcb(bev, readcb, NULL , errorcb, NULL); | |
bufferevent_set_timeouts(bev,&read_timeout,&write_timeout); | |
bufferevent_enable(bev, EV_READ | EV_WRITE); | |
} | |
static void | |
server_accept(evutil_socket_t listener, short event, void *arg) | |
{ | |
struct event_base *base = arg; | |
struct sockaddr_storage ss; | |
socklen_t slen = sizeof(ss); | |
int fd = accept(listener, (struct sockaddr*)&ss, &slen); | |
if (fd < 0) { | |
perror("accept"); | |
} else if (fd > FD_SETSIZE) { | |
close(fd); | |
} else { | |
struct bufferevent *bev; | |
evutil_make_socket_nonblocking(fd); | |
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); | |
bufferevent_setcb(bev, readcb, NULL, NULL, NULL); | |
//bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE); | |
bufferevent_enable(bev, EV_READ|EV_WRITE); | |
} | |
} | |
void spawn_server(struct event_base *base) | |
{ | |
evutil_socket_t listener; | |
struct sockaddr_in sin; | |
struct event *listener_event; | |
sin.sin_family = AF_INET; | |
sin.sin_addr.s_addr = 0; | |
sin.sin_port = htons(TEST_PORT); | |
listener = socket(AF_INET, SOCK_STREAM, 0); | |
evutil_make_socket_nonblocking(listener); | |
if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0) { | |
perror("bind"); | |
return; | |
} | |
if (listen(listener, 16)<0) { | |
perror("listen"); | |
return; | |
} | |
listener_event = event_new(base, listener, EV_READ|EV_PERSIST, server_accept, (void*)base); | |
/*XXX check it */ | |
event_add(listener_event, NULL); | |
} | |
void filter_test(struct event_base *base) | |
{ | |
struct bufferevent *bev,*bev2; | |
spawn_server(base); | |
bev2 = libevent_connect(base,TEST_IP,TEST_PORT); | |
filter_check(bev2); | |
bev = libevent_connect(base,TEST_IP,TEST_PORT); | |
bufferevent_setcb(bev, readcb, NULL , errorcb, NULL); | |
bufferevent_set_timeouts(bev,&read_timeout,&write_timeout); | |
bufferevent_enable(bev, EV_READ | EV_WRITE); | |
} | |
int | |
libevent_loop(void) | |
{ | |
struct event_base *base; | |
base = event_base_new(); | |
if (!base) | |
return 1; | |
filter_test(base); | |
while(1) | |
event_base_dispatch(base); | |
return 0; | |
} | |
int | |
main(int c, char **v) | |
{ | |
setvbuf(stdout, NULL, _IONBF, 0); | |
libevent_loop(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment