Changeset 03c971f in mainline for uspace/app/ping/ping.c


Ignore:
Timestamp:
2013-08-15T14:20:16Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
bb2a5b2
Parents:
f2c19b0 (diff), 2921602 (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:

Mainline changes.

File:
1 edited

Legend:

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

    rf2c19b0 r03c971f  
    3737#include <errno.h>
    3838#include <fibril_synch.h>
     39#include <net/socket_codes.h>
    3940#include <inet/dnsr.h>
    4041#include <inet/addr.h>
    4142#include <inet/inetping.h>
    4243#include <io/console.h>
     44#include <getopt.h>
    4345#include <stdio.h>
    4446#include <stdlib.h>
     47#include <str.h>
     48#include <str_error.h>
    4549#include <sys/types.h>
    4650
     
    5357#define PING_TIMEOUT (1000 * 1000)
    5458
     59typedef enum {
     60        RECEIVED_NONE,
     61        RECEIVED_SUCCESS,
     62        RECEIVED_INTERRUPT
     63} received_t;
     64
     65static received_t received;
     66static FIBRIL_CONDVAR_INITIALIZE(received_cv);
     67static FIBRIL_MUTEX_INITIALIZE(received_lock);
     68
     69static bool quit = false;
     70static FIBRIL_CONDVAR_INITIALIZE(quit_cv);
     71static FIBRIL_MUTEX_INITIALIZE(quit_lock);
     72
    5573static 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);
    6074
    6175static inetping_ev_ops_t ev_ops = {
     
    6377};
    6478
    65 static inet_addr_t src_addr;
    66 static inet_addr_t dest_addr;
    67 
    68 static bool ping_repeat = false;
     79static addr32_t src;
     80static addr32_t dest;
     81
     82static bool repeat_forever = false;
     83static size_t repeat_count = 1;
     84
     85static const char *short_options = "rn:";
    6986
    7087static void print_syntax(void)
    7188{
    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);
     89        printf("Syntax: %s [-n <count>|-r] <host>\n", NAME);
     90}
     91
     92static void ping_signal_received(received_t value)
     93{
     94        fibril_mutex_lock(&received_lock);
     95        received = value;
     96        fibril_mutex_unlock(&received_lock);
     97        fibril_condvar_broadcast(&received_cv);
     98}
     99
     100static void ping_signal_quit(void)
     101{
     102        fibril_mutex_lock(&quit_lock);
     103        quit = true;
     104        fibril_mutex_unlock(&quit_lock);
     105        fibril_condvar_broadcast(&quit_cv);
    81106}
    82107
    83108static int ping_ev_recv(inetping_sdu_t *sdu)
    84109{
    85         char *asrc, *adest;
    86         int rc;
    87 
    88         rc = inet_addr_format(&sdu->src, &asrc);
     110        inet_addr_t src_addr;
     111        inet_addr_set(sdu->src, &src_addr);
     112       
     113        inet_addr_t dest_addr;
     114        inet_addr_set(sdu->dest, &dest_addr);
     115       
     116        char *asrc;
     117        int rc = inet_addr_format(&src_addr, &asrc);
    89118        if (rc != EOK)
    90119                return ENOMEM;
    91 
    92         rc = inet_addr_format(&sdu->dest, &adest);
     120       
     121        char *adest;
     122        rc = inet_addr_format(&dest_addr, &adest);
    93123        if (rc != EOK) {
    94124                free(asrc);
    95125                return ENOMEM;
    96126        }
     127       
    97128        printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
    98129            "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
    99 
    100         if (!ping_repeat) {
    101                 ping_signal_done();
    102         }
    103 
     130       
     131        ping_signal_received(RECEIVED_SUCCESS);
     132       
    104133        free(asrc);
    105134        free(adest);
     
    110139{
    111140        inetping_sdu_t sdu;
    112         int rc;
    113 
    114         sdu.src = src_addr;
    115         sdu.dest = dest_addr;
     141       
     142        sdu.src = src;
     143        sdu.dest = dest;
    116144        sdu.seq_no = seq_no;
    117145        sdu.data = (void *) "foo";
    118146        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;
     147       
     148        int rc = inetping_send(&sdu);
     149        if (rc != EOK)
     150                printf("Failed sending echo request: %s (%d).\n",
     151                    str_error(rc), rc);
     152       
     153        return rc;
    127154}
    128155
     
    130157{
    131158        uint16_t seq_no = 0;
    132 
     159       
     160        while ((repeat_count--) || (repeat_forever)) {
     161                fibril_mutex_lock(&received_lock);
     162                received = RECEIVED_NONE;
     163                fibril_mutex_unlock(&received_lock);
     164               
     165                (void) ping_send(++seq_no);
     166               
     167                fibril_mutex_lock(&received_lock);
     168                int rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
     169                    PING_TIMEOUT);
     170                received_t recv = received;
     171                fibril_mutex_unlock(&received_lock);
     172               
     173                if ((rc == ETIMEOUT) || (recv == RECEIVED_NONE))
     174                        printf("Echo request timed out (seq. no %u)\n", seq_no);
     175               
     176                if (recv == RECEIVED_INTERRUPT)
     177                        break;
     178               
     179                if ((repeat_count > 0) || (repeat_forever)) {
     180                        fibril_mutex_lock(&received_lock);
     181                        rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
     182                            PING_DELAY);
     183                        recv = received;
     184                        fibril_mutex_unlock(&received_lock);
     185                       
     186                        if (recv == RECEIVED_INTERRUPT)
     187                                break;
     188                }
     189        }
     190       
     191        ping_signal_quit();
     192        return 0;
     193}
     194
     195static int input_fibril(void *arg)
     196{
     197        console_ctrl_t *con = console_init(stdin, stdout);
     198       
    133199        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) {
     200                cons_event_t ev;
    157201                if (!console_get_event(con, &ev))
    158202                        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) {
     203               
     204                if ((ev.type == CEV_KEY) && (ev.ev.key.type == KEY_PRESS) &&
     205                    ((ev.ev.key.mods & (KM_ALT | KM_SHIFT)) == 0) &&
     206                    ((ev.ev.key.mods & KM_CTRL) != 0)) {
    163207                        /* Ctrl+key */
    164208                        if (ev.ev.key.key == KC_Q) {
    165                                 ping_signal_done();
    166                                 return 0;
     209                                ping_signal_received(RECEIVED_INTERRUPT);
     210                                break;
    167211                        }
    168212                }
    169213        }
    170 
     214       
    171215        return 0;
    172216}
     
    178222        char *adest = NULL;
    179223        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) {
     224       
     225        int rc = inetping_init(&ev_ops);
     226        if (rc != EOK) {
     227                printf("Failed connecting to internet ping service: "
     228                    "%s (%d).\n", str_error(rc), rc);
     229                goto error;
     230        }
     231       
     232        int c;
     233        while ((c = getopt(argc, argv, short_options)) != -1) {
     234                switch (c) {
     235                case 'r':
     236                        repeat_forever = true;
     237                        break;
     238                case 'n':
     239                        rc = str_size_t(optarg, NULL, 10, true, &repeat_count);
     240                        if (rc != EOK) {
     241                                printf("Invalid repeat count.\n");
     242                                print_syntax();
     243                                goto error;
     244                        }
     245                        break;
     246                default:
     247                        printf("Unknown option passed.\n");
     248                        print_syntax();
     249                        goto error;
     250                }
     251        }
     252       
     253        if (optind >= argc) {
     254                printf("IP address or host name not supplied.\n");
    199255                print_syntax();
    200256                goto error;
    201257        }
    202 
     258       
    203259        /* Parse destination address */
    204         rc = inet_addr_parse(argv[argi], &dest_addr);
     260        inet_addr_t dest_addr;
     261        rc = inet_addr_parse(argv[optind], &dest_addr);
    205262        if (rc != EOK) {
    206263                /* Try interpreting as a host name */
    207                 rc = dnsr_name2host(argv[argi], &hinfo);
     264                rc = dnsr_name2host(argv[optind], &hinfo, AF_INET);
    208265                if (rc != EOK) {
    209                         printf(NAME ": Error resolving host '%s'.\n", argv[argi]);
     266                        printf("Error resolving host '%s'.\n", argv[optind]);
    210267                        goto error;
    211268                }
    212 
     269               
    213270                dest_addr = hinfo->addr;
    214271        }
    215 
     272       
     273        uint16_t af = inet_addr_get(&dest_addr, &dest, NULL);
     274        if (af != AF_INET) {
     275                printf("Destination '%s' is not an IPv4 address.\n",
     276                    argv[optind]);
     277                goto error;
     278        }
     279       
    216280        /* Determine source address */
    217         rc = inetping_get_srcaddr(&dest_addr, &src_addr);
    218         if (rc != EOK) {
    219                 printf(NAME ": Failed determining source address.\n");
    220                 goto error;
    221         }
    222 
     281        rc = inetping_get_srcaddr(dest, &src);
     282        if (rc != EOK) {
     283                printf("Failed determining source address.\n");
     284                goto error;
     285        }
     286       
     287        inet_addr_t src_addr;
     288        inet_addr_set(src, &src_addr);
     289       
    223290        rc = inet_addr_format(&src_addr, &asrc);
    224291        if (rc != EOK) {
    225                 printf(NAME ": Out of memory.\n");
    226                 goto error;
    227         }
    228 
     292                printf("Out of memory.\n");
     293                goto error;
     294        }
     295       
    229296        rc = inet_addr_format(&dest_addr, &adest);
    230297        if (rc != EOK) {
    231                 printf(NAME ": Out of memory.\n");
    232                 goto error;
    233         }
    234 
     298                printf("Out of memory.\n");
     299                goto error;
     300        }
     301       
    235302        if (hinfo != NULL) {
    236303                rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest);
    237304                if (rc < 0) {
    238                         printf(NAME ": Out of memory.\n");
     305                        printf("Out of memory.\n");
    239306                        goto error;
    240307                }
     
    243310                adest = NULL;
    244311        }
    245 
    246         printf("Sending ICMP echo request from %s to %s.\n",
     312       
     313        printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n",
    247314            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 
     315       
     316        fid_t fid = fibril_create(transmit_fibril, NULL);
     317        if (fid == 0) {
     318                printf("Failed creating transmit fibril.\n");
     319                goto error;
     320        }
     321       
     322        fibril_add_ready(fid);
     323       
     324        fid = fibril_create(input_fibril, NULL);
     325        if (fid == 0) {
     326                printf("Failed creating input fibril.\n");
     327                goto error;
     328        }
     329       
     330        fibril_add_ready(fid);
     331       
     332        fibril_mutex_lock(&quit_lock);
     333        while (!quit)
     334                fibril_condvar_wait(&quit_cv, &quit_lock);
     335        fibril_mutex_unlock(&quit_lock);
     336       
    284337        free(asrc);
    285338        free(adest);
     
    287340        dnsr_hostinfo_destroy(hinfo);
    288341        return 0;
     342       
    289343error:
    290344        free(asrc);
Note: See TracChangeset for help on using the changeset viewer.