summaryrefslogtreecommitdiff
path: root/tests/network
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2009-04-04 14:48:52 +0200
committerAndreas Baumann <abaumann@yahoo.com>2009-04-04 14:48:52 +0200
commit8e106cd6ba045049bfe47186e39eb77c9f4a17c4 (patch)
tree0f10a568a38596d959de62c2e15d409d14d54e5e /tests/network
parent508c96cba2aac136deaa073eda989a13e8e948d0 (diff)
downloadwolfbones-8e106cd6ba045049bfe47186e39eb77c9f4a17c4.tar.gz
wolfbones-8e106cd6ba045049bfe47186e39eb77c9f4a17c4.tar.bz2
added an asynchonous connect, but how to test all the cases!?
Diffstat (limited to 'tests/network')
-rw-r--r--tests/network/test1.c98
1 files changed, 84 insertions, 14 deletions
diff --git a/tests/network/test1.c b/tests/network/test1.c
index 4a4bf3d..6986683 100644
--- a/tests/network/test1.c
+++ b/tests/network/test1.c
@@ -1,3 +1,9 @@
+/* Unix traditional and most portable way of a TCP/IP client using select().
+ *
+ * Also tests asynchrononous connect (for proper timeout handling in case of
+ * no connection).
+ */
+
#include "port/netdb.h" /* for getaddrinfo */
#include "port/stdlib.h" /* for EXIT_XXX */
#include "port/stdio.h" /* for fprintf */
@@ -12,7 +18,7 @@
#include <assert.h> /* for assertions */
#include <signal.h> /* for signal */
-#define DEBUG 0
+#define DEBUG 1
static bool wolf_network_sock_nonblocking( int fd ) {
int flags;
@@ -49,6 +55,7 @@ static char *fd_set_to_string( fd_set *fd, int min_fd, int max_fd, char *buf, si
#define MAX_IDLE_TIMEOUT 10
#define WRITE_BUFFER_SIZE 4096
#define READ_BUFFER_SIZE 4096
+#define CONNECT_TIMEOUT 2
#define max(a,b) ((a) < (b) ? (b) : (a))
@@ -82,6 +89,10 @@ int main( int argc, char *argv[] ) {
bool stdin_eof;
bool fd_write_closed;
bool fd_eof;
+ int max_fd;
+ fd_set read_set;
+ fd_set write_set;
+ struct timeval timeout;
if( argc != 3 ) {
fprintf( stderr, "usage: test1 <host> <port>\n" );
@@ -111,19 +122,87 @@ int main( int argc, char *argv[] ) {
goto FAIL;
}
+ /* open the client endpoint */
fd = socket( result->ai_family, result->ai_socktype, result->ai_protocol );
if( fd < 0 ) {
fprintf( stderr, "socket failed: %s (%d)\n", strerror( errno ), errno );
goto FAIL;
}
+ /* set socket non-blocking for asynchronous connect */
+ if( !wolf_network_sock_nonblocking( fd ) ) {
+ (void)close( fd );
+ fprintf( stderr, "set nonblocking failed for socket: %s (%d)\n", strerror( errno ), errno );
+ goto FAIL;
+ }
+
+ /* connect asynchronously */
res = connect( fd, result->ai_addr, result->ai_addrlen );
if( res < 0 ) {
- (void)close( fd );
- fprintf( stderr, "connect failed: %s (%d)\n", strerror( errno ), errno );
+ if( errno == EINPROGRESS ) {
+ /* this is ok, being connected, we loop later in a select */
+ } else {
+ (void)close( fd );
+ fprintf( stderr, "connect failed: %s (%d)\n", strerror( errno ), errno );
+ goto FAIL;
+ }
+ } else {
+ /* a fast connect */
+ goto CONNECTED;
+ }
+
+ /* wait till we are connected */
+CONNECT_SELECT_AGAIN:
+ FD_ZERO( &read_set );
+ FD_ZERO( &write_set );
+ FD_SET( fd, &read_set );
+ FD_SET( fd, &write_set );
+ timeout.tv_sec = CONNECT_TIMEOUT;
+ timeout.tv_usec = 0;
+ res = select( fd + 1, &read_set, &write_set, NULL, &timeout );
+ if( res < 0 ) {
+ if( errno == EINTR || errno == EAGAIN ) {
+ goto CONNECT_SELECT_AGAIN;
+ } else {
+ /* fatal errors */
+ fprintf( stderr, "select failed: %s (%d)\n",
+ strerror( errno ), errno );
+ (void)close( fd );
+ goto FAIL;
+ }
+ } else if( res == 0 ) {
+ /* connect timeout */
+ fprintf( stderr, "Connect timeout..terminating\n" );
goto FAIL;
+ } else {
+ if( FD_ISSET( fd, &read_set ) || FD_ISSET( fd, &write_set ) ) {
+ socklen_t sock_error_len;
+ int sock_error;
+
+ sock_error_len = sizeof( int );
+ res = getsockopt( fd, SOL_SOCKET, SO_ERROR, &sock_error, &sock_error_len );
+ if( res < 0 ) {
+ fprintf( stderr, "getsockopt for connection check failed: %s (%d)\n",
+ strerror( errno ), errno );
+ (void)close( fd );
+ goto FAIL;
+ } else {
+ if( sock_error != 0 ) {
+ fprintf( stderr, "SO_ERROR is not ok: %s (%d)\n",
+ strerror( errno ), errno );
+ (void)close( fd );
+ goto FAIL;
+ }
+ }
+ } else {
+ fprintf( stderr, "Socket not ready after select\n" );
+ (void)close( fd );
+ goto FAIL;
+ }
}
+ fprintf( stderr, "Connected to %s, port %s\n", host, service );
+CONNECTED:
if( !wolf_network_sock_nonblocking( STDIN_FILENO ) ) {
(void)close( fd );
fprintf( stderr, "set nonblocking failed for stdin: %s (%d)\n", strerror( errno ), errno );
@@ -134,11 +213,6 @@ int main( int argc, char *argv[] ) {
fprintf( stderr, "set nonblocking failed for stdout: %s (%d)\n", strerror( errno ), errno );
goto FAIL;
}
- if( !wolf_network_sock_nonblocking( fd ) ) {
- (void)close( fd );
- fprintf( stderr, "set nonblocking failed for socket: %s (%d)\n", strerror( errno ), errno );
- goto FAIL;
- }
idle_secs = 0;
count = 0;
@@ -159,10 +233,6 @@ int main( int argc, char *argv[] ) {
signal( SIGPIPE, SIG_IGN );
do {
- int max_fd;
- fd_set read_set;
- fd_set write_set;
- struct timeval timeout;
ssize_t rres;
#if DEBUG
char buf[10];
@@ -348,8 +418,8 @@ fprintf( stderr, "select %04d read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_e
count++;
if( count % 10000 == 0 ) {
- fprintf( stderr, "Transfered stdin: %d, stdout: %d, fd-in: %d, fd-out: %d\n",
- total_stdin_read, total_stdout_written, total_fd_read, total_fd_written );
+ fprintf( stderr, "Transfered nof_selects: %d, stdin: %d, stdout: %d, fd-in: %d, fd-out: %d\n",
+ count, total_stdin_read, total_stdout_written, total_fd_read, total_fd_written );
}
} while( !terminate && !( stdin_eof && fd_eof ) );