Changeset 858fc90 in mainline for uspace/srv/net/app/echo/echo.c


Ignore:
Timestamp:
2010-03-15T19:35:25Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6092b56e
Parents:
92307f1 (diff), 4684368 (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 bzr://bzr.helenos.org/head.

File:
1 edited

Legend:

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

    r92307f1 r858fc90  
    5555#define NAME    "Echo"
    5656
     57/** Prints the application help.
     58 */
     59void echo_print_help(void);
     60
    5761/** Module entry point.
    5862 *  Reads command line parameters and starts listenning.
     
    6165 *  @returns EOK on success.
    6266 */
    63 int             main( int argc, char * argv[] );
    64 
    65 /** Prints the application help.
    66  */
    67 void    echo_print_help( void );
    68 
    69 /** Translates the character string to the protocol family number.
    70  *  @param[in] name The protocol family name.
    71  *  @returns The corresponding protocol family number.
    72  *  @returns EPFNOSUPPORTED if the protocol family is not supported.
    73  */
    74 int             echo_parse_protocol_family( const char * name );
    75 
    76 /** Translates the character string to the socket type number.
    77  *  @param[in] name The socket type name.
    78  *  @returns The corresponding socket type number.
    79  *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
    80  */
    81 int             echo_parse_socket_type( const char * name );
    82 
    83 void echo_print_help( void ){
     67int main(int argc, char * argv[]);
     68
     69void echo_print_help(void){
    8470        printf(
    8571                "Network Echo aplication\n" \
     
    115101}
    116102
    117 int echo_parse_protocol_family( const char * name ){
    118         if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
    119                 return PF_INET;
    120         }else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
    121                 return PF_INET6;
    122         }
    123         return EPFNOSUPPORT;
    124 }
    125 
    126 int echo_parse_socket_type( const char * name ){
    127         if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
    128                 return SOCK_DGRAM;
    129         }else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
    130                 return SOCK_STREAM;
    131         }
    132         return ESOCKTNOSUPPORT;
    133 }
    134 
    135 int main( int argc, char * argv[] ){
     103int main(int argc, char * argv[]){
    136104        ERROR_DECLARE;
    137105
    138         size_t                          size                    = 1024;
    139         int                                     verbose                 = 0;
    140         char *                          reply                   = NULL;
    141         sock_type_t                     type                    = SOCK_DGRAM;
    142         int                                     count                   = -1;
    143         int                                     family                  = PF_INET;
    144         uint16_t                        port                    = 7;
    145         int                                     backlog                 = 3;
    146 
    147         socklen_t                       max_length              = sizeof( struct sockaddr_in6 );
    148         uint8_t                         address_data[ max_length ];
    149         struct sockaddr *               address         = ( struct sockaddr * ) address_data;
    150         struct sockaddr_in *    address_in              = ( struct sockaddr_in * ) address;
    151         struct sockaddr_in6 *   address_in6     = ( struct sockaddr_in6 * ) address;
    152         socklen_t                       addrlen;
    153         char                            address_string[ INET6_ADDRSTRLEN ];
    154         uint8_t *                       address_start;
    155         int                                     socket_id;
    156         int                                     listening_id;
    157         char *                          data;
    158         size_t                          length;
    159         int                                     index;
    160         size_t                          reply_length;
    161         int                                     value;
    162 
    163         printf( "Task %d - ", task_get_id());
    164         printf( "%s\n", NAME );
    165 
    166         for( index = 1; index < argc; ++ index ){
    167                 if( argv[ index ][ 0 ] == '-' ){
    168                         switch( argv[ index ][ 1 ] ){
    169                                 case 'b':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & backlog, "accepted sockets queue size", 0 ));
    170                                                         break;
    171                                 case 'c':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "message count", 0 ));
    172                                                         break;
    173                                 case 'f':       ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, echo_parse_protocol_family ));
    174                                                         break;
    175                                 case 'h':       echo_print_help();
    176                                                         return EOK;
    177                                                         break;
    178                                 case 'p':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
    179                                                         port = ( uint16_t ) value;
    180                                                         break;
    181                                 case 'r':       ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 0 ));
    182                                                         break;
    183                                 case 's':       ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "receive size", 0 ));
    184                                                         size = (value >= 0 ) ? ( size_t ) value : 0;
    185                                                         break;
    186                                 case 't':       ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, echo_parse_socket_type ));
    187                                                         type = ( sock_type_t ) value;
    188                                                         break;
    189                                 case 'v':       verbose = 1;
    190                                                         break;
    191                                 case '-':       if( str_lcmp( argv[ index ] + 2, "backlog=", 6 ) == 0 ){
    192                                                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & backlog, "accepted sockets queue size", 8 ));
    193                                                         }else if( str_lcmp( argv[ index ] + 2, "count=", 6 ) == 0 ){
    194                                                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "message count", 8 ));
    195                                                         }else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
    196                                                                 ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, echo_parse_protocol_family ));
    197                                                         }else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
    198                                                                 echo_print_help();
    199                                                                 return EOK;
    200                                                         }else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
    201                                                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
    202                                                                 port = ( uint16_t ) value;
    203                                                         }else if( str_lcmp( argv[ index ] + 2, "reply=", 6 ) == 0 ){
    204                                                                 ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 8 ));
    205                                                         }else if( str_lcmp( argv[ index ] + 2, "size=", 5 ) == 0 ){
    206                                                                 ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "receive size", 7 ));
    207                                                                 size = (value >= 0 ) ? ( size_t ) value : 0;
    208                                                         }else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
    209                                                                 ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, echo_parse_socket_type ));
    210                                                                 type = ( sock_type_t ) value;
    211                                                         }else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
    212                                                                 verbose = 1;
    213                                                         }else{
    214                                                                 print_unrecognized( index, argv[ index ] + 2 );
    215                                                                 echo_print_help();
    216                                                                 return EINVAL;
    217                                                         }
    218                                                         break;
     106        size_t size                     = 1024;
     107        int verbose                     = 0;
     108        char * reply            = NULL;
     109        sock_type_t type        = SOCK_DGRAM;
     110        int count                       = -1;
     111        int family                      = PF_INET;
     112        uint16_t port           = 7;
     113        int backlog                     = 3;
     114
     115        socklen_t max_length                            = sizeof(struct sockaddr_in6);
     116        uint8_t address_data[max_length];
     117        struct sockaddr * address                       = (struct sockaddr *) address_data;
     118        struct sockaddr_in * address_in         = (struct sockaddr_in *) address;
     119        struct sockaddr_in6 * address_in6       = (struct sockaddr_in6 *) address;
     120        socklen_t addrlen;
     121        char address_string[INET6_ADDRSTRLEN];
     122        uint8_t * address_start;
     123        int socket_id;
     124        int listening_id;
     125        char * data;
     126        size_t length;
     127        int index;
     128        size_t reply_length;
     129        int value;
     130
     131        // print the program label
     132        printf("Task %d - ", task_get_id());
     133        printf("%s\n", NAME);
     134
     135        // parse the command line arguments
     136        for(index = 1; index < argc; ++ index){
     137                if(argv[index][0] == '-'){
     138                        switch(argv[index][1]){
     139                                case 'b':
     140                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &backlog, "accepted sockets queue size", 0));
     141                                        break;
     142                                case 'c':
     143                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "message count", 0));
     144                                        break;
     145                                case 'f':
     146                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 0, parse_protocol_family));
     147                                        break;
     148                                case 'h':
     149                                        echo_print_help();
     150                                        return EOK;
     151                                        break;
     152                                case 'p':
     153                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 0));
     154                                        port = (uint16_t) value;
     155                                        break;
     156                                case 'r':
     157                                        ERROR_PROPAGATE(parse_parameter_string(argc, argv, &index, &reply, "reply string", 0));
     158                                        break;
     159                                case 's':
     160                                        ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "receive size", 0));
     161                                        size = (value >= 0) ? (size_t) value : 0;
     162                                        break;
     163                                case 't':
     164                                        ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 0, parse_socket_type));
     165                                        type = (sock_type_t) value;
     166                                        break;
     167                                case 'v':
     168                                        verbose = 1;
     169                                        break;
     170                                // long options with the double minus sign ('-')
     171                                case '-':
     172                                        if(str_lcmp(argv[index] + 2, "backlog=", 6) == 0){
     173                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &backlog, "accepted sockets queue size", 8));
     174                                        }else if(str_lcmp(argv[index] + 2, "count=", 6) == 0){
     175                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &count, "message count", 8));
     176                                        }else if(str_lcmp(argv[index] + 2, "family=", 7) == 0){
     177                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &family, "protocol family", 9, parse_protocol_family));
     178                                        }else if(str_lcmp(argv[index] + 2, "help", 5) == 0){
     179                                                echo_print_help();
     180                                                return EOK;
     181                                        }else if(str_lcmp(argv[index] + 2, "port=", 5) == 0){
     182                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "port number", 7));
     183                                                port = (uint16_t) value;
     184                                        }else if(str_lcmp(argv[index] + 2, "reply=", 6) == 0){
     185                                                ERROR_PROPAGATE(parse_parameter_string(argc, argv, &index, &reply, "reply string", 8));
     186                                        }else if(str_lcmp(argv[index] + 2, "size=", 5) == 0){
     187                                                ERROR_PROPAGATE(parse_parameter_int(argc, argv, &index, &value, "receive size", 7));
     188                                                size = (value >= 0) ? (size_t) value : 0;
     189                                        }else if(str_lcmp(argv[index] + 2, "type=", 5) == 0){
     190                                                ERROR_PROPAGATE(parse_parameter_name_int(argc, argv, &index, &value, "socket type", 7, parse_socket_type));
     191                                                type = (sock_type_t) value;
     192                                        }else if(str_lcmp(argv[index] + 2, "verbose", 8) == 0){
     193                                                verbose = 1;
     194                                        }else{
     195                                                print_unrecognized(index, argv[index] + 2);
     196                                                echo_print_help();
     197                                                return EINVAL;
     198                                        }
     199                                        break;
    219200                                default:
    220                                         print_unrecognized( index, argv[ index ] + 1 );
     201                                        print_unrecognized(index, argv[index] + 1);
    221202                                        echo_print_help();
    222203                                        return EINVAL;
    223204                        }
    224205                }else{
    225                         print_unrecognized( index, argv[ index ] );
     206                        print_unrecognized(index, argv[index]);
    226207                        echo_print_help();
    227208                        return EINVAL;
     
    229210        }
    230211
    231         if( size <= 0 ){
    232                 fprintf( stderr, "Receive size too small (%d). Using 1024 bytes instead.\n", size );
     212        // check the buffer size
     213        if(size <= 0){
     214                fprintf(stderr, "Receive size too small (%d). Using 1024 bytes instead.\n", size);
    233215                size = 1024;
    234216        }
    235         // size plus terminating null (\0)
    236         data = ( char * ) malloc( size + 1 );
    237         if( ! data ){
    238                 fprintf( stderr, "Failed to allocate receive buffer.\n" );
     217        // size plus the terminating null (\0)
     218        data = (char *) malloc(size + 1);
     219        if(! data){
     220                fprintf(stderr, "Failed to allocate receive buffer.\n");
    239221                return ENOMEM;
    240222        }
    241223
    242         reply_length = reply ? str_length( reply ) : 0;
    243 
    244         listening_id = socket( family, type, 0 );
    245         if( listening_id < 0 ){
    246                 socket_print_error( stderr, listening_id, "Socket create: ", "\n" );
    247                 return listening_id;
    248         }
    249 
    250         bzero( address_data, max_length );
    251         switch( family ){
     224        // set the reply size if set
     225        reply_length = reply ? str_length(reply) : 0;
     226
     227        // prepare the address buffer
     228        bzero(address_data, max_length);
     229        switch(family){
    252230                case PF_INET:
    253231                        address_in->sin_family = AF_INET;
    254                         address_in->sin_port = htons( port );
    255                         addrlen = sizeof( struct sockaddr_in );
     232                        address_in->sin_port = htons(port);
     233                        addrlen = sizeof(struct sockaddr_in);
    256234                        break;
    257235                case PF_INET6:
    258236                        address_in6->sin6_family = AF_INET6;
    259                         address_in6->sin6_port = htons( port );
    260                         addrlen = sizeof( struct sockaddr_in6 );
     237                        address_in6->sin6_port = htons(port);
     238                        addrlen = sizeof(struct sockaddr_in6);
    261239                        break;
    262240                default:
    263                         fprintf( stderr, "Protocol family is not supported\n" );
     241                        fprintf(stderr, "Protocol family is not supported\n");
    264242                        return EAFNOSUPPORT;
    265243        }
    266244
    267         listening_id = socket( family, type, 0 );
    268         if( listening_id < 0 ){
    269                 socket_print_error( stderr, listening_id, "Socket create: ", "\n" );
     245        // get a listening socket
     246        listening_id = socket(family, type, 0);
     247        if(listening_id < 0){
     248                socket_print_error(stderr, listening_id, "Socket create: ", "\n");
    270249                return listening_id;
    271250        }
    272251
    273         if( type == SOCK_STREAM ){
    274                 if( backlog <= 0 ){
    275                         fprintf( stderr, "Accepted sockets queue size too small (%d). Using 3 instead.\n", size );
     252        // if the stream socket is used
     253        if(type == SOCK_STREAM){
     254                // check the backlog
     255                if(backlog <= 0){
     256                        fprintf(stderr, "Accepted sockets queue size too small (%d). Using 3 instead.\n", size);
    276257                        backlog = 3;
    277258                }
    278                 if( ERROR_OCCURRED( listen( listening_id, backlog ))){
    279                         socket_print_error( stderr, ERROR_CODE, "Socket listen: ", "\n" );
     259                // set the backlog
     260                if(ERROR_OCCURRED(listen(listening_id, backlog))){
     261                        socket_print_error(stderr, ERROR_CODE, "Socket listen: ", "\n");
    280262                        return ERROR_CODE;
    281263                }
    282264        }
    283265
    284         if( ERROR_OCCURRED( bind( listening_id, address, addrlen ))){
    285                 socket_print_error( stderr, ERROR_CODE, "Socket bind: ", "\n" );
     266        // bind the listenning socket
     267        if(ERROR_OCCURRED(bind(listening_id, address, addrlen))){
     268                socket_print_error(stderr, ERROR_CODE, "Socket bind: ", "\n");
    286269                return ERROR_CODE;
    287270        }
    288271
    289         if( verbose ) printf( "Socket %d listenning at %d\n", listening_id, port );
     272        if(verbose){
     273                printf("Socket %d listenning at %d\n", listening_id, port);
     274        }
    290275
    291276        socket_id = listening_id;
    292277
    293         while( count ){
     278        // do count times
     279        // or indefinitely if set to a negative value
     280        while(count){
     281
    294282                addrlen = max_length;
    295                 if( type == SOCK_STREAM ){
    296                         socket_id = accept( listening_id, address, & addrlen );
    297                         if( socket_id <= 0 ){
    298                                 socket_print_error( stderr, socket_id, "Socket accept: ", "\n" );
     283                if(type == SOCK_STREAM){
     284                        // acceept a socket if the stream socket is used
     285                        socket_id = accept(listening_id, address, &addrlen);
     286                        if(socket_id <= 0){
     287                                socket_print_error(stderr, socket_id, "Socket accept: ", "\n");
    299288                        }else{
    300                                 if( verbose ) printf( "Socket %d accepted\n", socket_id );
    301                         }
    302                 }
    303                 if( socket_id > 0 ){
    304                         value = recvfrom( socket_id, data, size, 0, address, & addrlen );
    305                         if( value < 0 ){
    306                                 socket_print_error( stderr, value, "Socket receive: ", "\n" );
     289                                if(verbose){
     290                                        printf("Socket %d accepted\n", socket_id);
     291                                }
     292                        }
     293                }
     294
     295                // if the datagram socket is used or the stream socked was accepted
     296                if(socket_id > 0){
     297
     298                        // receive an echo request
     299                        value = recvfrom(socket_id, data, size, 0, address, &addrlen);
     300                        if(value < 0){
     301                                socket_print_error(stderr, value, "Socket receive: ", "\n");
    307302                        }else{
    308                                 length = ( size_t ) value;
    309                                 if( verbose ){
     303                                length = (size_t) value;
     304                                if(verbose){
     305                                        // print the header
     306
     307                                        // get the source port and prepare the address buffer
    310308                                        address_start = NULL;
    311                                         switch( address->sa_family ){
     309                                        switch(address->sa_family){
    312310                                                case AF_INET:
    313                                                         port = ntohs( address_in->sin_port );
    314                                                         address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
     311                                                        port = ntohs(address_in->sin_port);
     312                                                        address_start = (uint8_t *) &address_in->sin_addr.s_addr;
    315313                                                        break;
    316314                                                case AF_INET6:
    317                                                         port = ntohs( address_in6->sin6_port );
    318                                                         address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
     315                                                        port = ntohs(address_in6->sin6_port);
     316                                                        address_start = (uint8_t *) &address_in6->sin6_addr.s6_addr;
    319317                                                        break;
    320318                                                default:
    321                                                         fprintf( stderr, "Address family %d (0x%X) is not supported.\n", address->sa_family );
     319                                                        fprintf(stderr, "Address family %d (0x%X) is not supported.\n", address->sa_family);
    322320                                        }
    323                                         if( address_start ){
    324                                                 if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){
    325                                                         fprintf( stderr, "Received address error %d\n", ERROR_CODE );
     321                                        // parse the source address
     322                                        if(address_start){
     323                                                if(ERROR_OCCURRED(inet_ntop(address->sa_family, address_start, address_string, sizeof(address_string)))){
     324                                                        fprintf(stderr, "Received address error %d\n", ERROR_CODE);
    326325                                                }else{
    327                                                         data[ length ] = '\0';
    328                                                         printf( "Socket %d received %d bytes from %s:%d\n%s\n", socket_id, length, address_string, port, data );
     326                                                        data[length] = '\0';
     327                                                        printf("Socket %d received %d bytes from %s:%d\n%s\n", socket_id, length, address_string, port, data);
    329328                                                }
    330329                                        }
    331330                                }
    332                                 if( ERROR_OCCURRED( sendto( socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen ))){
    333                                         socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
     331
     332                                // answer the request either with the static reply or the original data
     333                                if(ERROR_OCCURRED(sendto(socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen))){
     334                                        socket_print_error(stderr, ERROR_CODE, "Socket send: ", "\n");
    334335                                }
    335                         }
    336                         if( type == SOCK_STREAM ){
    337                                 if( ERROR_OCCURRED( closesocket( socket_id ))){
    338                                         socket_print_error( stderr, ERROR_CODE, "Close socket: ", "\n" );
     336
     337                        }
     338
     339                        // close the accepted stream socket
     340                        if(type == SOCK_STREAM){
     341                                if(ERROR_OCCURRED(closesocket(socket_id))){
     342                                        socket_print_error(stderr, ERROR_CODE, "Close socket: ", "\n");
    339343                                }
    340344                        }
    341                 }
    342                 if( count > 0 ){
     345
     346                }
     347
     348                // decrease the count if positive
     349                if(count > 0){
    343350                        -- count;
    344                         if( verbose ) printf( "Waiting for next %d packet(s)\n", count );
    345                 }
    346         }
    347 
    348         if( verbose ) printf( "Closing the socket\n" );
    349 
    350         if( ERROR_OCCURRED( closesocket( listening_id ))){
    351                 socket_print_error( stderr, ERROR_CODE, "Close socket: ", "\n" );
     351                        if(verbose){
     352                                printf("Waiting for next %d packet(s)\n", count);
     353                        }
     354                }
     355        }
     356
     357        if(verbose){
     358                printf("Closing the socket\n");
     359        }
     360
     361        // close the listenning socket
     362        if(ERROR_OCCURRED(closesocket(listening_id))){
     363                socket_print_error(stderr, ERROR_CODE, "Close socket: ", "\n");
    352364                return ERROR_CODE;
    353365        }
    354366
    355         if( verbose ) printf( "Exiting\n" );
     367        if(verbose){
     368                printf("Exiting\n");
     369        }
    356370
    357371        return EOK;
Note: See TracChangeset for help on using the changeset viewer.