diff options
author | Andreas Baumann <abaumann@yahoo.com> | 2009-04-04 14:48:52 +0200 |
---|---|---|
committer | Andreas Baumann <abaumann@yahoo.com> | 2009-04-04 14:48:52 +0200 |
commit | 8e106cd6ba045049bfe47186e39eb77c9f4a17c4 (patch) | |
tree | 0f10a568a38596d959de62c2e15d409d14d54e5e /tests/network | |
parent | 508c96cba2aac136deaa073eda989a13e8e948d0 (diff) | |
download | wolfbones-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.c | 98 |
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 ) ); |