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


Ignore:
File:
1 edited

Legend:

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

    r959d2ec r9749e47  
    4141#include <inet/inetping.h>
    4242#include <io/console.h>
     43#include <getopt.h>
    4344#include <stdio.h>
    4445#include <stdlib.h>
     46#include <str.h>
     47#include <str_error.h>
    4548#include <sys/types.h>
    4649
     
    5356#define PING_TIMEOUT (1000 * 1000)
    5457
     58typedef enum {
     59        RECEIVED_NONE,
     60        RECEIVED_SUCCESS,
     61        RECEIVED_INTERRUPT
     62} received_t;
     63
     64static received_t received;
     65static FIBRIL_CONDVAR_INITIALIZE(received_cv);
     66static FIBRIL_MUTEX_INITIALIZE(received_lock);
     67
     68static bool quit = false;
     69static FIBRIL_CONDVAR_INITIALIZE(quit_cv);
     70static FIBRIL_MUTEX_INITIALIZE(quit_lock);
     71
    5572static int ping_ev_recv(inetping_sdu_t *);
    56 
    57 static bool done = false;
    58 static FIBRIL_CONDVAR_INITIALIZE(done_cv);
    59 static FIBRIL_MUTEX_INITIALIZE(done_lock);
    6073
    6174static inetping_ev_ops_t ev_ops = {
     
    6679static inet_addr_t dest_addr;
    6780
    68 static bool ping_repeat = false;
     81static bool repeat_forever = false;
     82static size_t repeat_count = 1;
     83
     84static const char *short_options = "46rn:";
    6985
    7086static void print_syntax(void)
    7187{
    72         printf("syntax: " NAME " [-r] <host>\n");
    73 }
    74 
    75 static 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);
     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
     94static 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
     102static 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);
    81108}
    82109
    83110static int ping_ev_recv(inetping_sdu_t *sdu)
    84111{
    85         char *asrc, *adest;
    86         int rc;
    87 
    88         rc = inet_addr_format(&sdu->src, &asrc);
     112        char *asrc;
     113        int rc = inet_addr_format(&src_addr, &asrc);
    89114        if (rc != EOK)
    90115                return ENOMEM;
    91 
    92         rc = inet_addr_format(&sdu->dest, &adest);
     116       
     117        char *adest;
     118        rc = inet_addr_format(&dest_addr, &adest);
    93119        if (rc != EOK) {
    94120                free(asrc);
    95121                return ENOMEM;
    96122        }
     123       
    97124        printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
    98125            "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
    99 
    100         if (!ping_repeat) {
    101                 ping_signal_done();
    102         }
    103 
     126       
     127        ping_signal_received(RECEIVED_SUCCESS);
     128       
    104129        free(asrc);
    105130        free(adest);
     
    110135{
    111136        inetping_sdu_t sdu;
    112         int rc;
    113 
     137       
    114138        sdu.src = src_addr;
    115139        sdu.dest = dest_addr;
     
    117141        sdu.data = (void *) "foo";
    118142        sdu.size = 3;
    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;
     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;
    127150}
    128151
     
    130153{
    131154        uint16_t seq_no = 0;
    132 
     155       
     156        while ((repeat_count--) || (repeat_forever)) {
     157                fibril_mutex_lock(&received_lock);
     158                received = RECEIVED_NONE;
     159                fibril_mutex_unlock(&received_lock);
     160               
     161                (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();
     188        return 0;
     189}
     190
     191static int input_fibril(void *arg)
     192{
     193        console_ctrl_t *con = console_init(stdin, stdout);
     194       
    133195        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 
    141                 (void) ping_send(++seq_no);
    142                 async_usleep(PING_DELAY);
    143         }
    144 
    145         return 0;
    146 }
    147 
    148 static int input_fibril(void *arg)
    149 {
    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 
    156         while (true) {
     196                cons_event_t ev;
    157197                if (!console_get_event(con, &ev))
    158198                        break;
    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) {
     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)) {
    163203                        /* Ctrl+key */
    164204                        if (ev.ev.key.key == KC_Q) {
    165                                 ping_signal_done();
    166                                 return 0;
     205                                ping_signal_received(RECEIVED_INTERRUPT);
     206                                break;
    167207                        }
    168208                }
    169209        }
    170 
     210       
    171211        return 0;
    172212}
     
    178218        char *adest = NULL;
    179219        char *sdest = NULL;
    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) {
     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");
    199258                print_syntax();
    200259                goto error;
    201260        }
    202 
     261       
    203262        /* Parse destination address */
    204         rc = inet_addr_parse(argv[argi], &dest_addr);
     263        rc = inet_addr_parse(argv[optind], &dest_addr);
    205264        if (rc != EOK) {
    206265                /* Try interpreting as a host name */
    207                 rc = dnsr_name2host(argv[argi], &hinfo);
     266                rc = dnsr_name2host(argv[optind], &hinfo, ip_ver);
    208267                if (rc != EOK) {
    209                         printf(NAME ": Error resolving host '%s'.\n", argv[argi]);
     268                        printf("Error resolving host '%s'.\n", argv[optind]);
    210269                        goto error;
    211270                }
    212 
     271               
    213272                dest_addr = hinfo->addr;
    214273        }
    215 
     274       
    216275        /* Determine source address */
    217276        rc = inetping_get_srcaddr(&dest_addr, &src_addr);
    218277        if (rc != EOK) {
    219                 printf(NAME ": Failed determining source address.\n");
    220                 goto error;
    221         }
    222 
     278                printf("Failed determining source address.\n");
     279                goto error;
     280        }
     281       
    223282        rc = inet_addr_format(&src_addr, &asrc);
    224283        if (rc != EOK) {
    225                 printf(NAME ": Out of memory.\n");
    226                 goto error;
    227         }
    228 
     284                printf("Out of memory.\n");
     285                goto error;
     286        }
     287       
    229288        rc = inet_addr_format(&dest_addr, &adest);
    230289        if (rc != EOK) {
    231                 printf(NAME ": Out of memory.\n");
    232                 goto error;
    233         }
    234 
     290                printf("Out of memory.\n");
     291                goto error;
     292        }
     293       
    235294        if (hinfo != NULL) {
    236295                rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest);
    237296                if (rc < 0) {
    238                         printf(NAME ": Out of memory.\n");
     297                        printf("Out of memory.\n");
    239298                        goto error;
    240299                }
     
    243302                adest = NULL;
    244303        }
    245 
    246         printf("Sending ICMP echo request from %s to %s.\n",
     304       
     305        printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n",
    247306            asrc, sdest);
    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 
     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       
    284329        free(asrc);
    285330        free(adest);
     
    287332        dnsr_hostinfo_destroy(hinfo);
    288333        return 0;
     334       
    289335error:
    290336        free(asrc);
Note: See TracChangeset for help on using the changeset viewer.