Ignore:
Timestamp:
2010-03-09T22:23:18Z (14 years ago)
Author:
Lukas Mejdrech <lukasmejdrech@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
9f2ea28
Parents:
a8a13d0
Message:
  • net app command line argument checks, * code reorganization
File:
1 edited

Legend:

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

    ra8a13d0 r3be62bc  
    4848#include "../../err.h"
    4949
     50#include "../nettest.h"
    5051#include "../parse.h"
    5152#include "../print_error.h"
     
    6970/** Prints the application help.
    7071 */
    71 void 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  */
    78 int 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  */
    85 int parse_socket_type(const char * name);
     72void nettest1_print_help(void);
    8673
    8774/** Refreshes the data.
     
    9077 *  @param[in] size The data block size in bytes.
    9178 */
    92 void 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  */
    103 int 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  */
    112 int 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  */
    123 int 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  */
    137 int 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  */
    151 int 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  */
    167 int 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  */
    173 void print_mark(int index);
    174 
    175 void print_help(void){
    176         printf(
    177                 "Network Networking test 1 aplication - sockets\n" \
    178                 "Usage: echo [options] numeric_address\n" \
    179                 "Where options are:\n" \
    180                 "-f protocol_family | --family=protocol_family\n" \
    181                 "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
    182                 "\n" \
    183                 "-h | --help\n" \
    184                 "\tShow this application help.\n"
    185                 "\n" \
    186                 "-m count | --messages=count\n" \
    187                 "\tThe number of messages to send and receive per socket. The default is 10.\n" \
    188                 "\n" \
    189                 "-n sockets | --sockets=count\n" \
    190                 "\tThe number of sockets to use. The default is 10.\n" \
    191                 "\n" \
    192                 "-p port_number | --port=port_number\n" \
    193                 "\tThe port number the application should send messages to. The default is 7.\n" \
    194                 "\n" \
    195                 "-s packet_size | --size=packet_size\n" \
    196                 "\tThe packet data size the application sends. The default is 28 bytes.\n" \
    197                 "\n" \
    198                 "-v | --verbose\n" \
    199                 "\tShow all output messages.\n"
    200         );
    201 }
    202 
    203 int 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 
    212 int 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 
    221 void refresh_data(char * data, size_t size){
    222         size_t length;
    223 
    224         // fill the data
    225         length = 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 
    234 int 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 
    255 int 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 
    277 int 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 
    298 int 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 
    323 int 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 
    348 int 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 
    380 void print_mark(int index){
    381         if((index + 1) % 10){
    382                 printf("*");
    383         }else{
    384                 printf("|");
    385         }
    386         fflush(stdout);
    387 }
     79void nettest1_refresh_data(char * data, size_t size);
    38880
    38981int main(int argc, char * argv[]){
     
    39284        size_t size                     = 27;
    39385        int verbose                     = 0;
    394         sock_type_t type                        = SOCK_DGRAM;
     86        sock_type_t type        = SOCK_DGRAM;
    39587        int sockets                     = 10;
    39688        int messages            = 10;
    39789        int family                      = PF_INET;
    398         uint16_t port                   = 7;
    399 
    400         socklen_t max_length            = sizeof(struct sockaddr_in6);
     90        uint16_t port           = 7;
     91
     92        socklen_t max_length                            = sizeof(struct sockaddr_in6);
    40193        uint8_t address_data[max_length];
    402         struct sockaddr * address               = (struct sockaddr *) address_data;
     94        struct sockaddr * address                       = (struct sockaddr *) address_data;
    40395        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
    40496        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
    40597        socklen_t addrlen;
    406 //      char                            address_string[INET6_ADDRSTRLEN];
     98//      char address_string[INET6_ADDRSTRLEN];
    40799        uint8_t * address_start;
    408100
    409101        int * socket_ids;
    410         char *                          data;
     102        char * data;
    411103        int value;
    412104        int index;
     
    414106        struct timeval time_after;
    415107
     108        // print the program label
    416109        printf("Task %d - ", task_get_id());
    417110        printf("%s\n", NAME);
    418111
    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){
     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 ('-')
    425116                if(argv[index][0] == '-'){
    426117                        switch(argv[index][1]){
     118                                // short options with only one letter
    427119                                case 'f':
    428120                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    429121                                        break;
    430122                                case 'h':
    431                                         print_help();
     123                                        nettest1_print_help();
    432124                                        return EOK;
    433125                                        break;
     
    453145                                        verbose = 1;
    454146                                        break;
     147                                // long options with the double minus sign ('-')
    455148                                case '-':
    456149                                        if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    457150                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    458151                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    459                                                 print_help();
     152                                                nettest1_print_help();
    460153                                                return EOK;
    461154                                        }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
     
    473166                                        }else{
    474167                                                print_unrecognized(index, argv[index] + 2);
    475                                                 print_help();
     168                                                nettest1_print_help();
    476169                                                return EINVAL;
    477170                                        }
     
    479172                                default:
    480173                                        print_unrecognized(index, argv[index] + 1);
    481                                         print_help();
     174                                        nettest1_print_help();
    482175                                        return EINVAL;
    483176                        }
    484177                }else{
    485178                        print_unrecognized(index, argv[index]);
    486                         print_help();
     179                        nettest1_print_help();
    487180                        return EINVAL;
    488181                }
    489182        }
    490183
     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
    491192        bzero(address_data, max_length);
    492193        switch(family){
     
    508209        }
    509210
     211        // parse the last argument which should contain the address
    510212        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    511213                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     
    513215        }
    514216
     217        // check the buffer size
    515218        if(size <= 0){
    516219                fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
    517220                size = 1024;
    518221        }
    519         // size plus terminating null (\0)
     222
     223        // prepare the buffer
     224        // size plus the terminating null (\0)
    520225        data = (char *) malloc(size + 1);
    521226        if(! data){
     
    523228                return ENOMEM;
    524229        }
    525         refresh_data(data, size);
    526 
     230        nettest1_refresh_data(data, size);
     231
     232        // check the socket count
    527233        if(sockets <= 0){
    528234                fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
    529235                sockets = 2;
    530236        }
    531         // count plus terminating null (\0)
     237
     238        // prepare the socket buffer
     239        // count plus the terminating null (\0)
    532240        socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
    533241        if(! socket_ids){
     
    673381}
    674382
     383void nettest1_print_help(void){
     384        printf(
     385                "Network Networking test 1 aplication - sockets\n" \
     386                "Usage: echo [options] numeric_address\n" \
     387                "Where options are:\n" \
     388                "-f protocol_family | --family=protocol_family\n" \
     389                "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
     390                "\n" \
     391                "-h | --help\n" \
     392                "\tShow this application help.\n"
     393                "\n" \
     394                "-m count | --messages=count\n" \
     395                "\tThe number of messages to send and receive per socket. The default is 10.\n" \
     396                "\n" \
     397                "-n sockets | --sockets=count\n" \
     398                "\tThe number of sockets to use. The default is 10.\n" \
     399                "\n" \
     400                "-p port_number | --port=port_number\n" \
     401                "\tThe port number the application should send messages to. The default is 7.\n" \
     402                "\n" \
     403                "-s packet_size | --size=packet_size\n" \
     404                "\tThe packet data size the application sends. The default is 28 bytes.\n" \
     405                "\n" \
     406                "-v | --verbose\n" \
     407                "\tShow all output messages.\n"
     408        );
     409}
     410
     411void nettest1_refresh_data(char * data, size_t size){
     412        size_t length;
     413
     414        // fill the data
     415        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';
     422}
     423
    675424/** @}
    676425 */
Note: See TracChangeset for help on using the changeset viewer.