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


Ignore:
File:
1 edited

Legend:

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

    r0aa70f4 ra62ceaf  
    3737#include <errno.h>
    3838#include <fibril_synch.h>
    39 #include <net/socket_codes.h>
    40 #include <inet/dnsr.h>
    4139#include <inet/addr.h>
     40#include <inet/host.h>
    4241#include <inet/inetping.h>
    4342#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>
    4648#include <sys/types.h>
    4749
     
    5456#define PING_TIMEOUT (1000 * 1000)
    5557
     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
    5672static int ping_ev_recv(inetping_sdu_t *);
    57 
    58 static bool done = false;
    59 static FIBRIL_CONDVAR_INITIALIZE(done_cv);
    60 static FIBRIL_MUTEX_INITIALIZE(done_lock);
    6173
    6274static inetping_ev_ops_t ev_ops = {
     
    6476};
    6577
    66 static addr32_t src;
    67 static addr32_t dest;
    68 
    69 static bool ping_repeat = false;
     78static inet_addr_t src_addr;
     79static inet_addr_t dest_addr;
     80
     81static bool repeat_forever = false;
     82static size_t repeat_count = 1;
     83
     84static const char *short_options = "46rn:";
    7085
    7186static void print_syntax(void)
    7287{
    73         printf("syntax: " NAME " [-r] <host>\n");
    74 }
    75 
    76 static 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);
     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);
    82108}
    83109
    84110static int ping_ev_recv(inetping_sdu_t *sdu)
    85111{
    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        
    92112        char *asrc;
    93113        int rc = inet_addr_format(&src_addr, &asrc);
     
    105125            "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
    106126       
    107         if (!ping_repeat)
    108                 ping_signal_done();
     127        ping_signal_received(RECEIVED_SUCCESS);
    109128       
    110129        free(asrc);
     
    116135{
    117136        inetping_sdu_t sdu;
    118         int rc;
    119 
    120         sdu.src = src;
    121         sdu.dest = dest;
     137       
     138        sdu.src = src_addr;
     139        sdu.dest = dest_addr;
    122140        sdu.seq_no = seq_no;
    123141        sdu.data = (void *) "foo";
    124142        sdu.size = 3;
    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;
     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;
    133150}
    134151
     
    136153{
    137154        uint16_t seq_no = 0;
    138 
     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       
    139195        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 
    147                 (void) ping_send(++seq_no);
    148                 async_usleep(PING_DELAY);
    149         }
    150 
    151         return 0;
    152 }
    153 
    154 static int input_fibril(void *arg)
    155 {
    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 
    162         while (true) {
     196                cons_event_t ev;
    163197                if (!console_get_event(con, &ev))
    164198                        break;
    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) {
     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)) {
    169203                        /* Ctrl+key */
    170204                        if (ev.ev.key.key == KC_Q) {
    171                                 ping_signal_done();
    172                                 return 0;
     205                                ping_signal_received(RECEIVED_INTERRUPT);
     206                                break;
    173207                        }
    174208                }
    175209        }
    176 
     210       
    177211        return 0;
    178212}
     
    180214int main(int argc, char *argv[])
    181215{
    182         dnsr_hostinfo_t *hinfo = NULL;
    183216        char *asrc = NULL;
    184217        char *adest = NULL;
    185218        char *sdest = NULL;
    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]);
     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();
    217253                        goto error;
    218254                }
    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]);
     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);
    227269                goto error;
    228270        }
    229271       
    230272        /* Determine source address */
    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);
     273        rc = inetping_get_srcaddr(&dest_addr, &src_addr);
     274        if (rc != EOK) {
     275                printf("Failed determining source address.\n");
     276                goto error;
     277        }
    239278       
    240279        rc = inet_addr_format(&src_addr, &asrc);
    241280        if (rc != EOK) {
    242                 printf(NAME ": Out of memory.\n");
     281                printf("Out of memory.\n");
    243282                goto error;
    244283        }
     
    246285        rc = inet_addr_format(&dest_addr, &adest);
    247286        if (rc != EOK) {
    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",
     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",
    264298            asrc, sdest);
    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 
     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       
    301321        free(asrc);
    302322        free(adest);
    303323        free(sdest);
    304         dnsr_hostinfo_destroy(hinfo);
    305324        return 0;
    306325       
     
    309328        free(adest);
    310329        free(sdest);
    311         dnsr_hostinfo_destroy(hinfo);
    312330        return 1;
    313331}
Note: See TracChangeset for help on using the changeset viewer.