|
|
@ -16,18 +16,10 @@ |
|
|
|
# include <gnutls/gnutls.h> |
|
|
|
#endif |
|
|
|
|
|
|
|
static const struct addrinfo tcp_hints = |
|
|
|
/* ai_flags */ { .ai_flags = 0 |
|
|
|
/* ai_family */ , .ai_family = AF_UNSPEC |
|
|
|
/* ai_socktype */ , .ai_socktype = SOCK_STREAM |
|
|
|
, 0 |
|
|
|
}; |
|
|
|
|
|
|
|
#define MARK_PROGRESS write(STDERR_FILENO, ".", 1) |
|
|
|
|
|
|
|
#define HOST "127.0.0.1" |
|
|
|
#define SOCKFILE "/tmp/oi.sock" |
|
|
|
#define PORT "5000" |
|
|
|
#define PORT 5000 |
|
|
|
|
|
|
|
static evcom_server server; |
|
|
|
static int nconnections; |
|
|
@ -43,28 +35,28 @@ common_on_server_close (evcom_server *server, int errorno) |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
common_on_peer_close (evcom_socket *socket) |
|
|
|
common_on_peer_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(socket->errorno == 0); |
|
|
|
assert(stream->errorno == 0); |
|
|
|
printf("server connection closed\n"); |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
assert(socket->gnutls_errorno == 0); |
|
|
|
if (use_tls) gnutls_deinit(socket->session); |
|
|
|
assert(stream->gnutls_errorno == 0); |
|
|
|
if (use_tls) gnutls_deinit(stream->session); |
|
|
|
#endif |
|
|
|
free(socket); |
|
|
|
free(stream); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
common_on_client_timeout (evcom_socket *socket) |
|
|
|
common_on_client_timeout (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(socket); |
|
|
|
assert(stream); |
|
|
|
printf("client connection timeout\n"); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
common_on_peer_timeout (evcom_socket *socket) |
|
|
|
common_on_peer_timeout (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(socket); |
|
|
|
assert(stream); |
|
|
|
fprintf(stderr, "peer connection timeout\n"); |
|
|
|
assert(0); |
|
|
|
} |
|
|
@ -75,10 +67,10 @@ static gnutls_anon_server_credentials_t server_credentials; |
|
|
|
const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; |
|
|
|
static gnutls_dh_params_t dh_params; |
|
|
|
|
|
|
|
void anon_tls_server (evcom_socket *socket) |
|
|
|
void anon_tls_server (evcom_stream *stream) |
|
|
|
{ |
|
|
|
gnutls_session_t session; |
|
|
|
socket->data = session; |
|
|
|
stream->data = session; |
|
|
|
|
|
|
|
int r = gnutls_init(&session, GNUTLS_SERVER); |
|
|
|
assert(r == 0); |
|
|
@ -87,10 +79,10 @@ void anon_tls_server (evcom_socket *socket) |
|
|
|
gnutls_credentials_set(session, GNUTLS_CRD_ANON, server_credentials); |
|
|
|
gnutls_dh_set_prime_bits(session, DH_BITS); |
|
|
|
|
|
|
|
evcom_socket_set_secure_session(socket, session); |
|
|
|
evcom_stream_set_secure_session(stream, session); |
|
|
|
} |
|
|
|
|
|
|
|
void anon_tls_client (evcom_socket *socket) |
|
|
|
void anon_tls_client (evcom_stream *stream) |
|
|
|
{ |
|
|
|
gnutls_session_t client_session; |
|
|
|
gnutls_anon_client_credentials_t client_credentials; |
|
|
@ -102,8 +94,8 @@ void anon_tls_client (evcom_socket *socket) |
|
|
|
/* Need to enable anonymous KX specifically. */ |
|
|
|
gnutls_credentials_set(client_session, GNUTLS_CRD_ANON, client_credentials); |
|
|
|
|
|
|
|
evcom_socket_set_secure_session(socket, client_session); |
|
|
|
assert(socket->flags & EVCOM_SECURE); |
|
|
|
evcom_stream_set_secure_session(stream, client_session); |
|
|
|
assert(stream->flags & EVCOM_SECURE); |
|
|
|
} |
|
|
|
|
|
|
|
#endif // EVCOM_HAVE_GNUTLS
|
|
|
@ -120,10 +112,10 @@ void anon_tls_client (evcom_socket *socket) |
|
|
|
static int successful_ping_count; |
|
|
|
|
|
|
|
static void |
|
|
|
pingpong_on_peer_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
pingpong_on_peer_read (evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
if (len == 0) { |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -132,52 +124,52 @@ pingpong_on_peer_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
buf[len] = 0; |
|
|
|
printf("server got message: %s\n", buf); |
|
|
|
|
|
|
|
evcom_socket_write_simple(socket, PONG, sizeof PONG); |
|
|
|
evcom_stream_write_simple(stream, PONG, sizeof PONG); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
pingpong_on_client_close (evcom_socket *socket) |
|
|
|
pingpong_on_client_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
assert(socket); |
|
|
|
assert(stream); |
|
|
|
printf("client connection closed\n"); |
|
|
|
evcom_server_close(&server); |
|
|
|
} |
|
|
|
|
|
|
|
static evcom_socket* |
|
|
|
static evcom_stream* |
|
|
|
pingpong_on_server_connection (evcom_server *_server, struct sockaddr *addr) |
|
|
|
{ |
|
|
|
assert(_server == &server); |
|
|
|
assert(addr); |
|
|
|
|
|
|
|
evcom_socket *socket = malloc(sizeof(evcom_socket)); |
|
|
|
evcom_socket_init(socket, PINGPONG_TIMEOUT); |
|
|
|
socket->on_read = pingpong_on_peer_read; |
|
|
|
socket->on_close = common_on_peer_close; |
|
|
|
socket->on_timeout = common_on_peer_timeout; |
|
|
|
evcom_stream *stream = malloc(sizeof(evcom_stream)); |
|
|
|
evcom_stream_init(stream, PINGPONG_TIMEOUT); |
|
|
|
stream->on_read = pingpong_on_peer_read; |
|
|
|
stream->on_close = common_on_peer_close; |
|
|
|
stream->on_timeout = common_on_peer_timeout; |
|
|
|
|
|
|
|
nconnections++; |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_server(socket); |
|
|
|
if (use_tls) anon_tls_server(stream); |
|
|
|
#endif |
|
|
|
|
|
|
|
printf("on server connection\n"); |
|
|
|
|
|
|
|
return socket; |
|
|
|
return stream; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
pingpong_on_client_connect (evcom_socket *socket) |
|
|
|
pingpong_on_client_connect (evcom_stream *stream) |
|
|
|
{ |
|
|
|
printf("client connected. sending ping\n"); |
|
|
|
evcom_socket_write_simple(socket, PING, sizeof PING); |
|
|
|
evcom_stream_write_simple(stream, PING, sizeof PING); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
pingpong_on_client_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
pingpong_on_client_read (evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
if(len == 0) { |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -191,37 +183,37 @@ pingpong_on_client_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
assert(strcmp(buf, PONG) == 0); |
|
|
|
|
|
|
|
if (++successful_ping_count > EXCHANGES) { |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
if (successful_ping_count % (EXCHANGES/20) == 0) MARK_PROGRESS; |
|
|
|
|
|
|
|
evcom_socket_write_simple(socket, PING, sizeof PING); |
|
|
|
evcom_stream_write_simple(stream, PING, sizeof PING); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
pingpong (struct addrinfo *servinfo) |
|
|
|
pingpong (struct sockaddr *address) |
|
|
|
{ |
|
|
|
int r; |
|
|
|
evcom_socket client; |
|
|
|
evcom_stream client; |
|
|
|
|
|
|
|
successful_ping_count = 0; |
|
|
|
nconnections = 0; |
|
|
|
got_server_close = 0; |
|
|
|
|
|
|
|
printf("sizeof(evcom_server): %d\n", sizeof(evcom_server)); |
|
|
|
printf("sizeof(evcom_socket): %d\n", sizeof(evcom_socket)); |
|
|
|
printf("sizeof(evcom_stream): %d\n", sizeof(evcom_stream)); |
|
|
|
|
|
|
|
evcom_server_init(&server); |
|
|
|
server.on_connection = pingpong_on_server_connection; |
|
|
|
server.on_close = common_on_server_close; |
|
|
|
|
|
|
|
r = evcom_server_listen(&server, servinfo, 10); |
|
|
|
r = evcom_server_listen(&server, address, 10); |
|
|
|
assert(r == 0); |
|
|
|
evcom_server_attach(EV_DEFAULT_ &server); |
|
|
|
|
|
|
|
evcom_socket_init(&client, PINGPONG_TIMEOUT); |
|
|
|
evcom_stream_init(&client, PINGPONG_TIMEOUT); |
|
|
|
client.on_read = pingpong_on_client_read; |
|
|
|
client.on_connect = pingpong_on_client_connect; |
|
|
|
client.on_close = pingpong_on_client_close; |
|
|
@ -231,9 +223,9 @@ pingpong (struct addrinfo *servinfo) |
|
|
|
if (use_tls) anon_tls_client(&client); |
|
|
|
#endif |
|
|
|
|
|
|
|
r = evcom_socket_connect(&client, servinfo); |
|
|
|
r = evcom_stream_connect(&client, address); |
|
|
|
assert(r == 0 && "problem connecting"); |
|
|
|
evcom_socket_attach(EV_DEFAULT_ &client); |
|
|
|
evcom_stream_attach(EV_DEFAULT_ &client); |
|
|
|
|
|
|
|
ev_loop(EV_DEFAULT_ 0); |
|
|
|
|
|
|
@ -252,53 +244,53 @@ pingpong (struct addrinfo *servinfo) |
|
|
|
#define CONNINT_TIMEOUT 1000.0 |
|
|
|
|
|
|
|
static void |
|
|
|
connint_on_peer_read(evcom_socket *socket, const void *base, size_t len) |
|
|
|
connint_on_peer_read(evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
assert(base); |
|
|
|
assert(len == 0); |
|
|
|
evcom_socket_write_simple(socket, "BYE", 3); |
|
|
|
evcom_stream_write_simple(stream, "BYE", 3); |
|
|
|
printf("server wrote bye\n"); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
connint_on_peer_drain(evcom_socket *socket) |
|
|
|
connint_on_peer_drain(evcom_stream *stream) |
|
|
|
{ |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
|
|
|
|
|
static evcom_socket* |
|
|
|
static evcom_stream* |
|
|
|
connint_on_server_connection(evcom_server *_server, struct sockaddr *addr) |
|
|
|
{ |
|
|
|
assert(_server == &server); |
|
|
|
assert(addr); |
|
|
|
|
|
|
|
evcom_socket *socket = malloc(sizeof(evcom_socket)); |
|
|
|
evcom_socket_init(socket, CONNINT_TIMEOUT); |
|
|
|
socket->on_read = connint_on_peer_read; |
|
|
|
socket->on_drain = connint_on_peer_drain; |
|
|
|
socket->on_close = common_on_peer_close; |
|
|
|
socket->on_timeout = common_on_peer_timeout; |
|
|
|
evcom_stream *stream = malloc(sizeof(evcom_stream)); |
|
|
|
evcom_stream_init(stream, CONNINT_TIMEOUT); |
|
|
|
stream->on_read = connint_on_peer_read; |
|
|
|
stream->on_drain = connint_on_peer_drain; |
|
|
|
stream->on_close = common_on_peer_close; |
|
|
|
stream->on_timeout = common_on_peer_timeout; |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_server(socket); |
|
|
|
if (use_tls) anon_tls_server(stream); |
|
|
|
#endif |
|
|
|
|
|
|
|
printf("on server connection\n"); |
|
|
|
|
|
|
|
return socket; |
|
|
|
return stream; |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
connint_on_client_connect (evcom_socket *socket) |
|
|
|
connint_on_client_connect (evcom_stream *stream) |
|
|
|
{ |
|
|
|
printf("on client connection\n"); |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
connint_on_client_close (evcom_socket *socket) |
|
|
|
connint_on_client_close (evcom_stream *stream) |
|
|
|
{ |
|
|
|
evcom_socket_close(socket); // already closed, but it shouldn't crash if we try to do it again
|
|
|
|
evcom_stream_close(stream); // already closed, but it shouldn't crash if we try to do it again
|
|
|
|
|
|
|
|
printf("client connection closed\n"); |
|
|
|
|
|
|
@ -311,10 +303,10 @@ connint_on_client_close (evcom_socket *socket) |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
connint_on_client_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
connint_on_client_read (evcom_stream *stream, const void *base, size_t len) |
|
|
|
{ |
|
|
|
if (len == 0) { |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
@ -325,11 +317,11 @@ connint_on_client_read (evcom_socket *socket, const void *base, size_t len) |
|
|
|
printf("client got message: %s\n", buf); |
|
|
|
|
|
|
|
assert(strcmp(buf, "BYE") == 0); |
|
|
|
evcom_socket_close(socket); |
|
|
|
evcom_stream_close(stream); |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
connint (struct addrinfo *servinfo) |
|
|
|
connint (struct sockaddr *address) |
|
|
|
{ |
|
|
|
int r; |
|
|
|
|
|
|
@ -341,14 +333,14 @@ connint (struct addrinfo *servinfo) |
|
|
|
server.on_close = common_on_server_close; |
|
|
|
|
|
|
|
|
|
|
|
evcom_server_listen(&server, servinfo, 1000); |
|
|
|
evcom_server_listen(&server, address, 1000); |
|
|
|
evcom_server_attach(EV_DEFAULT_ &server); |
|
|
|
|
|
|
|
evcom_socket clients[NCONN]; |
|
|
|
evcom_stream clients[NCONN]; |
|
|
|
int i; |
|
|
|
for (i = 0; i < NCONN; i++) { |
|
|
|
evcom_socket *client = &clients[i]; |
|
|
|
evcom_socket_init(client, CONNINT_TIMEOUT); |
|
|
|
evcom_stream *client = &clients[i]; |
|
|
|
evcom_stream_init(client, CONNINT_TIMEOUT); |
|
|
|
client->on_read = connint_on_client_read; |
|
|
|
client->on_connect = connint_on_client_connect; |
|
|
|
client->on_close = connint_on_client_close; |
|
|
@ -356,9 +348,9 @@ connint (struct addrinfo *servinfo) |
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
if (use_tls) anon_tls_client(client); |
|
|
|
#endif |
|
|
|
r = evcom_socket_connect(client, servinfo); |
|
|
|
r = evcom_stream_connect(client, address); |
|
|
|
assert(r == 0 && "problem connecting"); |
|
|
|
evcom_socket_attach(EV_DEFAULT_ client); |
|
|
|
evcom_stream_attach(EV_DEFAULT_ client); |
|
|
|
} |
|
|
|
|
|
|
|
ev_loop(EV_DEFAULT_ 0); |
|
|
@ -370,52 +362,26 @@ connint (struct addrinfo *servinfo) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct addrinfo * |
|
|
|
create_tcp_address (void) |
|
|
|
{ |
|
|
|
struct addrinfo *servinfo; |
|
|
|
int r = getaddrinfo(NULL, PORT, &tcp_hints, &servinfo); |
|
|
|
assert(r == 0); |
|
|
|
return servinfo; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
free_tcp_address (struct addrinfo *servinfo) |
|
|
|
{ |
|
|
|
freeaddrinfo(servinfo); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct addrinfo * |
|
|
|
struct sockaddr * |
|
|
|
create_unix_address (void) |
|
|
|
{ |
|
|
|
struct addrinfo *servinfo; |
|
|
|
struct stat tstat; |
|
|
|
if (lstat(SOCKFILE, &tstat) == 0) { |
|
|
|
assert(S_ISSOCK(tstat.st_mode)); |
|
|
|
unlink(SOCKFILE); |
|
|
|
} |
|
|
|
|
|
|
|
servinfo = malloc(sizeof(struct addrinfo)); |
|
|
|
servinfo->ai_family = AF_UNIX; |
|
|
|
servinfo->ai_socktype = SOCK_STREAM; |
|
|
|
servinfo->ai_protocol = 0; |
|
|
|
struct sockaddr_un *address = calloc(1, sizeof(struct sockaddr_un)); |
|
|
|
address->sun_family = AF_UNIX; |
|
|
|
strcpy(address->sun_path, SOCKFILE); |
|
|
|
|
|
|
|
struct sockaddr_un *sockaddr = calloc(sizeof(struct sockaddr_un), 1); |
|
|
|
sockaddr->sun_family = AF_UNIX; |
|
|
|
strcpy(sockaddr->sun_path, SOCKFILE); |
|
|
|
|
|
|
|
servinfo->ai_addr = (struct sockaddr*)sockaddr; |
|
|
|
servinfo->ai_addrlen = sizeof(struct sockaddr_un); |
|
|
|
|
|
|
|
return servinfo; |
|
|
|
return (struct sockaddr*)address; |
|
|
|
} |
|
|
|
|
|
|
|
void |
|
|
|
free_unix_address (struct addrinfo *servinfo) |
|
|
|
free_unix_address (struct sockaddr *address) |
|
|
|
{ |
|
|
|
free(servinfo->ai_addr); |
|
|
|
free(servinfo); |
|
|
|
free(address); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -434,21 +400,26 @@ main (void) |
|
|
|
gnutls_anon_set_server_dh_params (server_credentials, dh_params); |
|
|
|
#endif |
|
|
|
|
|
|
|
struct addrinfo *tcp_address = create_tcp_address(); |
|
|
|
struct addrinfo *unix_address; |
|
|
|
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; |
|
|
|
assert(pingpong(tcp_address) == 0); |
|
|
|
assert(connint(tcp_address) == 0); |
|
|
|
assert(pingpong((struct sockaddr*)&tcp_address) == 0); |
|
|
|
assert(connint((struct sockaddr*)&tcp_address) == 0); |
|
|
|
|
|
|
|
#if EVCOM_HAVE_GNUTLS |
|
|
|
use_tls = 1; |
|
|
|
assert(pingpong(tcp_address) == 0); |
|
|
|
assert(connint(tcp_address) == 0); |
|
|
|
assert(pingpong((struct sockaddr*)&tcp_address) == 0); |
|
|
|
assert(connint((struct sockaddr*)&tcp_address) == 0); |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
struct sockaddr *unix_address; |
|
|
|
|
|
|
|
|
|
|
|
use_tls = 0; |
|
|
|
|
|
|
@ -473,6 +444,5 @@ main (void) |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
free_tcp_address(tcp_address); |
|
|
|
return 0; |
|
|
|
} |
|
|
|