Ignore:
Timestamp:
2010-03-10T05:46:54Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5782081
Parents:
71b00dcc (diff), b48ebd19 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~lukasmejdrech/helenos/network.

File:
1 edited

Legend:

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

    r71b00dcc r60ab6c3  
    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 nettest2_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 2 aplication - UDP transfer\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 29 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(NETTEST2_TEXT) - 1){
    227                 memcpy(data + length, NETTEST2_TEXT, sizeof(NETTEST2_TEXT) - 1);
    228                 length += sizeof(NETTEST2_TEXT) - 1;
    229         }
    230         memcpy(data + length, NETTEST2_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 nettest2_refresh_data(char * data, size_t size);
    38880
    38981int main(int argc, char * argv[]){
     
    39284        size_t size                     = 28;
    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;
     
    417109        printf("%s\n", NAME);
    418110
    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){
     111        // parse the command line arguments
     112        // stop before the last argument if it does not start with the minus sign ('-')
     113        for(index = 1; (index < argc - 1) || ((index == argc - 1) && (argv[index][0] == '-')); ++ index){
     114                // options should start with the minus sign ('-')
    425115                if(argv[index][0] == '-'){
    426116                        switch(argv[index][1]){
     117                                // short options with only one letter
    427118                                case 'f':
    428119                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
    429120                                        break;
    430121                                case 'h':
    431                                         print_help();
     122                                        nettest2_print_help();
    432123                                        return EOK;
    433124                                        break;
     
    453144                                        verbose = 1;
    454145                                        break;
     146                                // long options with the double minus sign ('-')
    455147                                case '-':
    456148                                        if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
    457149                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
    458150                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
    459                                                 print_help();
     151                                                nettest2_print_help();
    460152                                                return EOK;
    461153                                        }else if(str_lcmp(argv[index] + 2, "messages=", 6) == 0){
     
    473165                                        }else{
    474166                                                print_unrecognized(index, argv[index] + 2);
    475                                                 print_help();
     167                                                nettest2_print_help();
    476168                                                return EINVAL;
    477169                                        }
     
    479171                                default:
    480172                                        print_unrecognized(index, argv[index] + 1);
    481                                         print_help();
     173                                        nettest2_print_help();
    482174                                        return EINVAL;
    483175                        }
    484176                }else{
    485177                        print_unrecognized(index, argv[index]);
    486                         print_help();
     178                        nettest2_print_help();
    487179                        return EINVAL;
    488180                }
    489181        }
    490182
     183        // if not before the last argument containing the address
     184        if(index >= argc){
     185                printf("Command line error: missing address\n");
     186                nettest2_print_help();
     187                return EINVAL;
     188        }
     189
     190        // prepare the address buffer
    491191        bzero(address_data, max_length);
    492192        switch(family){
     
    508208        }
    509209
     210        // parse the last argument which should contain the address
    510211        if(ERROR_OCCURRED(inet_pton(family, argv[argc - 1], address_start))){
    511212                fprintf(stderr, "Address parse error %d\n", ERROR_CODE);
     
    513214        }
    514215
     216        // check the buffer size
    515217        if(size <= 0){
    516218                fprintf(stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size);
    517219                size = 1024;
    518220        }
     221
     222        // prepare the buffer
    519223        // size plus terminating null (\0)
    520224        data = (char *) malloc(size + 1);
     
    523227                return ENOMEM;
    524228        }
    525         refresh_data(data, size);
    526 
     229        nettest2_refresh_data(data, size);
     230
     231        // check the socket count
    527232        if(sockets <= 0){
    528233                fprintf(stderr, "Socket count too small (%d). Using 2 instead.\n", sockets);
    529234                sockets = 2;
    530235        }
    531         // count plus terminating null (\0)
     236
     237        // prepare the socket buffer
     238        // count plus the terminating null (\0)
    532239        socket_ids = (int *) malloc(sizeof(int) * (sockets + 1));
    533240        if(! socket_ids){
     
    597304}
    598305
     306void nettest2_print_help(void){
     307        printf(
     308                "Network Networking test 2 aplication - UDP transfer\n" \
     309                "Usage: echo [options] numeric_address\n" \
     310                "Where options are:\n" \
     311                "-f protocol_family | --family=protocol_family\n" \
     312                "\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
     313                "\n" \
     314                "-h | --help\n" \
     315                "\tShow this application help.\n"
     316                "\n" \
     317                "-m count | --messages=count\n" \
     318                "\tThe number of messages to send and receive per socket. The default is 10.\n" \
     319                "\n" \
     320                "-n sockets | --sockets=count\n" \
     321                "\tThe number of sockets to use. The default is 10.\n" \
     322                "\n" \
     323                "-p port_number | --port=port_number\n" \
     324                "\tThe port number the application should send messages to. The default is 7.\n" \
     325                "\n" \
     326                "-s packet_size | --size=packet_size\n" \
     327                "\tThe packet data size the application sends. The default is 29 bytes.\n" \
     328                "\n" \
     329                "-v | --verbose\n" \
     330                "\tShow all output messages.\n"
     331        );
     332}
     333
     334void nettest2_refresh_data(char * data, size_t size){
     335        size_t length;
     336
     337        // fill the data
     338        length = 0;
     339        while(size > length + sizeof(NETTEST2_TEXT) - 1){
     340                memcpy(data + length, NETTEST2_TEXT, sizeof(NETTEST2_TEXT) - 1);
     341                length += sizeof(NETTEST2_TEXT) - 1;
     342        }
     343        memcpy(data + length, NETTEST2_TEXT, size - length);
     344        data[size] = '\0';
     345}
     346
    599347/** @}
    600348 */
Note: See TracChangeset for help on using the changeset viewer.