|
|
@ -16,7 +16,14 @@ |
|
|
|
# include <gnutls/gnutls.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
#define MARK_PROGRESS write(STDERR_FILENO, ".", 1) |
|
|
|
#undef MAX |
|
|
|
#define MAX(a,b) ((a) > (b) ? (a) : (b)) |
|
|
|
|
|
|
|
#undef MIN |
|
|
|
#define MIN(a,b) ((a) < (b) ? (a) : (b)) |
|
|
|
|
|
|
|
#define MARK_PROGRESS(c,cur,max) \ |
|
|
|
if (cur % (MAX(max,50)/50) == 0) write(STDERR_FILENO, c, 1) |
|
|
|
|
|
|
|
#define SOCKFILE "/tmp/oi.sock" |
|
|
|
#define PORT 5000 |
|
|
@ -128,7 +135,7 @@ pingpong_on_peer_read (evcom_stream *stream, const void *base, size_t len) |
|
|
|
buf[len] = 0; |
|
|
|
printf("server got message: %s\n", buf); |
|
|
|
|
|
|
|
evcom_stream_write_simple(stream, PONG, sizeof PONG); |
|
|
|
evcom_stream_write(stream, PONG, sizeof PONG); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
@ -170,7 +177,7 @@ static void |
|
|
|
pingpong_on_client_connect (evcom_stream *stream) |
|
|
|
{ |
|
|
|
printf("client connected. sending ping\n"); |
|
|
|
evcom_stream_write_simple(stream, PING, sizeof PING); |
|
|
|
evcom_stream_write(stream, PING, sizeof PING); |
|
|
|
assert(EVCOM_CONNECTED_RW == evcom_stream_state(stream)); |
|
|
|
} |
|
|
|
|
|
|
@ -196,9 +203,9 @@ pingpong_on_client_read (evcom_stream *stream, const void *base, size_t len) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (successful_ping_count % (EXCHANGES/20) == 0) MARK_PROGRESS; |
|
|
|
MARK_PROGRESS(".", successful_ping_count, EXCHANGES); |
|
|
|
|
|
|
|
evcom_stream_write_simple(stream, PING, sizeof PING); |
|
|
|
evcom_stream_write(stream, PING, sizeof PING); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
@ -211,8 +218,8 @@ pingpong (struct sockaddr *address) |
|
|
|
nconnections = 0; |
|
|
|
got_server_close = 0; |
|
|
|
|
|
|
|
printf("sizeof(evcom_server): %d\n", sizeof(evcom_server)); |
|
|
|
printf("sizeof(evcom_stream): %d\n", sizeof(evcom_stream)); |
|
|
|
printf("sizeof(evcom_server): %d\n", (int)sizeof(evcom_server)); |
|
|
|
printf("sizeof(evcom_stream): %d\n", (int)sizeof(evcom_stream)); |
|
|
|
|
|
|
|
evcom_server_init(&server); |
|
|
|
server.on_connection = pingpong_on_server_connection; |
|
|
@ -258,7 +265,7 @@ send_bye_and_close(evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
assert(base); |
|
|
|
assert(len == 0); |
|
|
|
evcom_stream_write_simple(stream, "BYE", 3); |
|
|
|
evcom_stream_write(stream, "BYE", 3); |
|
|
|
printf("server wrote bye\n"); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
@ -298,7 +305,7 @@ connint_on_client_close (evcom_stream *stream) |
|
|
|
|
|
|
|
printf("client connection closed\n"); |
|
|
|
|
|
|
|
if (nconnections % (NCONN/20) == 0) MARK_PROGRESS; |
|
|
|
MARK_PROGRESS(".", nconnections, NCONN); |
|
|
|
|
|
|
|
if(++nconnections == NCONN) { |
|
|
|
evcom_server_close(&server); |
|
|
@ -367,6 +374,365 @@ connint (struct sockaddr *address) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static evcom_reader reader; |
|
|
|
static evcom_writer writer; |
|
|
|
static int reader_got_close = 0; |
|
|
|
static int reader_got_eof = 0; |
|
|
|
static int reader_got_hello = 0; |
|
|
|
static int reader_cnt = 0; |
|
|
|
static int writer_got_close = 0; |
|
|
|
#define PIPE_MSG "hello world" |
|
|
|
#define PIPE_CNT 5000 |
|
|
|
|
|
|
|
static void |
|
|
|
reader_read (evcom_reader *r, const void *str, size_t len) |
|
|
|
{ |
|
|
|
assert(r == &reader); |
|
|
|
|
|
|
|
if (len == 0) { |
|
|
|
reader_got_eof = 1; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
assert(len == strlen(PIPE_MSG)); |
|
|
|
|
|
|
|
if (strncmp(str, PIPE_MSG, strlen(PIPE_MSG)) == 0) { |
|
|
|
reader_got_hello = 1; |
|
|
|
} |
|
|
|
|
|
|
|
if (++reader_cnt < PIPE_CNT) { |
|
|
|
MARK_PROGRESS(".", reader_cnt, PIPE_CNT); |
|
|
|
evcom_writer_write(&writer, PIPE_MSG, strlen(PIPE_MSG)); |
|
|
|
} else { |
|
|
|
evcom_writer_close(&writer); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
reader_close (evcom_reader *r) |
|
|
|
{ |
|
|
|
assert(r == &reader); |
|
|
|
reader_got_close = 1; |
|
|
|
evcom_reader_detach(r); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
writer_close (evcom_writer *w) |
|
|
|
{ |
|
|
|
assert(w == &writer); |
|
|
|
writer_got_close = 1; |
|
|
|
evcom_writer_detach(w); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
pipe_stream (void) |
|
|
|
{ |
|
|
|
reader_cnt = 0; |
|
|
|
reader_got_close = 0; |
|
|
|
reader_got_hello = 0; |
|
|
|
reader_got_eof = 0; |
|
|
|
writer_got_close = 0; |
|
|
|
|
|
|
|
int pipefd[2]; |
|
|
|
int r = pipe(pipefd); |
|
|
|
if (r < 0) { |
|
|
|
perror("pipe()"); |
|
|
|
return -1; |
|
|
|
} |
|
|
|
|
|
|
|
evcom_reader_init(&reader); |
|
|
|
reader.on_read = reader_read; |
|
|
|
reader.on_close = reader_close; |
|
|
|
evcom_reader_set(&reader, pipefd[0]); |
|
|
|
evcom_reader_attach(EV_DEFAULT_ &reader); |
|
|
|
|
|
|
|
evcom_writer_init(&writer); |
|
|
|
writer.on_close = writer_close; |
|
|
|
evcom_writer_set(&writer, pipefd[1]); |
|
|
|
evcom_writer_attach(EV_DEFAULT_ &writer); |
|
|
|
|
|
|
|
evcom_writer_write(&writer, PIPE_MSG, strlen(PIPE_MSG)); |
|
|
|
|
|
|
|
ev_loop(EV_DEFAULT_ 0); |
|
|
|
|
|
|
|
assert(reader_got_close); |
|
|
|
assert(reader_got_hello); |
|
|
|
assert(reader_got_eof); |
|
|
|
assert(writer_got_close); |
|
|
|
assert(reader_cnt == PIPE_CNT); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
#define PAIR_PINGPONG_TIMEOUT 5000.0 |
|
|
|
#define PAIR_PINGPONG_EXCHANGES 50 |
|
|
|
static int a_got_close; |
|
|
|
static int a_got_connect; |
|
|
|
static int b_got_close; |
|
|
|
static int b_got_connect; |
|
|
|
static int pair_pingpong_cnt; |
|
|
|
static evcom_stream a, b; |
|
|
|
|
|
|
|
void a_connect (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(stream == &a); |
|
|
|
a_got_connect = 1; |
|
|
|
} |
|
|
|
|
|
|
|
void a_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
evcom_stream_detach(stream); |
|
|
|
assert(stream == &a); |
|
|
|
a_got_close = 1; |
|
|
|
|
|
|
|
assert(stream->errorno == 0); |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (stream->gnutls_errorno) { |
|
|
|
fprintf(stderr, "\nGNUTLS ERROR: %s\n", gnutls_strerror(stream->gnutls_errorno)); |
|
|
|
} |
|
|
|
assert(stream->gnutls_errorno == 0); |
|
|
|
if (use_tls) gnutls_deinit(stream->session); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void a_read (evcom_stream *stream, const void *buf, size_t len) |
|
|
|
{ |
|
|
|
assert(stream == &a); |
|
|
|
if (len == 0) return; |
|
|
|
|
|
|
|
assert(len == strlen(PONG)); |
|
|
|
assert(strncmp(buf, PONG, strlen(PONG)) == 0); |
|
|
|
|
|
|
|
if (++pair_pingpong_cnt < PAIR_PINGPONG_EXCHANGES) { |
|
|
|
evcom_stream_write(&a, PING, strlen(PING)); |
|
|
|
} else if (pair_pingpong_cnt == PAIR_PINGPONG_EXCHANGES) { |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
|
|
|
|
|
MARK_PROGRESS(".", pair_pingpong_cnt, PAIR_PINGPONG_EXCHANGES); |
|
|
|
} |
|
|
|
|
|
|
|
void b_connect (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(stream == &b); |
|
|
|
b_got_connect = 1; |
|
|
|
} |
|
|
|
|
|
|
|
void b_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
evcom_stream_detach(stream); |
|
|
|
assert(stream == &b); |
|
|
|
b_got_close = 1; |
|
|
|
|
|
|
|
assert(stream->errorno == 0); |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (stream->gnutls_errorno) { |
|
|
|
fprintf(stderr, "\nGNUTLS ERROR: %s\n", gnutls_strerror(stream->gnutls_errorno)); |
|
|
|
} |
|
|
|
assert(stream->gnutls_errorno == 0); |
|
|
|
if (use_tls) gnutls_deinit(stream->session); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|
|
|
|
void b_read (evcom_stream *stream, const void *buf, size_t len) |
|
|
|
{ |
|
|
|
assert(stream == &b); |
|
|
|
if (len == 0) { |
|
|
|
evcom_stream_close(stream); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
assert(len == strlen(PING)); |
|
|
|
assert(strncmp(buf, PING, strlen(PING)) == 0); |
|
|
|
|
|
|
|
evcom_stream_write(&b, PONG, strlen(PONG)); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
pair_pingpong () |
|
|
|
{ |
|
|
|
a_got_close = 0; |
|
|
|
a_got_connect = 0; |
|
|
|
b_got_close = 0; |
|
|
|
b_got_connect = 0; |
|
|
|
pair_pingpong_cnt = 0; |
|
|
|
|
|
|
|
evcom_stream_init(&a, PAIR_PINGPONG_TIMEOUT); |
|
|
|
a.on_close = a_close; |
|
|
|
a.on_connect = a_connect; |
|
|
|
a.on_read = a_read; |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_client(&a); |
|
|
|
#endif |
|
|
|
|
|
|
|
evcom_stream_init(&b, PAIR_PINGPONG_TIMEOUT); |
|
|
|
b.on_close = b_close; |
|
|
|
b.on_connect = b_connect; |
|
|
|
b.on_read = b_read; |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_server(&b); |
|
|
|
#endif |
|
|
|
|
|
|
|
int r = evcom_stream_pair(&a, &b); |
|
|
|
assert(r == 0); |
|
|
|
|
|
|
|
evcom_stream_attach(EV_DEFAULT_ &a); |
|
|
|
evcom_stream_attach(EV_DEFAULT_ &b); |
|
|
|
|
|
|
|
evcom_stream_write(&a, PING, strlen(PING)); |
|
|
|
|
|
|
|
ev_loop(EV_DEFAULT_ 0); |
|
|
|
|
|
|
|
assert(a_got_close); |
|
|
|
assert(a_got_connect); |
|
|
|
assert(b_got_close); |
|
|
|
assert(b_got_connect); |
|
|
|
assert(pair_pingpong_cnt == PAIR_PINGPONG_EXCHANGES); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
free_stream (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(stream->errorno == 0); |
|
|
|
free(stream); |
|
|
|
} |
|
|
|
|
|
|
|
#define ZERO_TIMEOUT 50.0 |
|
|
|
static size_t zero_to_write = 0; |
|
|
|
static size_t zero_written = 0; |
|
|
|
static size_t zero_read = 0; |
|
|
|
static size_t zero_client_closed = 0; |
|
|
|
|
|
|
|
static void |
|
|
|
error_out (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(stream); |
|
|
|
fprintf(stderr, "peer connection timeout\n"); |
|
|
|
assert(0); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
echo (evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
if(len == 0) { |
|
|
|
fprintf(stderr, "close"); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} else { |
|
|
|
evcom_stream_write(stream, base, len); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static evcom_stream* |
|
|
|
make_echo_connection (evcom_server *server, struct sockaddr *addr) |
|
|
|
{ |
|
|
|
assert(server); |
|
|
|
assert(addr); |
|
|
|
|
|
|
|
evcom_stream *stream = malloc(sizeof(evcom_stream)); |
|
|
|
evcom_stream_init(stream, ZERO_TIMEOUT); |
|
|
|
stream->on_read = echo; |
|
|
|
stream->on_close = free_stream; |
|
|
|
stream->on_timeout = error_out; |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_server(stream); |
|
|
|
#endif |
|
|
|
|
|
|
|
return stream; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
zero_start (evcom_stream *stream) |
|
|
|
{ |
|
|
|
evcom_stream_write(stream, "0", 1); |
|
|
|
zero_written++; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
zero_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(stream); |
|
|
|
zero_client_closed = 1; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
zero_recv (evcom_stream *stream, const void *buf, size_t len) |
|
|
|
{ |
|
|
|
MARK_PROGRESS("-", zero_read, zero_to_write); |
|
|
|
zero_read += len; |
|
|
|
|
|
|
|
size_t i; |
|
|
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
assert(((char*)buf)[i] == '0'); |
|
|
|
} |
|
|
|
|
|
|
|
for (i = 0; i < MIN(zero_to_write - zero_written, 90000); i++) { |
|
|
|
evcom_stream_write(stream, "0", 1); |
|
|
|
zero_written++; |
|
|
|
|
|
|
|
MARK_PROGRESS(".", zero_written, zero_to_write); |
|
|
|
|
|
|
|
if (zero_written == zero_to_write) { |
|
|
|
|
|
|
|
fprintf(stderr, "CLOSE"); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (len == 0) { |
|
|
|
fprintf(stderr, "finish"); |
|
|
|
evcom_server_close(&server); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
zero_stream (struct sockaddr *address, size_t to_write) |
|
|
|
{ |
|
|
|
int r; |
|
|
|
|
|
|
|
assert(to_write >= 1024); // should be kind of big at least.
|
|
|
|
zero_to_write = to_write; |
|
|
|
got_server_close = 0; |
|
|
|
zero_written = 0; |
|
|
|
zero_read = 0; |
|
|
|
zero_client_closed = 0; |
|
|
|
|
|
|
|
evcom_server_init(&server); |
|
|
|
server.on_connection = make_echo_connection; |
|
|
|
server.on_close = common_on_server_close; |
|
|
|
|
|
|
|
evcom_server_listen(&server, address, 1000); |
|
|
|
evcom_server_attach(EV_DEFAULT_ &server); |
|
|
|
|
|
|
|
evcom_stream client; |
|
|
|
evcom_stream_init(&client, ZERO_TIMEOUT); |
|
|
|
client.on_read = zero_recv; |
|
|
|
client.on_connect = zero_start; |
|
|
|
client.on_close = zero_close; |
|
|
|
client.on_timeout = error_out; |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_client(&client); |
|
|
|
#endif |
|
|
|
r = evcom_stream_connect(&client, address); |
|
|
|
assert(r == 0 && "problem connecting"); |
|
|
|
evcom_stream_attach(EV_DEFAULT_ &client); |
|
|
|
|
|
|
|
ev_loop(EV_DEFAULT_ 0); |
|
|
|
|
|
|
|
assert(got_server_close); |
|
|
|
assert(zero_written == zero_to_write); |
|
|
|
assert(zero_read == zero_to_write); |
|
|
|
assert(zero_client_closed) ; |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct sockaddr * |
|
|
|
create_unix_address (void) |
|
|
|
{ |
|
|
@ -386,6 +752,11 @@ create_unix_address (void) |
|
|
|
void |
|
|
|
free_unix_address (struct sockaddr *address) |
|
|
|
{ |
|
|
|
struct stat tstat; |
|
|
|
if (lstat(SOCKFILE, &tstat) == 0) { |
|
|
|
assert(S_ISSOCK(tstat.st_mode)); |
|
|
|
unlink(SOCKFILE); |
|
|
|
} |
|
|
|
free(address); |
|
|
|
} |
|
|
|
|
|
|
@ -405,47 +776,86 @@ main (void) |
|
|
|
gnutls_anon_set_server_dh_params (server_credentials, dh_params); |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
struct sockaddr_in tcp_address; |
|
|
|
memset(&tcp_address, 0, sizeof(struct sockaddr_in)); |
|
|
|
tcp_address.sin_family = AF_INET; |
|
|
|
tcp_address.sin_port = htons(PORT); |
|
|
|
tcp_address.sin_addr.s_addr = INADDR_ANY; |
|
|
|
|
|
|
|
|
|
|
|
use_tls = 0; |
|
|
|
|
|
|
|
fprintf(stderr, "zero_stream tcp: "); |
|
|
|
assert(zero_stream((struct sockaddr*)&tcp_address, 5*1024*1024) == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "pipe_stream: "); |
|
|
|
assert(pipe_stream() == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "pair_pingpong: "); |
|
|
|
assert(pair_pingpong() == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "pingpong tcp: "); |
|
|
|
assert(pingpong((struct sockaddr*)&tcp_address) == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "connint tcp: "); |
|
|
|
assert(connint((struct sockaddr*)&tcp_address) == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
use_tls = 1; |
|
|
|
|
|
|
|
fprintf(stderr, "zero_stream ssl: "); |
|
|
|
assert(zero_stream((struct sockaddr*)&tcp_address, 50*1024) == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "pair_pingpong ssl: "); |
|
|
|
assert(pair_pingpong() == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "pingpong ssl: "); |
|
|
|
assert(pingpong((struct sockaddr*)&tcp_address) == 0); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "connint ssl: "); |
|
|
|
assert(connint((struct sockaddr*)&tcp_address) == 0); |
|
|
|
#endif |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
struct sockaddr *unix_address; |
|
|
|
|
|
|
|
|
|
|
|
use_tls = 0; |
|
|
|
|
|
|
|
fprintf(stderr, "pingpong unix: "); |
|
|
|
unix_address = create_unix_address(); |
|
|
|
assert(pingpong(unix_address) == 0); |
|
|
|
free_unix_address(unix_address); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "connint unix: "); |
|
|
|
unix_address = create_unix_address(); |
|
|
|
assert(connint(unix_address) == 0); |
|
|
|
free_unix_address(unix_address); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
use_tls = 1; |
|
|
|
|
|
|
|
fprintf(stderr, "pingpong unix ssl: "); |
|
|
|
unix_address = create_unix_address(); |
|
|
|
assert(pingpong(unix_address) == 0); |
|
|
|
free_unix_address(unix_address); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
|
|
|
|
fprintf(stderr, "connint unix ssl: "); |
|
|
|
unix_address = create_unix_address(); |
|
|
|
assert(connint(unix_address) == 0); |
|
|
|
free_unix_address(unix_address); |
|
|
|
fprintf(stderr, "\n"); |
|
|
|
#endif |
|
|
|
|
|
|
|
return 0; |
|
|
|