Changes in uspace/app/ping/ping.c [9749e47:959d2ec] in mainline


Ignore:
File:
1 edited

Legend:

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

    r9749e47 r959d2ec  
    4141#include <inet/inetping.h>
    4242#include <io/console.h>
    43 #include <getopt.h>
    4443#include <stdio.h>
    4544#include <stdlib.h>
    46 #include <str.h>
    47 #include <str_error.h>
    4845#include <sys/types.h>
    4946
     
    5653#define PING_TIMEOUT (1000 * 1000)
    5754
    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 
    7255static int ping_ev_recv(inetping_sdu_t *);
     56
     57static bool done = false;
     58static FIBRIL_CONDVAR_INITIALIZE(done_cv);
     59static FIBRIL_MUTEX_INITIALIZE(done_lock);
    7360
    7461static inetping_ev_ops_t ev_ops = {
     
    7966static inet_addr_t dest_addr;
    8067
    81 static bool repeat_forever = false;
    82 static size_t repeat_count = 1;
    83 
    84 static const char *short_options = "46rn:";
     68static bool ping_repeat = false;
    8569
    8670static void print_syntax(void)
    8771{
    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);
     72        printf("syntax: " NAME " [-r] <host>\n");
     73}
     74
     75static void ping_signal_done(void)
     76{
     77        fibril_mutex_lock(&done_lock);
     78        done = true;
     79        fibril_mutex_unlock(&done_lock);
     80        fibril_condvar_broadcast(&done_cv);
    10881}
    10982
    11083static int ping_ev_recv(inetping_sdu_t *sdu)
    11184{
    112         char *asrc;
    113         int rc = inet_addr_format(&src_addr, &asrc);
     85        char *asrc, *adest;
     86        int rc;
     87
     88        rc = inet_addr_format(&sdu->src, &asrc);
    11489        if (rc != EOK)
    11590                return ENOMEM;
    116        
    117         char *adest;
    118         rc = inet_addr_format(&dest_addr, &adest);
     91
     92        rc = inet_addr_format(&sdu->dest, &adest);
    11993        if (rc != EOK) {
    12094                free(asrc);
    12195                return ENOMEM;
    12296        }
    123        
    12497        printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
    12598            "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
    126        
    127         ping_signal_received(RECEIVED_SUCCESS);
    128        
     99
     100        if (!ping_repeat) {
     101                ping_signal_done();
     102        }
     103
    129104        free(asrc);
    130105        free(adest);
     
    135110{
    136111        inetping_sdu_t sdu;
    137        
     112        int rc;
     113
    138114        sdu.src = src_addr;
    139115        sdu.dest = dest_addr;
     
    141117        sdu.data = (void *) "foo";
    142118        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;
     119
     120        rc = inetping_send(&sdu);
     121        if (rc != EOK) {
     122                printf(NAME ": Failed sending echo request (%d).\n", rc);
     123                return rc;
     124        }
     125
     126        return EOK;
    150127}
    151128
     
    153130{
    154131        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                
     132
     133        while (true) {
     134                fibril_mutex_lock(&done_lock);
     135                if (done) {
     136                        fibril_mutex_unlock(&done_lock);
     137                        return 0;
     138                }
     139                fibril_mutex_unlock(&done_lock);
     140
    161141                (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();
     142                async_usleep(PING_DELAY);
     143        }
     144
    188145        return 0;
    189146}
     
    191148static int input_fibril(void *arg)
    192149{
    193         console_ctrl_t *con = console_init(stdin, stdout);
    194        
     150        console_ctrl_t *con;
     151        cons_event_t ev;
     152
     153        con = console_init(stdin, stdout);
     154        printf("[Press Ctrl-Q to quit]\n");
     155
    195156        while (true) {
    196                 cons_event_t ev;
    197157                if (!console_get_event(con, &ev))
    198158                        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)) {
     159
     160                if (ev.type == CEV_KEY && ev.ev.key.type == KEY_PRESS &&
     161                    (ev.ev.key.mods & (KM_ALT | KM_SHIFT)) ==
     162                    0 && (ev.ev.key.mods & KM_CTRL) != 0) {
    203163                        /* Ctrl+key */
    204164                        if (ev.ev.key.key == KC_Q) {
    205                                 ping_signal_received(RECEIVED_INTERRUPT);
    206                                 break;
     165                                ping_signal_done();
     166                                return 0;
    207167                        }
    208168                }
    209169        }
    210        
     170
    211171        return 0;
    212172}
     
    218178        char *adest = NULL;
    219179        char *sdest = NULL;
    220         ip_ver_t ip_ver = ip_any;
    221        
    222         int rc = inetping_init(&ev_ops);
    223         if (rc != EOK) {
    224                 printf("Failed connecting to internet ping service: "
    225                     "%s (%d).\n", str_error(rc), rc);
    226                 goto error;
    227         }
    228        
    229         int c;
    230         while ((c = getopt(argc, argv, short_options)) != -1) {
    231                 switch (c) {
    232                 case 'r':
    233                         repeat_forever = true;
    234                         break;
    235                 case 'n':
    236                         rc = str_size_t(optarg, NULL, 10, true, &repeat_count);
    237                         if (rc != EOK) {
    238                                 printf("Invalid repeat count.\n");
    239                                 print_syntax();
    240                                 goto error;
    241                         }
    242                         break;
    243                 case '4':
    244                         ip_ver = ip_v4;
    245                         break;
    246                 case '6':
    247                         ip_ver = ip_v6;
    248                         break;
    249                 default:
    250                         printf("Unknown option passed.\n");
    251                         print_syntax();
    252                         goto error;
    253                 }
    254         }
    255        
    256         if (optind >= argc) {
    257                 printf("IP address or host name not supplied.\n");
     180        int rc;
     181        int argi;
     182
     183        rc = inetping_init(&ev_ops);
     184        if (rc != EOK) {
     185                printf(NAME ": Failed connecting to internet ping service "
     186                    "(%d).\n", rc);
     187                goto error;
     188        }
     189
     190        argi = 1;
     191        if (argi < argc && str_cmp(argv[argi], "-r") == 0) {
     192                ping_repeat = true;
     193                ++argi;
     194        } else {
     195                ping_repeat = false;
     196        }
     197
     198        if (argc - argi != 1) {
    258199                print_syntax();
    259200                goto error;
    260201        }
    261        
     202
    262203        /* Parse destination address */
    263         rc = inet_addr_parse(argv[optind], &dest_addr);
     204        rc = inet_addr_parse(argv[argi], &dest_addr);
    264205        if (rc != EOK) {
    265206                /* Try interpreting as a host name */
    266                 rc = dnsr_name2host(argv[optind], &hinfo, ip_ver);
     207                rc = dnsr_name2host(argv[argi], &hinfo);
    267208                if (rc != EOK) {
    268                         printf("Error resolving host '%s'.\n", argv[optind]);
    269                         goto error;
    270                 }
    271                
     209                        printf(NAME ": Error resolving host '%s'.\n", argv[argi]);
     210                        goto error;
     211                }
     212
    272213                dest_addr = hinfo->addr;
    273214        }
    274        
     215
    275216        /* Determine source address */
    276217        rc = inetping_get_srcaddr(&dest_addr, &src_addr);
    277218        if (rc != EOK) {
    278                 printf("Failed determining source address.\n");
    279                 goto error;
    280         }
    281        
     219                printf(NAME ": Failed determining source address.\n");
     220                goto error;
     221        }
     222
    282223        rc = inet_addr_format(&src_addr, &asrc);
    283224        if (rc != EOK) {
    284                 printf("Out of memory.\n");
    285                 goto error;
    286         }
    287        
     225                printf(NAME ": Out of memory.\n");
     226                goto error;
     227        }
     228
    288229        rc = inet_addr_format(&dest_addr, &adest);
    289230        if (rc != EOK) {
    290                 printf("Out of memory.\n");
    291                 goto error;
    292         }
    293        
     231                printf(NAME ": Out of memory.\n");
     232                goto error;
     233        }
     234
    294235        if (hinfo != NULL) {
    295236                rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest);
    296237                if (rc < 0) {
    297                         printf("Out of memory.\n");
     238                        printf(NAME ": Out of memory.\n");
    298239                        goto error;
    299240                }
     
    302243                adest = NULL;
    303244        }
    304        
    305         printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n",
     245
     246        printf("Sending ICMP echo request from %s to %s.\n",
    306247            asrc, sdest);
    307        
    308         fid_t fid = fibril_create(transmit_fibril, NULL);
    309         if (fid == 0) {
    310                 printf("Failed creating transmit fibril.\n");
    311                 goto error;
    312         }
    313        
    314         fibril_add_ready(fid);
    315        
    316         fid = fibril_create(input_fibril, NULL);
    317         if (fid == 0) {
    318                 printf("Failed creating input fibril.\n");
    319                 goto error;
    320         }
    321        
    322         fibril_add_ready(fid);
    323        
    324         fibril_mutex_lock(&quit_lock);
    325         while (!quit)
    326                 fibril_condvar_wait(&quit_cv, &quit_lock);
    327         fibril_mutex_unlock(&quit_lock);
    328        
     248
     249        fid_t fid;
     250
     251        if (ping_repeat) {
     252                fid = fibril_create(transmit_fibril, NULL);
     253                if (fid == 0) {
     254                        printf(NAME ": Failed creating transmit fibril.\n");
     255                        goto error;
     256                }
     257
     258                fibril_add_ready(fid);
     259
     260                fid = fibril_create(input_fibril, NULL);
     261                if (fid == 0) {
     262                        printf(NAME ": Failed creating input fibril.\n");
     263                        goto error;
     264                }
     265
     266                fibril_add_ready(fid);
     267        } else {
     268                ping_send(1);
     269        }
     270
     271        fibril_mutex_lock(&done_lock);
     272        rc = EOK;
     273        while (!done && rc != ETIMEOUT) {
     274                rc = fibril_condvar_wait_timeout(&done_cv, &done_lock,
     275                        ping_repeat ? 0 : PING_TIMEOUT);
     276        }
     277        fibril_mutex_unlock(&done_lock);
     278
     279        if (rc == ETIMEOUT) {
     280                printf(NAME ": Echo request timed out.\n");
     281                goto error;
     282        }
     283
    329284        free(asrc);
    330285        free(adest);
     
    332287        dnsr_hostinfo_destroy(hinfo);
    333288        return 0;
    334        
    335289error:
    336290        free(asrc);
Note: See TracChangeset for help on using the changeset viewer.