From d67a84d6bc200b13b2b8d69c7319f0a1772822c5 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Mon, 6 Apr 2009 13:09:52 +0200 Subject: also did the echo server test2 in networking, a little bit simplistic --- tests/network/test2.c | 351 ++++++++++++++++---------------------------------- 1 file changed, 108 insertions(+), 243 deletions(-) (limited to 'tests') diff --git a/tests/network/test2.c b/tests/network/test2.c index 5192bb2..3964c93 100644 --- a/tests/network/test2.c +++ b/tests/network/test2.c @@ -20,7 +20,8 @@ #define DEBUG 0 -#define ACCEPT_TIMEOUT 5 +#define MAX_ACCEPT_IDLE_TIMEOUT 4 +#define MAX_IDLE_TIMEOUT 10 static bool wolf_network_sock_nonblocking( int fd ) { int flags; @@ -33,22 +34,61 @@ static bool wolf_network_sock_nonblocking( int fd ) { return true; } +#if DEBUG +static char *fd_set_to_string( fd_set *fd, int min_fd, int max_fd, char *buf, size_t buflen ) { + int i; + size_t j; + + assert( min_fd <= max_fd ); + + for( i = min_fd, j = 0; i <= max_fd && j < buflen; i++, j++ ) { + if( FD_ISSET( i, fd ) ) { + buf[j] = '1'; + } else { + buf[j] = '0'; + } + } + + buf[j] = '\0'; + + return buf; +} +#endif + +#define BUFFER_SIZE 4096 + +static volatile bool terminate = false; + +static void term_handler( int sig ) { + WOLF_UNUSED( sig ); + terminate = true; +} + int main( int argc, char* argv[] ) { int error; - int serv_fd; + int serv_fd = -1; int res; char *host; char *service; struct addrinfo hints; - struct addrinfo *result; + struct addrinfo *result = NULL; wolf_network_sockaddr_union_t client_addr; socklen_t client_addr_len; fd_set read_set; + fd_set write_set; struct timeval timeout; char client_hostname[NI_MAXHOST] = ""; char client_service[NI_MAXSERV] = ""; int on; - int client_fd; + int client_fd = -1; + int idle_secs; + char buffer[BUFFER_SIZE]; + size_t fd_to_write; + size_t fd_written; + size_t total_fd_read; + size_t total_fd_written; + int count; + bool fd_eof; if( argc != 3 ) { fprintf( stderr, "usage: test2 \n" ); @@ -63,6 +103,10 @@ int main( int argc, char* argv[] ) { WSAStartup( MAKEWORD( 2, 2 ), &wsa_data ); #endif + signal( SIGTERM, term_handler ); + signal( SIGINT, term_handler ); + signal( SIGPIPE, SIG_IGN ); + /* tell getaddrinfo what we want */ memset( &hints, 0, sizeof( struct addrinfo ) ); hints.ai_flags = AI_PASSIVE; @@ -100,7 +144,6 @@ int main( int argc, char* argv[] ) { /* bind server socket */ res = bind( serv_fd, result->ai_addr, result->ai_addrlen ); if( res < 0 ) { - (void)close( serv_fd ); fprintf( stderr, "bind failed: %s (%d)\n", strerror( errno ), errno ); goto FAIL; } @@ -108,14 +151,12 @@ int main( int argc, char* argv[] ) { /* listen to the socket */ res = listen( serv_fd, 10 ); if( res < 0 ) { - (void)close( serv_fd ); fprintf( stderr, "listen failed: %s (%d)\n", strerror( errno ), errno ); goto FAIL; } /* set socket non-blocking for accepts (Stevens 15.6) */ if( !wolf_network_sock_nonblocking( serv_fd ) ) { - (void)close( serv_fd ); fprintf( stderr, "set nonblocking failed for server socket: %s (%d)\n", strerror( errno ), errno ); goto FAIL; } @@ -127,10 +168,12 @@ FIRST_ACCEPT_AGAIN: client_addr_len = sizeof( client_addr ); client_fd = accept( serv_fd, &client_addr.addr, &client_addr_len ); if( client_fd < 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK ) { + if( errno == EINTR ) { + if( terminate ) goto OK; + goto FIRST_ACCEPT_AGAIN; + } else if( errno == EAGAIN || errno == EWOULDBLOCK ) { /* as expected, skip */ } else { - (void)close( serv_fd ); fprintf( stderr, "first non-blocking accept failed: %s (%d)\n", strerror( errno ), errno ); goto FAIL; } @@ -142,18 +185,20 @@ FIRST_ACCEPT_AGAIN: ACCEPT_SELECT_AGAIN: FD_ZERO( &read_set ); FD_SET( serv_fd, &read_set ); - timeout.tv_sec = ACCEPT_TIMEOUT; + timeout.tv_sec = MAX_ACCEPT_IDLE_TIMEOUT; timeout.tv_usec = 0; res = select( serv_fd + 1, &read_set, NULL, NULL, &timeout ); if( res < 0 ) { - if( errno == EINTR || errno == EAGAIN ) { + if( errno == EINTR ) { + if( terminate ) goto OK; + goto ACCEPT_SELECT_AGAIN; + } else if( errno == EAGAIN ) { goto ACCEPT_SELECT_AGAIN; } else { /* fatal errors */ fprintf( stderr, "accept/select failed: %s (%d)\n", strerror( errno ), errno ); - (void)close( serv_fd ); goto FAIL; } } else if( res == 0 ) { @@ -179,13 +224,13 @@ ACCEPT_AGAIN: client_fd = accept( serv_fd, &client_addr.addr, &client_addr_len ); if( client_fd < 0 ) { if( errno == EINTR ) { + if( terminate ) goto OK; /* interrupted, again */ goto ACCEPT_AGAIN; } else if( errno == ECONNABORTED ) { /* connection run away */ goto FIRST_ACCEPT_AGAIN; } else { - (void)close( serv_fd ); fprintf( stderr, "second non-blocking accept failed: %s (%d)\n", strerror( errno ), errno ); goto FAIL; } @@ -197,7 +242,6 @@ ACCEPT_AGAIN: client_service, NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST ); if( res < 0 ) { - (void)close( serv_fd ); fprintf( stderr, "getnameinfo failed: %s (%d)\n", gai_strerror( error ), error ); goto FAIL; @@ -205,176 +249,48 @@ ACCEPT_AGAIN: fprintf( stderr, "New connection from %s, port %s\n", client_hostname, client_service ); - (void)close( client_fd ); - - goto FIRST_ACCEPT_AGAIN; - -FAIL: - freeaddrinfo( result ); - -#ifdef _WIN32 - WSACleanup( ); -#endif - - return EXIT_FAILURE; - -//OK: - freeaddrinfo( result ); - -#ifdef _WIN32 - WSACleanup( ); -#endif - - return EXIT_SUCCESS; -} - -#if 0 - -#if DEBUG -static char *fd_set_to_string( fd_set *fd, int min_fd, int max_fd, char *buf, size_t buflen ) { - int i; - size_t j; - - assert( min_fd <= max_fd ); - - for( i = min_fd, j = 0; i <= max_fd && j < buflen; i++, j++ ) { - if( FD_ISSET( i, fd ) ) { - buf[j] = '1'; - } else { - buf[j] = '0'; - } - } - - buf[j] = '\0'; - - return buf; -} -#endif - -#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)) - -static volatile bool terminate = false; - -static void term_handler( int sig ) { - WOLF_UNUSED( sig ); - terminate = true; -} - - -int main( int argc, char *argv[] ) { - int res; - int idle_secs; - char read_buffer[READ_BUFFER_SIZE]; - char write_buffer[WRITE_BUFFER_SIZE]; - size_t stdout_to_write; - size_t stdout_written; - size_t fd_to_write; - size_t fd_written; - size_t total_stdin_read; - size_t total_fd_read; - size_t total_fd_written; - size_t total_stdout_written; - int count; - bool stdin_eof; - bool fd_write_closed; - bool fd_eof; - -CONNECT_SELECT_AGAIN: - 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( error == 0 ) { - goto CONNECTED; - } else { - fprintf( stderr, "SO_ERROR is not ok: %s (%d)\n", - strerror( error ), error ); - (void)close( fd ); - goto FAIL; - } - } - } else { - fprintf( stderr, "Socket not ready after select\n" ); - (void)close( fd ); - goto FAIL; - } - } - -CONNECTED: + /* handle connection input/output as echo server */ idle_secs = 0; count = 0; - stdout_to_write = 0; - stdout_written = 0; fd_to_write = 0; fd_written = 0; - total_stdin_read = 0; total_fd_read = 0; total_fd_written = 0; - total_stdout_written = 0; - stdin_eof = false; - fd_write_closed = false; fd_eof = false; - signal( SIGTERM, term_handler ); - signal( SIGINT, term_handler ); - signal( SIGPIPE, SIG_IGN ); - do { ssize_t rres; #if DEBUG char buf[10]; char buf2[10]; #endif - FD_ZERO( &read_set ); FD_ZERO( &write_set ); timeout.tv_sec = 1; timeout.tv_usec = 0; - - /* set up select mask and compute highest file descriptor number */ - max_fd = 0; - max_fd = max( max_fd, STDIN_FILENO ); - max_fd = max( max_fd, STDOUT_FILENO ); - max_fd = max( max_fd, fd ); - - if( !stdin_eof && fd_to_write == 0 ) { - FD_SET( STDIN_FILENO, &read_set ); - } - if( stdout_to_write > 0 ) { - FD_SET( STDOUT_FILENO, &write_set ); - } - if( stdout_to_write == 0 ) { - FD_SET( fd, &read_set ); + if( fd_to_write == 0 ) { + FD_SET( client_fd, &read_set ); } if( fd_to_write > 0 ) { - FD_SET( fd, &write_set ); + FD_SET( client_fd, &write_set ); } /* wait for events or timeout */ #if DEBUG -fprintf( stderr, "select call read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_eof: %d fdwcl: %d\n", - fd_set_to_string( &read_set, 0, max_fd, buf, 10 ), - fd_set_to_string( &write_set, 0, max_fd, buf2, 10 ), - fd_to_write, stdout_to_write, stdin_eof, fd_write_closed ); +fprintf( stderr, "select call read_fd: %s write_fd: %s buf: %d eof: %d\n", + fd_set_to_string( &read_set, client_fd, client_fd, buf, 10 ), + fd_set_to_string( &write_set, client_fd, client_fd, buf2, 10 ), + fd_to_write, fd_eof ); #endif - res = select( max_fd + 1, &read_set, &write_set, NULL, &timeout ); + res = select( client_fd + 1, &read_set, &write_set, NULL, &timeout ); #if DEBUG -fprintf( stderr, "select %04d read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_eof: %d fdwcl: %d\n", - res, fd_set_to_string( &read_set, 0, max_fd, buf, 10 ), - fd_set_to_string( &write_set, 0, max_fd, buf2, 10 ), - fd_to_write, stdout_to_write, stdin_eof, fd_write_closed ); +fprintf( stderr, "select %04d read_fd: %s write_fd: %s buf: %d eof: %d\n", + res, fd_set_to_string( &read_set, client_fd, client_fd, buf, 10 ), + fd_set_to_string( &write_set, client_fd, client_fd, buf2, 10 ), + fd_to_write, fd_eof ); #endif if( res < 0 ) { @@ -384,7 +300,6 @@ fprintf( stderr, "select %04d read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_e /* fatal errors */ fprintf( stderr, "select failed: %s (%d)\n", strerror( errno ), errno ); - (void)close( fd ); goto FAIL; } } else if( res == 0 ) { @@ -399,39 +314,16 @@ fprintf( stderr, "select %04d read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_e /* something happened */ idle_secs = 0; - /* empty the socket read buffer to stdout */ - if( FD_ISSET( STDOUT_FILENO, &write_set ) ) { - assert( stdout_to_write > 0 ); - rres = write( STDOUT_FILENO, read_buffer + stdout_written, stdout_to_write ); - if( rres < 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) { - /* skip */ - } else { - fprintf( stderr, "write to stdout failed: %s (%d)\n", - strerror( errno ), errno ); - (void)close( fd ); - goto FAIL; - } - } else { - assert( rres >= 0 ); - stdout_written += (size_t)rres; - assert( stdout_to_write >= (size_t)rres ); - stdout_to_write -= (size_t)rres; - total_stdout_written += (size_t)rres; - } - } - - /* empty the socket write buffer writing to fd */ - if( FD_ISSET( fd, &write_set ) ) { + /* if we have something to write back to the client, do that */ + if( FD_ISSET( client_fd, &write_set ) ) { assert( fd_to_write > 0 ); - rres = write( fd, write_buffer + fd_written, fd_to_write ); + rres = write( client_fd, buffer + fd_written, fd_to_write ); if( rres < 0 ) { if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) { /* skip */ } else { - fprintf( stderr, "write to socket failed: %s (%d)\n", + fprintf( stderr, "write to stdout failed: %s (%d)\n", strerror( errno ), errno ); - (void)close( fd ); goto FAIL; } } else { @@ -439,101 +331,74 @@ fprintf( stderr, "select %04d read_fd: %s write_fd: %s wbuf: %d rbuf: %d stdin_e fd_written += (size_t)rres; assert( fd_to_write >= (size_t)rres ); fd_to_write -= (size_t)rres; + fd_written += (size_t)rres; total_fd_written += (size_t)rres; } } - /* read from socket, fill socket read buffer */ - if( FD_ISSET( fd, &read_set ) ) { - assert( stdout_to_write == 0 ); - rres = read( fd, read_buffer, READ_BUFFER_SIZE ); + /* if there is space in the read buffer and something to be read, do so */ + if( FD_ISSET( client_fd, &read_set ) ) { + assert( fd_to_write == 0 ); + rres = read( client_fd, buffer, BUFFER_SIZE ); if( rres < 0 ) { if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) { /* skip */ } else { fprintf( stderr, "read from socket failed: %s (%d)\n", strerror( errno ), errno ); - (void)close( fd ); goto FAIL; } } else if( rres == 0 ) { /* EOF on socket */ - shutdown( fd, SHUT_RD ); + shutdown( client_fd, SHUT_RD ); fd_eof = true; #if DEBUG fprintf( stderr, "EOF on socket\n" ); -#endif - } else { - assert( rres > 0 ); - stdout_written = 0; - stdout_to_write = (size_t)rres; - total_fd_read += (size_t)rres; - } - } - - /* read from stdin, fill socket write buffer */ - if( FD_ISSET( STDIN_FILENO, &read_set ) ) { - assert( fd_to_write == 0 ); - rres = read( STDIN_FILENO, write_buffer, WRITE_BUFFER_SIZE ); - if( rres < 0 ) { - if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR ) { - /* skip */ - } else { - fprintf( stderr, "read from stdin failed: %s (%d)\n", - strerror( errno ), errno ); - (void)close( fd ); - goto FAIL; - } - } else if( rres == 0 ) { - /* EOF on STDIN */ - stdin_eof = true; - fclose( stdin ); - -#if DEBUG - fprintf( stderr, "EOF on stdin\n" ); #endif } else { assert( rres > 0 ); fd_written = 0; fd_to_write = (size_t)rres; - total_stdin_read += (size_t)rres; + total_fd_read += (size_t)rres; } } - - /* close writing side of the socket if we have emptied - * the socket write buffer and there is nothing more on - * the input (stdin) - */ - if( fd_to_write == 0 && stdin_eof && !fd_write_closed ) { -#if DEBUG - fprintf( stderr, "socket SHUT_WR\n" ); -#endif - shutdown( fd, SHUT_WR ); - fd_write_closed = true; - } } count++; if( count % 10000 == 0 ) { - fprintf( stderr, "Transfered nof_selects: %d, stdin: %zd, stdout: %zd, fd-in: %zd, fd-out: %zd\n", - count, total_stdin_read, total_stdout_written, total_fd_read, total_fd_written ); + fprintf( stderr, "Transfered nof_selects: %d, fd-in: %zd, fd-out: %zd\n", + count, total_fd_read, total_fd_written ); } - } while( !terminate && !( stdin_eof && fd_eof ) ); + } while( !terminate && !( fd_eof && fd_to_write == 0 ) ); END: - fprintf( stderr, "Terminated stdin: %zd, stdout: %zd, fd-in: %zd, fd-out: %zd\n", - total_stdin_read, total_stdout_written, total_fd_read, total_fd_written ); - res = close( fd ); - if( res < 0 ) { - fprintf( stderr, "close failed: %s (%d)\n", strerror( errno ), errno ); - goto FAIL; - } - + fprintf( stderr, "Terminated nof_selects: %d, fd-in: %zd, fd-out: %zd\n", + count, total_fd_read, total_fd_written ); + + (void)close( client_fd ); + (void)close( serv_fd ); freeaddrinfo( result ); goto OK; +FAIL: -} + if( client_fd >= 0 ) (void)close( client_fd ); + if( serv_fd >= 0 ) (void)close( serv_fd ); + if( result != NULL ) freeaddrinfo( result ); + +#ifdef _WIN32 + WSACleanup( ); +#endif + + return EXIT_FAILURE; + +OK: + +#ifdef _WIN32 + WSACleanup( ); #endif + + return EXIT_SUCCESS; +} -- cgit v1.2.3-54-g00ecf