Changes in uspace/app/ping/ping.c [a62ceaf:0aa70f4] in mainline


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/ping/ping.c

    ra62ceaf r0aa70f4  
    3737#include <errno.h>
    3838#include <fibril_synch.h>
     39#include <net/socket_codes.h>
     40#include <inet/dnsr.h>
    3941#include <inet/addr.h>
    40 #include <inet/host.h>
    4142#include <inet/inetping.h>
    4243#include <io/console.h>
    43 #include <getopt.h>
    4444#include <stdio.h>
    4545#include <stdlib.h>
    46 #include <str.h>
    47 #include <str_error.h>
    4846#include <sys/types.h>
    4947
     
    5654#define PING_TIMEOUT (1000 * 1000)
    5755
    58 typedef enum {
    59         RECEIVED_NONE,
    60         RECEIVED_SUCCESS,
    61         RECEIVED_INTERRUPT
    62 } received_t;
    63 
    64 static received_t received;
    65 static FIBRIL_CONDVAR_INITIALIZE(received_cv);
    66 static FIBRIL_MUTEX_INITIALIZE(received_lock);
    67 
    68 static bool quit = false;
    69 static FIBRIL_CONDVAR_INITIALIZE(quit_cv);
    70 static FIBRIL_MUTEX_INITIALIZE(quit_lock);
    71 
    7256static int ping_ev_recv(inetping_sdu_t *);
     57
     58static bool done = false;
     59static FIBRIL_CONDVAR_INITIALIZE(done_cv);
     60static FIBRIL_MUTEX_INITIALIZE(done_lock);
    7361
    7462static inetping_ev_ops_t ev_ops = {
     
    7664};
    7765
    78 static inet_addr_t src_addr;
    79 static inet_addr_t dest_addr;
    80 
    81 static bool repeat_forever = false;
    82 static size_t repeat_count = 1;
    83 
    84 static const char *short_options = "46rn:";
     66static addr32_t src;
     67static addr32_t dest;
     68
     69static bool ping_repeat = false;
    8570
    8671static void print_syntax(void)
    8772{
    88         printf("Syntax: %s [<options>] <host>\n", NAME);
    89         printf("\t-n <count> Repeat the specified number of times\n");
    90         printf("\t-r         Repeat forever\n");
    91         printf("\t-4|-6      Use IPv4 or IPv6 destination host address\n");
    92 }
    93 
    94 static void ping_signal_received(received_t value)
    95 {
    96         fibril_mutex_lock(&received_lock);
    97         received = value;
    98         fibril_mutex_unlock(&received_lock);
    99         fibril_condvar_broadcast(&received_cv);
    100 }
    101 
    102 static void ping_signal_quit(void)
    103 {
    104         fibril_mutex_lock(&quit_lock);
    105         quit = true;
    106         fibril_mutex_unlock(&quit_lock);
    107         fibril_condvar_broadcast(&quit_cv);
     73        printf("syntax: " NAME " [-r] <host>\n");
     74}
     75
     76static void ping_signal_done(void)
     77{
     78        fibril_mutex_lock(&done_lock);
     79        done = true;
     80        fibril_mutex_unlock(&done_lock);
     81        fibril_condvar_broadcast(&done_cv);
    10882}
    10983
    11084static int ping_ev_recv(inetping_sdu_t *sdu)
    11185{
     86        inet_addr_t src_addr;
     87        inet_addr_set(sdu->src, &src_addr);
     88       
     89        inet_addr_t dest_addr;
     90        inet_addr_set(sdu->dest, &dest_addr);
     91       
    11292        char *asrc;
    11393        int rc = inet_addr_format(&src_addr, &asrc);
     
    125105            "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
    126106       
    127         ping_signal_received(RECEIVED_SUCCESS);
     107        if (!ping_repeat)
     108                ping_signal_done();
    128109       
    129110        free(asrc);
     
    135116{
    136117        inetping_sdu_t sdu;
    137        
    138         sdu.src = src_addr;
    139         sdu.dest = dest_addr;
     118        int rc;
     119
     120        sdu.src = src;
     121        sdu.dest = dest;
    140122        sdu.seq_no = seq_no;
    141123        sdu.data = (void *) "foo";
    142124        sdu.size = 3;
    143        
    144         int rc = inetping_send(&sdu);
    145         if (rc != EOK)
    146                 printf("Failed sending echo request: %s (%d).\n",
    147                     str_error(rc), rc);
    148        
    149         return rc;
     125
     126        rc = inetping_send(&sdu);
     127        if (rc != EOK) {
     128                printf(NAME ": Failed sending echo request (%d).\n", rc);
     129                return rc;
     130        }
     131
     132        return EOK;
    150133}
    151134
     
    153136{
    154137        uint16_t seq_no = 0;
    155        
    156         while ((repeat_count--) || (repeat_forever)) {
    157                 fibril_mutex_lock(&received_lock);
    158                 received = RECEIVED_NONE;
    159                 fibril_mutex_unlock(&received_lock);
    160                
     138
     139        while (true) {
     140                fibril_mutex_lock(&done_lock);
     141                if (done) {
     142                        fibril_mutex_unlock(&done_lock);
     143                        return 0;
     144                }
     145                fibril_mutex_unlock(&done_lock);
     146
    161147                (void) ping_send(++seq_no);
    162                
    163                 fibril_mutex_lock(&received_lock);
    164                 int rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
    165                     PING_TIMEOUT);
    166                 received_t recv = received;
    167                 fibril_mutex_unlock(&received_lock);
    168                
    169                 if ((rc == ETIMEOUT) || (recv == RECEIVED_NONE))
    170                         printf("Echo request timed out (seq. no %u)\n", seq_no);
    171                
    172                 if (recv == RECEIVED_INTERRUPT)
    173                         break;
    174                
    175                 if ((repeat_count > 0) || (repeat_forever)) {
    176                         fibril_mutex_lock(&received_lock);
    177                         rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
    178                             PING_DELAY);
    179                         recv = received;
    180                         fibril_mutex_unlock(&received_lock);
    181                        
    182                         if (recv == RECEIVED_INTERRUPT)
    183                                 break;
    184                 }
    185         }
    186        
    187         ping_signal_quit();
     148                async_usleep(PING_DELAY);
     149        }
     150
    188151        return 0;
    189152}
     
    191154static int input_fibril(void *arg)
    192155{
    193         console_ctrl_t *con = console_init(stdin, stdout);
    194        
     156        console_ctrl_t *con;
     157        cons_event_t ev;
     158
     159        con = console_init(stdin, stdout);
     160        printf("[Press Ctrl-Q to quit]\n");
     161
    195162        while (true) {
    196                 cons_event_t ev;
    197163                if (!console_get_event(con, &ev))
    198164                        break;
    199                
    200                 if ((ev.type == CEV_KEY) && (ev.ev.key.type == KEY_PRESS) &&
    201                     ((ev.ev.key.mods & (KM_ALT | KM_SHIFT)) == 0) &&
    202                     ((ev.ev.key.mods & KM_CTRL) != 0)) {
     165
     166                if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS &&
     167                    (ev.ev.key.mods & (KM_ALT | KM_SHIFT)) ==
     168                    0 && (ev.ev.key.mods & KM_CTRL) != 0) {
    203169                        /* Ctrl+key */
    204170                        if (ev.ev.key.key == KC_Q) {
    205                                 ping_signal_received(RECEIVED_INTERRUPT);
    206                                 break;
     171                                ping_signal_done();
     172                                return 0;
    207173                        }
    208174                }
    209175        }
    210        
     176
    211177        return 0;
    212178}
     
    214180int main(int argc, char *argv[])
    215181{
     182        dnsr_hostinfo_t *hinfo = NULL;
    216183        char *asrc = NULL;
    217184        char *adest = NULL;
    218185        char *sdest = NULL;
    219         char *host;
    220         const char *errmsg;
    221         ip_ver_t ip_ver = ip_any;
    222        
    223         int rc = inetping_init(&ev_ops);
    224         if (rc != EOK) {
    225                 printf("Failed connecting to internet ping service: "
    226                     "%s (%d).\n", str_error(rc), rc);
    227                 goto error;
    228         }
    229        
    230         int c;
    231         while ((c = getopt(argc, argv, short_options)) != -1) {
    232                 switch (c) {
    233                 case 'r':
    234                         repeat_forever = true;
    235                         break;
    236                 case 'n':
    237                         rc = str_size_t(optarg, NULL, 10, true, &repeat_count);
    238                         if (rc != EOK) {
    239                                 printf("Invalid repeat count.\n");
    240                                 print_syntax();
    241                                 goto error;
    242                         }
    243                         break;
    244                 case '4':
    245                         ip_ver = ip_v4;
    246                         break;
    247                 case '6':
    248                         ip_ver = ip_v6;
    249                         break;
    250                 default:
    251                         printf("Unknown option passed.\n");
    252                         print_syntax();
     186        int rc;
     187        int argi;
     188
     189        rc = inetping_init(&ev_ops);
     190        if (rc != EOK) {
     191                printf(NAME ": Failed connecting to internet ping service "
     192                    "(%d).\n", rc);
     193                goto error;
     194        }
     195
     196        argi = 1;
     197        if (argi < argc && str_cmp(argv[argi], "-r") == 0) {
     198                ping_repeat = true;
     199                ++argi;
     200        } else {
     201                ping_repeat = false;
     202        }
     203
     204        if (argc - argi != 1) {
     205                print_syntax();
     206                goto error;
     207        }
     208
     209        /* Parse destination address */
     210        inet_addr_t dest_addr;
     211        rc = inet_addr_parse(argv[argi], &dest_addr);
     212        if (rc != EOK) {
     213                /* Try interpreting as a host name */
     214                rc = dnsr_name2host(argv[argi], &hinfo, AF_INET);
     215                if (rc != EOK) {
     216                        printf(NAME ": Error resolving host '%s'.\n", argv[argi]);
    253217                        goto error;
    254218                }
    255         }
    256        
    257         if (optind >= argc) {
    258                 printf("IP address or host name not supplied.\n");
    259                 print_syntax();
    260                 goto error;
    261         }
    262        
    263         host = argv[optind];
    264        
    265         /* Look up host */
    266         rc = inet_host_plookup_one(host, ip_ver, &dest_addr, NULL, &errmsg);
    267         if (rc != EOK) {
    268                 printf("Error resolving host '%s' (%s).\n", host, errmsg);
     219               
     220                dest_addr = hinfo->addr;
     221        }
     222       
     223        uint16_t af = inet_addr_get(&dest_addr, &dest, NULL);
     224        if (af != AF_INET) {
     225                printf(NAME ": Destination '%s' is not an IPv4 address.\n",
     226                    argv[argi]);
    269227                goto error;
    270228        }
    271229       
    272230        /* Determine source address */
    273         rc = inetping_get_srcaddr(&dest_addr, &src_addr);
    274         if (rc != EOK) {
    275                 printf("Failed determining source address.\n");
    276                 goto error;
    277         }
     231        rc = inetping_get_srcaddr(dest, &src);
     232        if (rc != EOK) {
     233                printf(NAME ": Failed determining source address.\n");
     234                goto error;
     235        }
     236       
     237        inet_addr_t src_addr;
     238        inet_addr_set(src, &src_addr);
    278239       
    279240        rc = inet_addr_format(&src_addr, &asrc);
    280241        if (rc != EOK) {
    281                 printf("Out of memory.\n");
     242                printf(NAME ": Out of memory.\n");
    282243                goto error;
    283244        }
     
    285246        rc = inet_addr_format(&dest_addr, &adest);
    286247        if (rc != EOK) {
    287                 printf("Out of memory.\n");
    288                 goto error;
    289         }
    290        
    291         rc = asprintf(&sdest, "%s (%s)", host, adest);
    292         if (rc < 0) {
    293                 printf("Out of memory.\n");
    294                 goto error;
    295         }
    296        
    297         printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n",
     248                printf(NAME ": Out of memory.\n");
     249                goto error;
     250        }
     251       
     252        if (hinfo != NULL) {
     253                rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest);
     254                if (rc < 0) {
     255                        printf(NAME ": Out of memory.\n");
     256                        goto error;
     257                }
     258        } else {
     259                sdest = adest;
     260                adest = NULL;
     261        }
     262
     263        printf("Sending ICMP echo request from %s to %s.\n",
    298264            asrc, sdest);
    299        
    300         fid_t fid = fibril_create(transmit_fibril, NULL);
    301         if (fid == 0) {
    302                 printf("Failed creating transmit fibril.\n");
    303                 goto error;
    304         }
    305        
    306         fibril_add_ready(fid);
    307        
    308         fid = fibril_create(input_fibril, NULL);
    309         if (fid == 0) {
    310                 printf("Failed creating input fibril.\n");
    311                 goto error;
    312         }
    313        
    314         fibril_add_ready(fid);
    315        
    316         fibril_mutex_lock(&quit_lock);
    317         while (!quit)
    318                 fibril_condvar_wait(&quit_cv, &quit_lock);
    319         fibril_mutex_unlock(&quit_lock);
    320        
     265
     266        fid_t fid;
     267
     268        if (ping_repeat) {
     269                fid = fibril_create(transmit_fibril, NULL);
     270                if (fid == 0) {
     271                        printf(NAME ": Failed creating transmit fibril.\n");
     272                        goto error;
     273                }
     274
     275                fibril_add_ready(fid);
     276
     277                fid = fibril_create(input_fibril, NULL);
     278                if (fid == 0) {
     279                        printf(NAME ": Failed creating input fibril.\n");
     280                        goto error;
     281                }
     282
     283                fibril_add_ready(fid);
     284        } else {
     285                ping_send(1);
     286        }
     287
     288        fibril_mutex_lock(&done_lock);
     289        rc = EOK;
     290        while (!done && rc != ETIMEOUT) {
     291                rc = fibril_condvar_wait_timeout(&done_cv, &done_lock,
     292                        ping_repeat ? 0 : PING_TIMEOUT);
     293        }
     294        fibril_mutex_unlock(&done_lock);
     295
     296        if (rc == ETIMEOUT) {
     297                printf(NAME ": Echo request timed out.\n");
     298                goto error;
     299        }
     300
    321301        free(asrc);
    322302        free(adest);
    323303        free(sdest);
     304        dnsr_hostinfo_destroy(hinfo);
    324305        return 0;
    325306       
     
    328309        free(adest);
    329310        free(sdest);
     311        dnsr_hostinfo_destroy(hinfo);
    330312        return 1;
    331313}
Note: See TracChangeset for help on using the changeset viewer.