Subversion Repositories HelenOS

Rev

Rev 4740 | Rev 4749 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup echo
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  *  Networking test 1 application - UDP sockets.
  35.  */
  36.  
  37. #include <malloc.h>
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <task.h>
  41. #include <time.h>
  42.  
  43. #include "../../include/in.h"
  44. #include "../../include/in6.h"
  45. #include "../../include/inet.h"
  46. #include "../../include/socket.h"
  47.  
  48. #include "../../err.h"
  49.  
  50. #include "../parse.h"
  51. #include "../print_error.h"
  52.  
  53. /** Echo module name.
  54.  */
  55. #define NAME    "Nettest1"
  56.  
  57. /** Packet data pattern.
  58.  */
  59. #define NETTEST1_TEXT   "Networking test 1 - UDP sockets"
  60.  
  61. /** Module entry point.
  62.  *  Starts testing.
  63.  *  @param argc The number of command line parameters. Input parameter.
  64.  *  @param argv The command line parameters. Input parameter.
  65.  *  @returns EOK on success.
  66.  */
  67. int     main( int argc, char * argv[] );
  68.  
  69. /** Prints the application help.
  70.  */
  71. void    print_help( void );
  72.  
  73. /** Translates the character string to the protocol family number.
  74.  *  @param name The protocol family name. Input parameter.
  75.  *  @returns The corresponding protocol family number.
  76.  *  @returns EPFNOSUPPORTED if the protocol family is not supported.
  77.  */
  78. int     parse_protocol_family( const char * name );
  79.  
  80. /** Translates the character string to the socket type number.
  81.  *  @param name The socket type name. Input parameter.
  82.  *  @returns The corresponding socket type number.
  83.  *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
  84.  */
  85. int     parse_socket_type( const char * name );
  86.  
  87. void    refresh_data( char * data, size_t size );
  88. int sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type );
  89. int sockets_close( int verbose, int * socket_ids, int sockets );
  90. int sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen );
  91. int sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages );
  92. int sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
  93. int sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
  94. void    print_mark( int index );
  95.  
  96. void print_help( void ){
  97.     printf(
  98.         "Network Networking test 1 aplication - UDP sockets\n" \
  99.         "Usage: echo [options] numeric_address\n" \
  100.         "Where options are:\n" \
  101.         "-f protocol_family | --family=protocol_family\n" \
  102.         "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
  103.         "\n" \
  104.         "-h | --help\n" \
  105.         "\tShow this application help.\n"
  106.         "\n" \
  107.         "-m count | --messages=count\n" \
  108.         "\tThe number of messages to send and receive per socket. The default is 100.\n" \
  109.         "\n" \
  110.         "-n sockets | --sockets=count\n" \
  111.         "\tThe number of sockets to use. The default is 100.\n" \
  112.         "\n" \
  113.         "-p port_number | --port=port_number\n" \
  114.         "\tThe port number the application should send messages to. The default is 7.\n" \
  115.         "\n" \
  116.         "-s packet_size | --size=packet_size\n" \
  117.         "\tThe packet data size the application sends. The default is 38 bytes.\n" \
  118.         "\n" \
  119.         "-v | --verbose\n" \
  120.         "\tShow all output messages.\n"
  121.     );
  122. }
  123.  
  124. int parse_protocol_family( const char * name ){
  125.     if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
  126.         return PF_INET;
  127.     }else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
  128.         return PF_INET6;
  129.     }
  130.     return EPFNOSUPPORT;
  131. }
  132.  
  133. int parse_socket_type( const char * name ){
  134.     if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
  135.         return SOCK_DGRAM;
  136.     }else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
  137.         return SOCK_STREAM;
  138.     }
  139.     return ESOCKTNOSUPPORT;
  140. }
  141.  
  142. void refresh_data( char * data, size_t size ){
  143.     size_t  length;
  144.  
  145.     // fill the data
  146.     length = 0;
  147.     while( size > length + sizeof( NETTEST1_TEXT )){
  148.         memcpy( data + length, NETTEST1_TEXT, sizeof( NETTEST1_TEXT ));
  149.         length += sizeof( NETTEST1_TEXT );
  150.     }
  151.     memcpy( data + length, NETTEST1_TEXT, size - length );
  152. }
  153.  
  154. int sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type ){
  155.     int index;
  156.  
  157.     if( verbose ) printf( "Create\t" );
  158.     fflush( stdout );
  159.     for( index = 0; index < sockets; ++ index ){
  160.         socket_ids[ index ] = socket( family, type, 0 );
  161.         if( socket_ids[ index ] < 0 ){
  162.             printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
  163.             socket_print_error( stderr, socket_ids[ index ], "Socket create: ", "\n" );
  164.             return socket_ids[ index ];
  165.         }
  166.         if( verbose ) print_mark( index );
  167.     }
  168.     return EOK;
  169. }
  170.  
  171. int sockets_close( int verbose, int * socket_ids, int sockets ){
  172.     ERROR_DECLARE;
  173.  
  174.     int index;
  175.  
  176.     if( verbose ) printf( "\tClose\t" );
  177.     fflush( stdout );
  178.     for( index = 0; index < sockets; ++ index ){
  179.         if( ERROR_OCCURRED( closesocket( socket_ids[ index ] ))){
  180.             printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
  181.             socket_print_error( stderr, ERROR_CODE, "Socket close: ", "\n" );
  182.             return ERROR_CODE;
  183.         }
  184.         if( verbose ) print_mark( index );
  185.     }
  186.     return EOK;
  187. }
  188.  
  189. int sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen ){
  190.     ERROR_DECLARE;
  191.  
  192.     int index;
  193.  
  194.     if( verbose ) printf( "\tConnect\t" );
  195.     fflush( stdout );
  196.     for( index = 0; index < sockets; ++ index ){
  197.         if( ERROR_OCCURRED( connect( socket_ids[ index ], address, addrlen ))){
  198.             socket_print_error( stderr, ERROR_CODE, "Socket connect: ", "\n" );
  199.             return ERROR_CODE;
  200.         }
  201.         if( verbose ) print_mark( index );
  202.     }
  203.     return EOK;
  204. }
  205.  
  206. int sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages ){
  207.     ERROR_DECLARE;
  208.  
  209.     int index;
  210.     int message;
  211.  
  212.     if( verbose ) printf( "\tSendto\t" );
  213.     fflush( stdout );
  214.     for( index = 0; index < sockets; ++ index ){
  215.         for( message = 0; message < messages; ++ message ){
  216.             if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, addrlen ))){
  217.                 printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
  218.                 socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
  219.                 return ERROR_CODE;
  220.             }
  221.         }
  222.         if( verbose ) print_mark( index );
  223.     }
  224.     return EOK;
  225. }
  226.  
  227. int sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
  228.     int value;
  229.     int index;
  230.     int message;
  231.  
  232.     if( verbose ) printf( "\tRecvfrom\t" );
  233.     fflush( stdout );
  234.     for( index = 0; index < sockets; ++ index ){
  235.         for( message = 0; message < messages; ++ message ){
  236.             value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
  237.             if( value < 0 ){
  238.                 printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
  239.                 socket_print_error( stderr, value, "Socket receive: ", "\n" );
  240.                 return value;
  241.             }
  242.         }
  243.         if( verbose ) print_mark( index );
  244.     }
  245.     return EOK;
  246. }
  247.  
  248. int sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
  249.     ERROR_DECLARE;
  250.  
  251.     int value;
  252.     int index;
  253.     int message;
  254.  
  255.     if( verbose ) printf( "\tSendto and recvfrom\t" );
  256.     fflush( stdout );
  257.     for( index = 0; index < sockets; ++ index ){
  258.         for( message = 0; message < messages; ++ message ){
  259.             if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, * addrlen ))){
  260.                 printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
  261.                 socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
  262.                 return ERROR_CODE;
  263.             }
  264.             value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
  265.             if( value < 0 ){
  266.                 printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
  267.                 socket_print_error( stderr, value, "Socket receive: ", "\n" );
  268.                 return value;
  269.             }
  270.         }
  271.         if( verbose ) print_mark( index );
  272.     }
  273.     return EOK;
  274. }
  275.  
  276. void print_mark( int index ){
  277.     if(( index + 1 ) % 10 ){
  278.         printf( "*" );
  279.     }else{
  280.         printf( "|" );
  281.     }
  282.     fflush( stdout );
  283. }
  284.  
  285. int main( int argc, char * argv[] ){
  286.     ERROR_DECLARE;
  287.  
  288.     size_t              size            = 38;
  289.     int                 verbose         = 0;
  290.     sock_type_t         type            = SOCK_DGRAM;
  291.     int                 sockets         = 10;
  292.     int                 messages        = 10;
  293.     int                 family          = PF_INET;
  294.     uint16_t            port            = 7;
  295.  
  296.     socklen_t           max_length      = sizeof( struct sockaddr_in6 );
  297.     uint8_t             address_data[ max_length ];
  298.     struct sockaddr *       address     = ( struct sockaddr * ) address_data;
  299.     struct sockaddr_in *    address_in      = ( struct sockaddr_in * ) address;
  300.     struct sockaddr_in6 *   address_in6 = ( struct sockaddr_in6 * ) address;
  301.     socklen_t           addrlen;
  302. //  char                address_string[ INET6_ADDRSTRLEN ];
  303.     uint8_t *           address_start;
  304.  
  305.     int *               socket_ids;
  306.     char *              data;
  307.     int                 value;
  308.     int                 index;
  309.     struct timeval      time_before;
  310.     struct timeval      time_after;
  311.  
  312.     printf( "Task %d - ", task_get_id());
  313.     printf( "%s\n", NAME );
  314.  
  315.     if( argc <= 1 ){
  316.         print_help();
  317.         return EINVAL;
  318.     }
  319.  
  320.     for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
  321.         if( argv[ index ][ 0 ] == '-' ){
  322.             switch( argv[ index ][ 1 ] ){
  323.                 case 'f':   ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, parse_protocol_family ));
  324.                             break;
  325.                 case 'h':   print_help();
  326.                             return EOK;
  327.                             break;
  328.                 case 'm':   ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 0 ));
  329.                             break;
  330.                 case 'n':   ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 0 ));
  331.                             break;
  332.                 case 'p':   ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
  333.                             port = ( uint16_t ) value;
  334.                             break;
  335.                 case 's':   ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
  336.                             size = (value >= 0 ) ? ( size_t ) value : 0;
  337.                             break;
  338.                 case 't':   ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, parse_socket_type ));
  339.                             type = ( sock_type_t ) value;
  340.                             break;
  341.                 case 'v':   verbose = 1;
  342.                             break;
  343.                 case '-':   if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
  344.                                 ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, parse_protocol_family ));
  345.                             }else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
  346.                                 print_help();
  347.                                 return EOK;
  348.                             }else if( str_lcmp( argv[ index ] + 2, "messages=", 6 ) == 0 ){
  349.                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 8 ));
  350.                             }else if( str_lcmp( argv[ index ] + 2, "sockets=", 6 ) == 0 ){
  351.                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 8 ));
  352.                             }else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
  353.                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
  354.                                 port = ( uint16_t ) value;
  355.                             }else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
  356.                                 ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, parse_socket_type ));
  357.                                 type = ( sock_type_t ) value;
  358.                             }else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
  359.                                 verbose = 1;
  360.                             }else{
  361.                                 print_unrecognized( index, argv[ index ] + 2 );
  362.                                 print_help();
  363.                                 return EINVAL;
  364.                             }
  365.                             break;
  366.                 default:
  367.                     print_unrecognized( index, argv[ index ] + 1 );
  368.                     print_help();
  369.                     return EINVAL;
  370.             }
  371.         }else{
  372.             print_unrecognized( index, argv[ index ] );
  373.             print_help();
  374.             return EINVAL;
  375.         }
  376.     }
  377.  
  378.     bzero( address_data, max_length );
  379.     switch( family ){
  380.         case PF_INET:
  381.             address_in->sin_family = AF_INET;
  382.             address_in->sin_port = htons( port );
  383.             address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
  384.             addrlen = sizeof( struct sockaddr_in );
  385.             break;
  386.         case PF_INET6:
  387.             address_in6->sin6_family = AF_INET6;
  388.             address_in6->sin6_port = htons( port );
  389.             address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
  390.             addrlen = sizeof( struct sockaddr_in6 );
  391.             break;
  392.         default:
  393.             fprintf( stderr, "Address family is not supported\n" );
  394.             return EAFNOSUPPORT;
  395.     }
  396.  
  397.     if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
  398.         fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
  399.         return ERROR_CODE;
  400.     }
  401.  
  402.     if( size <= 0 ){
  403.         fprintf( stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size );
  404.         size = 1024;
  405.     }
  406.     // size plus terminating null (\0)
  407.     data = ( char * ) malloc( size + 1 );
  408.     if( ! data ){
  409.         fprintf( stderr, "Failed to allocate data buffer.\n" );
  410.         return ENOMEM;
  411.     }
  412.     refresh_data( data, size );
  413.  
  414.     if( sockets <= 0 ){
  415.         fprintf( stderr, "Socket count too small (%d). Using 2 instead.\n", sockets );
  416.         sockets = 2;
  417.     }
  418.     // count plus terminating null (\0)
  419.     socket_ids = ( int * ) malloc( sizeof( int ) * ( sockets + 1 ));
  420.     if( ! socket_ids ){
  421.         fprintf( stderr, "Failed to allocate receive buffer.\n" );
  422.         return ENOMEM;
  423.     }
  424.     socket_ids[ sockets ] = NULL;
  425.  
  426.     if( verbose ) printf( "Starting tests\n" );
  427.  
  428.     if( verbose ) printf( "1 socket, 1 message\n" );
  429.  
  430.     if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
  431.         fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
  432.         return ERROR_CODE;
  433.     }
  434.  
  435.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
  436.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
  437.     if( verbose ) printf( "\tOK\n" );
  438.  
  439.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
  440.     if( type == SOCK_STREAM ){
  441.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
  442.     }
  443.     ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
  444.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
  445.     if( verbose ) printf( "\tOK\n" );
  446.  
  447.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
  448.     if( type == SOCK_STREAM ){
  449.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
  450.     }
  451.     ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, 1 ));
  452.     ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
  453.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
  454.     if( verbose ) printf( "\tOK\n" );
  455.  
  456.     if( verbose ) printf( "1 socket, %d messages\n", messages );
  457.  
  458.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
  459.     if( type == SOCK_STREAM ){
  460.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
  461.     }
  462.     ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
  463.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
  464.     if( verbose ) printf( "\tOK\n" );
  465.  
  466.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
  467.     if( type == SOCK_STREAM ){
  468.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
  469.     }
  470.     ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, messages ));
  471.     ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
  472.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
  473.     if( verbose ) printf( "\tOK\n" );
  474.  
  475.     if( verbose ) printf( "%d sockets, 1 message\n", sockets );
  476.  
  477.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
  478.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
  479.     if( verbose ) printf( "\tOK\n" );
  480.  
  481.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
  482.     if( type == SOCK_STREAM ){
  483.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
  484.     }
  485.     ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
  486.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
  487.     if( verbose ) printf( "\tOK\n" );
  488.  
  489.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
  490.     if( type == SOCK_STREAM ){
  491.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
  492.     }
  493.     ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, 1 ));
  494.     ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
  495.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
  496.     if( verbose ) printf( "\tOK\n" );
  497.  
  498.     if( verbose ) printf( "%d sockets, %d messages\n", sockets, messages );
  499.  
  500.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
  501.     if( type == SOCK_STREAM ){
  502.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
  503.     }
  504.     ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
  505.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
  506.     if( verbose ) printf( "\tOK\n" );
  507.  
  508.     ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
  509.     if( type == SOCK_STREAM ){
  510.         ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
  511.     }
  512.     ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, messages ));
  513.     ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
  514.     ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
  515.  
  516.     if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
  517.         fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
  518.         return ERROR_CODE;
  519.     }
  520.  
  521.     if( verbose ) printf( "\tOK\n" );
  522.  
  523.     printf( "Tested in %d microseconds\n", tv_sub( & time_after, & time_before ));
  524.  
  525.     if( verbose ) printf( "Exiting\n" );
  526.  
  527.     return EOK;
  528. }
  529.  
  530. /** @}
  531.  */
  532.