Ignore:
File:
1 edited

Legend:

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

    r3be62bc raadf01e  
    4848#include "../../err.h"
    4949
    50 #include "../nettest.h"
    5150#include "../parse.h"
    5251#include "../print_error.h"
     
    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){
     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){
    412222        size_t length;
    413223
     
    422232}
    423233
     234int sockets_create(int verbose, int * socket_ids, int sockets, int family, sock_type_t type){
     235        int index;
     236
     237        if(verbose){
     238                printf("Create\t");
     239        }
     240        fflush(stdout);
     241        for(index = 0; index < sockets; ++ index){
     242                socket_ids[index] = socket(family, type, 0);
     243                if(socket_ids[index] < 0){
     244                        printf("Socket %d (%d) error:\n", index, socket_ids[index]);
     245                        socket_print_error(stderr, socket_ids[index], "Socket create: ", "\n");
     246                        return socket_ids[index];
     247                }
     248                if(verbose){
     249                        print_mark(index);
     250                }
     251        }
     252        return EOK;
     253}
     254
     255int sockets_close(int verbose, int * socket_ids, int sockets){
     256        ERROR_DECLARE;
     257
     258        int index;
     259
     260        if(verbose){
     261                printf("\tClose\t");
     262        }
     263        fflush(stdout);
     264        for(index = 0; index < sockets; ++ index){
     265                if(ERROR_OCCURRED(closesocket(socket_ids[index]))){
     266                        printf("Socket %d (%d) error:\n", index, socket_ids[index]);
     267                        socket_print_error(stderr, ERROR_CODE, "Socket close: ", "\n");
     268                        return ERROR_CODE;
     269                }
     270                if(verbose){
     271                        print_mark(index);
     272                }
     273        }
     274        return EOK;
     275}
     276
     277int sockets_connect(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen){
     278        ERROR_DECLARE;
     279
     280        int index;
     281
     282        if(verbose){
     283                printf("\tConnect\t");
     284        }
     285        fflush(stdout);
     286        for(index = 0; index < sockets; ++ index){
     287                if(ERROR_OCCURRED(connect(socket_ids[index], address, addrlen))){
     288                        socket_print_error(stderr, ERROR_CODE, "Socket connect: ", "\n");
     289                        return ERROR_CODE;
     290                }
     291                if(verbose){
     292                        print_mark(index);
     293                }
     294        }
     295        return EOK;
     296}
     297
     298int sockets_sendto(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages){
     299        ERROR_DECLARE;
     300
     301        int index;
     302        int message;
     303
     304        if(verbose){
     305                printf("\tSendto\t");
     306        }
     307        fflush(stdout);
     308        for(index = 0; index < sockets; ++ index){
     309                for(message = 0; message < messages; ++ message){
     310                        if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, addrlen))){
     311                                printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
     312                                socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
     313                                return ERROR_CODE;
     314                        }
     315                }
     316                if(verbose){
     317                        print_mark(index);
     318                }
     319        }
     320        return EOK;
     321}
     322
     323int sockets_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
     324        int value;
     325        int index;
     326        int message;
     327
     328        if(verbose){
     329                printf("\tRecvfrom\t");
     330        }
     331        fflush(stdout);
     332        for(index = 0; index < sockets; ++ index){
     333                for(message = 0; message < messages; ++ message){
     334                        value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
     335                        if(value < 0){
     336                                printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
     337                                socket_print_error(stderr, value, "Socket receive: ", "\n");
     338                                return value;
     339                        }
     340                }
     341                if(verbose){
     342                        print_mark(index);
     343                }
     344        }
     345        return EOK;
     346}
     347
     348int sockets_sendto_recvfrom(int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages){
     349        ERROR_DECLARE;
     350
     351        int value;
     352        int index;
     353        int message;
     354
     355        if(verbose){
     356                printf("\tSendto and recvfrom\t");
     357        }
     358        fflush(stdout);
     359        for(index = 0; index < sockets; ++ index){
     360                for(message = 0; message < messages; ++ message){
     361                        if(ERROR_OCCURRED(sendto(socket_ids[index], data, size, 0, address, * addrlen))){
     362                                printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
     363                                socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
     364                                return ERROR_CODE;
     365                        }
     366                        value = recvfrom(socket_ids[index], data, size, 0, address, addrlen);
     367                        if(value < 0){
     368                                printf("Socket %d (%d), message %d error:\n", index, socket_ids[index], message);
     369                                socket_print_error(stderr, value, "Socket receive: ", "\n");
     370                                return value;
     371                        }
     372                }
     373                if(verbose){
     374                        print_mark(index);
     375                }
     376        }
     377        return EOK;
     378}
     379
     380void print_mark(int index){
     381        if((index + 1) % 10){
     382                printf("*");
     383        }else{
     384                printf("|");
     385        }
     386        fflush(stdout);
     387}
     388
     389int main(int argc, char * argv[]){
     390        ERROR_DECLARE;
     391
     392        size_t size                     = 27;
     393        int verbose                     = 0;
     394        sock_type_t type                        = SOCK_DGRAM;
     395        int sockets                     = 10;
     396        int messages            = 10;
     397        int family                      = PF_INET;
     398        uint16_t port                   = 7;
     399
     400        socklen_t max_length            = sizeof(struct sockaddr_in6);
     401        uint8_t address_data[max_length];
     402        struct sockaddr * address               = (struct sockaddr *) address_data;
     403        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
     404        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
     405        socklen_t addrlen;
     406//      char                            address_string[INET6_ADDRSTRLEN];
     407        uint8_t * address_start;
     408
     409        int * socket_ids;
     410        char *                          data;
     411        int value;
     412        int index;
     413        struct timeval time_before;
     414        struct timeval time_after;
     415
     416        printf("Task %d - ", task_get_id());
     417        printf("%s\n", NAME);
     418
     419        if(argc <= 1){
     420                print_help();
     421                return EINVAL;
     422        }
     423
     424        for(index = 1; (index < argc - 1) || ((index == argc) && (argv[index][0] == '-')); ++ index){
     425                if(argv[index][0] == '-'){
     426                        switch(argv[index][1]){
     427                                case 'f':
     428                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
     429                                        break;
     430                                case 'h':
     431                                        print_help();
     432                                        return EOK;
     433                                        break;
     434                                case 'm':
     435                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 0));
     436                                        break;
     437                                case 'n':
     438                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 0));
     439                                        break;
     440                                case 'p':
     441                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 0));
     442                                        port = (uint16_t) value;
     443                                        break;
     444                                case 's':
     445                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "packet size", 0));
     446                                        size = (value >= 0) ? (size_t) value : 0;
     447                                        break;
     448                                case 't':
     449                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, parse_socket_type));
     450                                        type = (sock_type_t) value;
     451                                        break;
     452                                case 'v':
     453                                        verbose = 1;
     454                                        break;
     455                                case '-':
     456                                        if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
     457                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
     458                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
     459                                                print_help();
     460                                                return EOK;
     461                                        }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
     462                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &messages, "message count", 8));
     463                                        }else if(str_lcmp(argv[index] + 2, "sockets=", 6) == 0){
     464                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &sockets, "socket count", 8));
     465                                        }else if(str_lcmp(argv[index] + 2, "port=", 5) == 0){
     466                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 7));
     467                                                port = (uint16_t) value;
     468                                        }else if(str_lcmp(argv[index] + 2, "type=", 5) == 0){
     469                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, parse_socket_type));
     470                                                type = (sock_type_t) value;
     471                                        }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
     472                                                verbose = 1;
     473                                        }else{
     474                                                print_unrecognized(index, argv[index] + 2);
     475                                                print_help();
     476                                                return EINVAL;
     477                                        }
     478                                        break;
     479                                default:
     480                                        print_unrecognized(index, argv[index] + 1);
     481                                        print_help();
     482                                        return EINVAL;
     483                        }
     484                }else{
     485                        print_unrecognized(index, argv[index]);
     486                        print_help();
     487                        return EINVAL;
     488                }
     489        }
     490
     491        bzero(address_data, max_length);
     492        switch(family){
     493                case PF_INET:
     494                        address_in->sin_family = AF_INET;
     495                        address_in->sin_port = htons(port);
     496                        address_start = (uint8_t *) &address_in->sin_addr.s_addr;
     497                        addrlen = sizeof(struct sockaddr_in);
     498                        break;
     499                case PF_INET6:
     500                        address_in6->sin6_family = AF_INET6;
     501                        address_in6->sin6_port = htons(port);
     502                        address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
     503                        addrlen = sizeof(struct sockaddr_in6);
     504                        break;
     505                default:
     506                        fprintf(stderr, "Address family is not supported\n");
     507                        return EAFNOSUPPORT;
     508        }
     509
     510        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
     511                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     512                return ERROR_CODE;
     513        }
     514
     515        if(size <= 0){
     516                fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
     517                size = 1024;
     518        }
     519        // size plus terminating null (\0)
     520        data = (char *) malloc(size + 1);
     521        if(! data){
     522                fprintf(stderr, "Failed to allocate data buffer.\n");
     523                return ENOMEM;
     524        }
     525        refresh_data(data, size);
     526
     527        if(sockets <= 0){
     528                fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
     529                sockets = 2;
     530        }
     531        // count plus terminating null (\0)
     532        socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
     533        if(! socket_ids){
     534                fprintf(stderr, "Failed to allocate receive buffer.\n");
     535                return ENOMEM;
     536        }
     537        socket_ids[sockets] = NULL;
     538
     539        if(verbose){
     540                printf("Starting tests\n");
     541        }
     542
     543        if(verbose){
     544                printf("1 socket, 1 message\n");
     545        }
     546
     547        if(ERROR_OCCURRED(gettimeofday(&time_before, NULL))){
     548                fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
     549                return ERROR_CODE;
     550        }
     551
     552        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
     553        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
     554        if(verbose){
     555                printf("\tOK\n");
     556        }
     557
     558        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
     559        if(type == SOCK_STREAM){
     560                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
     561        }
     562        ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, 1));
     563        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
     564        if(verbose){
     565                printf("\tOK\n");
     566        }
     567
     568        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
     569        if(type == SOCK_STREAM){
     570                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
     571        }
     572        ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, 1, address, addrlen, data, size, 1));
     573        ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, 1));
     574        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
     575        if(verbose){
     576                printf("\tOK\n");
     577        }
     578
     579        if(verbose){
     580                printf("1 socket, %d messages\n", messages);
     581        }
     582
     583        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
     584        if(type == SOCK_STREAM){
     585                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
     586        }
     587        ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, messages));
     588        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
     589        if(verbose){
     590                printf("\tOK\n");
     591        }
     592
     593        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, 1, family, type));
     594        if(type == SOCK_STREAM){
     595                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, 1, address, addrlen));
     596        }
     597        ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, 1, address, addrlen, data, size, messages));
     598        ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, 1, address, &addrlen, data, size, messages));
     599        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, 1));
     600        if(verbose){
     601                printf("\tOK\n");
     602        }
     603
     604        if(verbose){
     605                printf("%d sockets, 1 message\n", sockets);
     606        }
     607
     608        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
     609        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
     610        if(verbose){
     611                printf("\tOK\n");
     612        }
     613
     614        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
     615        if(type == SOCK_STREAM){
     616                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
     617        }
     618        ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, 1));
     619        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
     620        if(verbose){
     621                printf("\tOK\n");
     622        }
     623
     624        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
     625        if(type == SOCK_STREAM){
     626                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
     627        }
     628        ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, 1));
     629        ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, 1));
     630        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
     631        if(verbose){
     632                printf("\tOK\n");
     633        }
     634
     635        if(verbose){
     636                printf("%d sockets, %d messages\n", sockets, messages);
     637        }
     638
     639        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
     640        if(type == SOCK_STREAM){
     641                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
     642        }
     643        ERROR_PROPAGATE(sockets_sendto_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
     644        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
     645        if(verbose){
     646                printf("\tOK\n");
     647        }
     648
     649        ERROR_PROPAGATE(sockets_create(verbose, socket_ids, sockets, family, type));
     650        if(type == SOCK_STREAM){
     651                ERROR_PROPAGATE(sockets_connect(verbose, socket_ids, sockets, address, addrlen));
     652        }
     653        ERROR_PROPAGATE(sockets_sendto(verbose, socket_ids, sockets, address, addrlen, data, size, messages));
     654        ERROR_PROPAGATE(sockets_recvfrom(verbose, socket_ids, sockets, address, &addrlen, data, size, messages));
     655        ERROR_PROPAGATE(sockets_close(verbose, socket_ids, sockets));
     656
     657        if(ERROR_OCCURRED(gettimeofday(&time_after, NULL))){
     658                fprintf(stderr, "Get time of day error %d\n", ERROR_CODE);
     659                return ERROR_CODE;
     660        }
     661
     662        if(verbose){
     663                printf("\tOK\n");
     664        }
     665
     666        printf("Tested in %d microseconds\n", tv_sub(&time_after, &time_before));
     667
     668        if(verbose){
     669                printf("Exiting\n");
     670        }
     671
     672        return EOK;
     673}
     674
    424675/** @}
    425676 */
Note: See TracChangeset for help on using the changeset viewer.