Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/app/nettest1/nettest1.c

    r3be62bc r9d28b9c  
    4848#include "../../err.h"
    4949
    50 #include "../nettest.h"
    5150#include "../parse.h"
    5251#include "../print_error.h"
     
    6665 *  @returns EOK on success.
    6766 */
    68 int main(int argc, char * argv[]);
     67int             main( int argc, char * argv[] );
    6968
    7069/** Prints the application help.
    7170 */
    72 void nettest1_print_help(void);
     71void    print_help( void );
     72
     73/** Translates the character string to the protocol family number.
     74 *  @param[in] name The protocol family name.
     75 *  @returns The corresponding protocol family number.
     76 *  @returns EPFNOSUPPORTED if the protocol family is not supported.
     77 */
     78int             parse_protocol_family( const char * name );
     79
     80/** Translates the character string to the socket type number.
     81 *  @param[in] name The socket type name.
     82 *  @returns The corresponding socket type number.
     83 *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
     84 */
     85int             parse_socket_type( const char * name );
    7386
    7487/** Refreshes the data.
     
    7790 *  @param[in] size The data block size in bytes.
    7891 */
    79 void nettest1_refresh_data(char * data, size_t size);
    80 
    81 int main(int argc, char * argv[]){
    82         ERROR_DECLARE;
    83 
    84         size_t size                     = 27;
    85         int verbose                     = 0;
    86         sock_type_t type        = SOCK_DGRAM;
    87         int sockets                     = 10;
    88         int messages            = 10;
    89         int family                      = PF_INET;
    90         uint16_t port           = 7;
    91 
    92         socklen_t max_length                            = sizeof(struct sockaddr_in6);
    93         uint8_t address_data[max_length];
    94         struct sockaddr * address                       = (struct sockaddr *) address_data;
    95         struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    96         struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
    97         socklen_t addrlen;
    98 //      char address_string[INET6_ADDRSTRLEN];
    99         uint8_t * address_start;
    100 
    101         int * socket_ids;
    102         char * data;
    103         int value;
    104         int index;
    105         struct timeval time_before;
    106         struct timeval time_after;
    107 
    108         // print the program label
    109         printf("Task %d - ", task_get_id());
    110         printf("%s\n", NAME);
    111 
    112         // parse the command line arguments
    113         // stop before the last argument if it does not start with the minus sign ('-')
    114         for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
    115                 // options should start with the minus sign ('-')
    116                 if(argv[index][0] == '-'){
    117                         switch(argv[index][1]){
    118                                 // short options with only one letter
    119                                 case 'f':
    120                                         ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    121                                         break;
    122                                 case 'h':
    123                                         nettest1_print_help();
    124                                         return EOK;
    125                                         break;
    126                                 case 'm':
    127                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 0));
    128                                         break;
    129                                 case 'n':
    130                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 0));
    131                                         break;
    132                                 case 'p':
    133                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 0));
    134                                         port = (uint16_t) value;
    135                                         break;
    136                                 case 's':
    137                                         ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "packet size", 0));
    138                                         size = (value >= 0) ? (size_t) value : 0;
    139                                         break;
    140                                 case 't':
    141                                         ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, parse_socket_type));
    142                                         type = (sock_type_t) value;
    143                                         break;
    144                                 case 'v':
    145                                         verbose = 1;
    146                                         break;
    147                                 // long options with the double minus sign ('-')
    148                                 case '-':
    149                                         if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    150                                                 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    151                                         }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    152                                                 nettest1_print_help();
    153                                                 return EOK;
    154                                         }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
    155                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 8));
    156                                         }else if(str_lcmp(argv[index] + 2, "sockets=", 6) == 0){
    157                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 8));
    158                                         }else if(str_lcmp(argv[index] + 2, "port=", 5) == 0){
    159                                                 ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 7));
    160                                                 port = (uint16_t) value;
    161                                         }else if(str_lcmp(argv[index] + 2, "type=", 5) == 0){
    162                                                 ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, parse_socket_type));
    163                                                 type = (sock_type_t) value;
    164                                         }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
    165                                                 verbose = 1;
    166                                         }else{
    167                                                 print_unrecognized(index, argv[index] + 2);
    168                                                 nettest1_print_help();
    169                                                 return EINVAL;
    170                                         }
    171                                         break;
    172                                 default:
    173                                         print_unrecognized(index, argv[index] + 1);
    174                                         nettest1_print_help();
    175                                         return EINVAL;
    176                         }
    177                 }else{
    178                         print_unrecognized(index, argv[index]);
    179                         nettest1_print_help();
    180                         return EINVAL;
    181                 }
    182         }
    183 
    184         // if not before the last argument containing the address
    185         if(index >= argc){
    186                 printf("Command line error: missing address\n");
    187                 nettest1_print_help();
    188                 return EINVAL;
    189         }
    190 
    191         // prepare the address buffer
    192         bzero(address_data, max_length);
    193         switch(family){
    194                 case PF_INET:
    195                         address_in->sin_family = AF_INET;
    196                         address_in->sin_port = htons(port);
    197                         address_start = (uint8_t *) &address_in->sin_addr.s_addr;
    198                         addrlen = sizeof(struct sockaddr_in);
    199                         break;
    200                 case PF_INET6:
    201                         address_in6->sin6_family = AF_INET6;
    202                         address_in6->sin6_port = htons(port);
    203                         address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
    204                         addrlen = sizeof(struct sockaddr_in6);
    205                         break;
    206                 default:
    207                         fprintf(stderr, "Address family is not supported\n");
    208                         return EAFNOSUPPORT;
    209         }
    210 
    211         // parse the last argument which should contain the address
    212         if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    213                 fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
    214                 return ERROR_CODE;
    215         }
    216 
    217         // check the buffer size
    218         if(size <= 0){
    219                 fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
    220                 size = 1024;
    221         }
    222 
    223         // prepare the buffer
    224         // size plus the terminating null (\0)
    225         data = (char *) malloc(size + 1);
    226         if(! data){
    227                 fprintf(stderr, "Failed to allocate data buffer.\n");
    228                 return ENOMEM;
    229         }
    230         nettest1_refresh_data(data, size);
    231 
    232         // check the socket count
    233         if(sockets <= 0){
    234                 fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
    235                 sockets = 2;
    236         }
    237 
    238         // prepare the socket buffer
    239         // count plus the terminating null (\0)
    240         socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
    241         if(! socket_ids){
    242                 fprintf(stderr, "Failed to allocate receive buffer.\n");
    243                 return ENOMEM;
    244         }
    245         socket_ids[sockets] = NULL;
    246 
    247         if(verbose){
    248                 printf("Starting tests\n");
    249         }
    250 
    251         if(verbose){
    252                 printf("1 socket, 1 message\n");
    253         }
    254 
    255         if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
    256                 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
    257                 return ERROR_CODE;
    258         }
    259 
    260         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
    261         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
    262         if(verbose){
    263                 printf("\tOK\n");
    264         }
    265 
    266         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
    267         if(type == SOCK_STREAM){
    268                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
    269         }
    270         ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, 1));
    271         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
    272         if(verbose){
    273                 printf("\tOK\n");
    274         }
    275 
    276         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
    277         if(type == SOCK_STREAM){
    278                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
    279         }
    280         ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, 1, address, addrlen, data, size, 1));
    281         ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, 1));
    282         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
    283         if(verbose){
    284                 printf("\tOK\n");
    285         }
    286 
    287         if(verbose){
    288                 printf("1 socket, %d messages\n", messages);
    289         }
    290 
    291         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
    292         if(type == SOCK_STREAM){
    293                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
    294         }
    295         ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, messages));
    296         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
    297         if(verbose){
    298                 printf("\tOK\n");
    299         }
    300 
    301         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
    302         if(type == SOCK_STREAM){
    303                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
    304         }
    305         ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, 1, address, addrlen, data, size, messages));
    306         ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, messages));
    307         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
    308         if(verbose){
    309                 printf("\tOK\n");
    310         }
    311 
    312         if(verbose){
    313                 printf("%d sockets, 1 message\n", sockets);
    314         }
    315 
    316         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
    317         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
    318         if(verbose){
    319                 printf("\tOK\n");
    320         }
    321 
    322         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
    323         if(type == SOCK_STREAM){
    324                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
    325         }
    326         ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, 1));
    327         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
    328         if(verbose){
    329                 printf("\tOK\n");
    330         }
    331 
    332         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
    333         if(type == SOCK_STREAM){
    334                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
    335         }
    336         ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, 1));
    337         ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, 1));
    338         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
    339         if(verbose){
    340                 printf("\tOK\n");
    341         }
    342 
    343         if(verbose){
    344                 printf("%d sockets, %d messages\n", sockets, messages);
    345         }
    346 
    347         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
    348         if(type == SOCK_STREAM){
    349                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
    350         }
    351         ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
    352         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
    353         if(verbose){
    354                 printf("\tOK\n");
    355         }
    356 
    357         ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
    358         if(type == SOCK_STREAM){
    359                 ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
    360         }
    361         ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, messages));
    362         ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
    363         ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
    364 
    365         if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
    366                 fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
    367                 return ERROR_CODE;
    368         }
    369 
    370         if(verbose){
    371                 printf("\tOK\n");
    372         }
    373 
    374         printf("Tested in %d microseconds\n", tv_sub(&time_after, &time_before));
    375 
    376         if(verbose){
    377                 printf("Exiting\n");
    378         }
    379 
    380         return EOK;
    381 }
    382 
    383 void nettest1_print_help(void){
     92void    refresh_data( char * data, size_t size );
     93
     94/** Creates new sockets.
     95 *  @param[in] verbose A value indicating whether to print out verbose information.
     96 *  @param[out] socket_ids A field to store the socket identifiers.
     97 *  @param[in] sockets The number of sockets to create. Should be at most the size of the field.
     98 *  @param[in] family The socket address family.
     99 *  @param[in] type The socket type.
     100 *  @returns EOK on success.
     101 *  @returns Other error codes as defined for the socket() function.
     102 */
     103int     sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type );
     104
     105/** Closes sockets.
     106 *  @param[in] verbose A value indicating whether to print out verbose information.
     107 *  @param[in] socket_ids A field of stored socket identifiers.
     108 *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
     109 *  @returns EOK on success.
     110 *  @returns Other error codes as defined for the closesocket() function.
     111 */
     112int     sockets_close( int verbose, int * socket_ids, int sockets );
     113
     114/** Connects sockets.
     115 *  @param[in] verbose A value indicating whether to print out verbose information.
     116 *  @param[in] socket_ids A field of stored socket identifiers.
     117 *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
     118 *  @param[in] address The destination host address to connect to.
     119 *  @param[in] addrlen The length of the destination address in bytes.
     120 *  @returns EOK on success.
     121 *  @returns Other error codes as defined for the connect() function.
     122 */
     123int     sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen );
     124
     125/** Sends data via sockets.
     126 *  @param[in] verbose A value indicating whether to print out verbose information.
     127 *  @param[in] socket_ids A field of stored socket identifiers.
     128 *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
     129 *  @param[in] address The destination host address to send data to.
     130 *  @param[in] addrlen The length of the destination address in bytes.
     131 *  @param[in] data The data to be sent.
     132 *  @param[in] size The data size in bytes.
     133 *  @param[in] messages The number of datagrams per socket to be sent.
     134 *  @returns EOK on success.
     135 *  @returns Other error codes as defined for the sendto() function.
     136 */
     137int     sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages );
     138
     139/** Receives data via sockets.
     140 *  @param[in] verbose A value indicating whether to print out verbose information.
     141 *  @param[in] socket_ids A field of stored socket identifiers.
     142 *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
     143 *  @param[in] address The source host address of received datagrams.
     144 *  @param[in,out] addrlen The maximum length of the source address in bytes. The actual size of the source address is set instead.
     145 *  @param[out] data The received data.
     146 *  @param[in] size The maximum data size in bytes.
     147 *  @param[in] messages The number of datagrams per socket to be received.
     148 *  @returns EOK on success.
     149 *  @returns Other error codes as defined for the recvfrom() function.
     150 */
     151int     sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
     152
     153/** Sends and receives data via sockets.
     154 *  Each datagram is sent and a reply read consequently.
     155 *  The next datagram is sent after the reply is received.
     156 *  @param[in] verbose A value indicating whether to print out verbose information.
     157 *  @param[in] socket_ids A field of stored socket identifiers.
     158 *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
     159 *  @param[in,out] address The destination host address to send data to. The source host address of received datagrams is set instead.
     160 *  @param[in] addrlen The length of the destination address in bytes.
     161 *  @param[in,out] data The data to be sent. The received data are set instead.
     162 *  @param[in] size The data size in bytes.
     163 *  @param[in] messages The number of datagrams per socket to be received.
     164 *  @returns EOK on success.
     165 *  @returns Other error codes as defined for the recvfrom() function.
     166 */
     167int     sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
     168
     169/** Prints a mark.
     170 *  If the index is a multiple of ten, a different mark is printed.
     171 *  @param[in] index The index of the mark to be printed.
     172 */
     173void    print_mark( int index );
     174
     175void print_help( void ){
    384176        printf(
    385177                "Network Networking test 1 aplication - sockets\n" \
     
    409201}
    410202
    411 void nettest1_refresh_data(char * data, size_t size){
    412         size_t length;
     203int parse_protocol_family( const char * name ){
     204        if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
     205                return PF_INET;
     206        }else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
     207                return PF_INET6;
     208        }
     209        return EPFNOSUPPORT;
     210}
     211
     212int parse_socket_type( const char * name ){
     213        if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
     214                return SOCK_DGRAM;
     215        }else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
     216                return SOCK_STREAM;
     217        }
     218        return ESOCKTNOSUPPORT;
     219}
     220
     221void refresh_data( char * data, size_t size ){
     222        size_t  length;
    413223
    414224        // fill the data
    415225        length = 0;
    416         while(size > length + sizeof(NETTEST1_TEXT) - 1){
    417                 memcpy(data + length, NETTEST1_TEXT, sizeof(NETTEST1_TEXT) - 1);
    418                 length += sizeof(NETTEST1_TEXT) - 1;
    419         }
    420         memcpy(data + length, NETTEST1_TEXT, size - length);
    421         data[size] = '\0';
     226        while( size > length + sizeof( NETTEST1_TEXT ) - 1 ){
     227                memcpy( data + length, NETTEST1_TEXT, sizeof( NETTEST1_TEXT ) - 1 );
     228                length += sizeof( NETTEST1_TEXT ) - 1;
     229        }
     230        memcpy( data + length, NETTEST1_TEXT, size - length );
     231        data[ size ] = '\0';
     232}
     233
     234int sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type ){
     235        int     index;
     236
     237        if( verbose ) printf( "Create\t" );
     238        fflush( stdout );
     239        for( index = 0; index < sockets; ++ index ){
     240                socket_ids[ index ] = socket( family, type, 0 );
     241                if( socket_ids[ index ] < 0 ){
     242                        printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
     243                        socket_print_error( stderr, socket_ids[ index ], "Socket create: ", "\n" );
     244                        return socket_ids[ index ];
     245                }
     246                if( verbose ){
     247                        print_mark( index );
     248                }
     249        }
     250        return EOK;
     251}
     252
     253int sockets_close( int verbose, int * socket_ids, int sockets ){
     254        ERROR_DECLARE;
     255
     256        int     index;
     257
     258        if( verbose ) printf( "\tClose\t" );
     259        fflush( stdout );
     260        for( index = 0; index < sockets; ++ index ){
     261                if( ERROR_OCCURRED( closesocket( socket_ids[ index ] ))){
     262                        printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
     263                        socket_print_error( stderr, ERROR_CODE, "Socket close: ", "\n" );
     264                        return ERROR_CODE;
     265                }
     266                if( verbose ) print_mark( index );
     267        }
     268        return EOK;
     269}
     270
     271int sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen ){
     272        ERROR_DECLARE;
     273
     274        int     index;
     275
     276        if( verbose ) printf( "\tConnect\t" );
     277        fflush( stdout );
     278        for( index = 0; index < sockets; ++ index ){
     279                if( ERROR_OCCURRED( connect( socket_ids[ index ], address, addrlen ))){
     280                        socket_print_error( stderr, ERROR_CODE, "Socket connect: ", "\n" );
     281                        return ERROR_CODE;
     282                }
     283                if( verbose ) print_mark( index );
     284        }
     285        return EOK;
     286}
     287
     288int sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages ){
     289        ERROR_DECLARE;
     290
     291        int     index;
     292        int     message;
     293
     294        if( verbose ) printf( "\tSendto\t" );
     295        fflush( stdout );
     296        for( index = 0; index < sockets; ++ index ){
     297                for( message = 0; message < messages; ++ message ){
     298                        if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, addrlen ))){
     299                                printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
     300                                socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
     301                                return ERROR_CODE;
     302                        }
     303                }
     304                if( verbose ) print_mark( index );
     305        }
     306        return EOK;
     307}
     308
     309int sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
     310        int     value;
     311        int     index;
     312        int     message;
     313
     314        if( verbose ) printf( "\tRecvfrom\t" );
     315        fflush( stdout );
     316        for( index = 0; index < sockets; ++ index ){
     317                for( message = 0; message < messages; ++ message ){
     318                        value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
     319                        if( value < 0 ){
     320                                printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
     321                                socket_print_error( stderr, value, "Socket receive: ", "\n" );
     322                                return value;
     323                        }
     324                }
     325                if( verbose ) print_mark( index );
     326        }
     327        return EOK;
     328}
     329
     330int sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
     331        ERROR_DECLARE;
     332
     333        int     value;
     334        int     index;
     335        int     message;
     336
     337        if( verbose ) printf( "\tSendto and recvfrom\t" );
     338        fflush( stdout );
     339        for( index = 0; index < sockets; ++ index ){
     340                for( message = 0; message < messages; ++ message ){
     341                        if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, * addrlen ))){
     342                                printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
     343                                socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
     344                                return ERROR_CODE;
     345                        }
     346                        value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
     347                        if( value < 0 ){
     348                                printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
     349                                socket_print_error( stderr, value, "Socket receive: ", "\n" );
     350                                return value;
     351                        }
     352                }
     353                if( verbose ) print_mark( index );
     354        }
     355        return EOK;
     356}
     357
     358void print_mark( int index ){
     359        if(( index + 1 ) % 10 ){
     360                printf( "*" );
     361        }else{
     362                printf( "|" );
     363        }
     364        fflush( stdout );
     365}
     366
     367int main( int argc, char * argv[] ){
     368        ERROR_DECLARE;
     369
     370        size_t                          size                    = 27;
     371        int                                     verbose                 = 0;
     372        sock_type_t                     type                    = SOCK_DGRAM;
     373        int                                     sockets                 = 10;
     374        int                                     messages                = 10;
     375        int                                     family                  = PF_INET;
     376        uint16_t                        port                    = 7;
     377
     378        socklen_t                       max_length              = sizeof( struct sockaddr_in6 );
     379        uint8_t                         address_data[ max_length ];
     380        struct sockaddr *               address         = ( struct sockaddr * ) address_data;
     381        struct sockaddr_in *    address_in              = ( struct sockaddr_in * ) address;
     382        struct sockaddr_in6 *   address_in6     = ( struct sockaddr_in6 * ) address;
     383        socklen_t                       addrlen;
     384//      char                            address_string[ INET6_ADDRSTRLEN ];
     385        uint8_t *                       address_start;
     386
     387        int *                           socket_ids;
     388        char *                          data;
     389        int                                     value;
     390        int                                     index;
     391        struct timeval          time_before;
     392        struct timeval          time_after;
     393
     394        printf( "Task %d - ", task_get_id());
     395        printf( "%s\n", NAME );
     396
     397        if( argc <= 1 ){
     398                print_help();
     399                return EINVAL;
     400        }
     401
     402        for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
     403                if( argv[ index ][ 0 ] == '-' ){
     404                        switch( argv[ index ][ 1 ] ){
     405                                case 'f':       ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, parse_protocol_family ));
     406                                                        break;
     407                                case 'h':       print_help();
     408                                                        return EOK;
     409                                                        break;
     410                                case 'm':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 0 ));
     411                                                        break;
     412                                case 'n':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 0 ));
     413                                                        break;
     414                                case 'p':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
     415                                                        port = ( uint16_t ) value;
     416                                                        break;
     417                                case 's':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
     418                                                        size = (value >= 0 ) ? ( size_t ) value : 0;
     419                                                        break;
     420                                case 't':       ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, parse_socket_type ));
     421                                                        type = ( sock_type_t ) value;
     422                                                        break;
     423                                case 'v':       verbose = 1;
     424                                                        break;
     425                                case '-':       if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
     426                                                                ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, parse_protocol_family ));
     427                                                        }else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
     428                                                                print_help();
     429                                                                return EOK;
     430                                                        }else if( str_lcmp( argv[ index ] + 2, "messages=", 6 ) == 0 ){
     431                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 8 ));
     432                                                        }else if( str_lcmp( argv[ index ] + 2, "sockets=", 6 ) == 0 ){
     433                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 8 ));
     434                                                        }else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
     435                                                                ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
     436                                                                port = ( uint16_t ) value;
     437                                                        }else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
     438                                                                ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, parse_socket_type ));
     439                                                                type = ( sock_type_t ) value;
     440                                                        }else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
     441                                                                verbose = 1;
     442                                                        }else{
     443                                                                print_unrecognized( index, argv[ index ] + 2 );
     444                                                                print_help();
     445                                                                return EINVAL;
     446                                                        }
     447                                                        break;
     448                                default:
     449                                        print_unrecognized( index, argv[ index ] + 1 );
     450                                        print_help();
     451                                        return EINVAL;
     452                        }
     453                }else{
     454                        print_unrecognized( index, argv[ index ] );
     455                        print_help();
     456                        return EINVAL;
     457                }
     458        }
     459
     460        bzero( address_data, max_length );
     461        switch( family ){
     462                case PF_INET:
     463                        address_in->sin_family = AF_INET;
     464                        address_in->sin_port = htons( port );
     465                        address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
     466                        addrlen = sizeof( struct sockaddr_in );
     467                        break;
     468                case PF_INET6:
     469                        address_in6->sin6_family = AF_INET6;
     470                        address_in6->sin6_port = htons( port );
     471                        address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
     472                        addrlen = sizeof( struct sockaddr_in6 );
     473                        break;
     474                default:
     475                        fprintf( stderr, "Address family is not supported\n" );
     476                        return EAFNOSUPPORT;
     477        }
     478
     479        if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
     480                fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
     481                return ERROR_CODE;
     482        }
     483
     484        if( size <= 0 ){
     485                fprintf( stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size );
     486                size = 1024;
     487        }
     488        // size plus terminating null (\0)
     489        data = ( char * ) malloc( size + 1 );
     490        if( ! data ){
     491                fprintf( stderr, "Failed to allocate data buffer.\n" );
     492                return ENOMEM;
     493        }
     494        refresh_data( data, size );
     495
     496        if( sockets <= 0 ){
     497                fprintf( stderr, "Socket count too small (%d). Using 2 instead.\n", sockets );
     498                sockets = 2;
     499        }
     500        // count plus terminating null (\0)
     501        socket_ids = ( int * ) malloc( sizeof( int ) * ( sockets + 1 ));
     502        if( ! socket_ids ){
     503                fprintf( stderr, "Failed to allocate receive buffer.\n" );
     504                return ENOMEM;
     505        }
     506        socket_ids[ sockets ] = NULL;
     507
     508        if( verbose ) printf( "Starting tests\n" );
     509
     510        if( verbose ) printf( "1 socket, 1 message\n" );
     511
     512        if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
     513                fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
     514                return ERROR_CODE;
     515        }
     516
     517        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
     518        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
     519        if( verbose ) printf( "\tOK\n" );
     520
     521        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
     522        if( type == SOCK_STREAM ){
     523                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
     524        }
     525        ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
     526        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
     527        if( verbose ) printf( "\tOK\n" );
     528
     529        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
     530        if( type == SOCK_STREAM ){
     531                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
     532        }
     533        ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, 1 ));
     534        ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
     535        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
     536        if( verbose ) printf( "\tOK\n" );
     537
     538        if( verbose ) printf( "1 socket, %d messages\n", messages );
     539
     540        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
     541        if( type == SOCK_STREAM ){
     542                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
     543        }
     544        ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
     545        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
     546        if( verbose ) printf( "\tOK\n" );
     547
     548        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
     549        if( type == SOCK_STREAM ){
     550                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
     551        }
     552        ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, messages ));
     553        ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
     554        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
     555        if( verbose ) printf( "\tOK\n" );
     556
     557        if( verbose ) printf( "%d sockets, 1 message\n", sockets );
     558
     559        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
     560        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
     561        if( verbose ) printf( "\tOK\n" );
     562
     563        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
     564        if( type == SOCK_STREAM ){
     565                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
     566        }
     567        ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
     568        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
     569        if( verbose ) printf( "\tOK\n" );
     570
     571        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
     572        if( type == SOCK_STREAM ){
     573                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
     574        }
     575        ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, 1 ));
     576        ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
     577        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
     578        if( verbose ) printf( "\tOK\n" );
     579
     580        if( verbose ) printf( "%d sockets, %d messages\n", sockets, messages );
     581
     582        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
     583        if( type == SOCK_STREAM ){
     584                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
     585        }
     586        ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
     587        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
     588        if( verbose ) printf( "\tOK\n" );
     589
     590        ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
     591        if( type == SOCK_STREAM ){
     592                ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
     593        }
     594        ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, messages ));
     595        ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
     596        ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
     597
     598        if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
     599                fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
     600                return ERROR_CODE;
     601        }
     602
     603        if( verbose ) printf( "\tOK\n" );
     604
     605        printf( "Tested in %d microseconds\n", tv_sub( & time_after, & time_before ));
     606
     607        if( verbose ) printf( "Exiting\n" );
     608
     609        return EOK;
    422610}
    423611
Note: See TracChangeset for help on using the changeset viewer.