source: mainline/uspace/app/ping/ping.c@ a35b458

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a35b458 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 7.6 KB
RevLine 
[6428115]1/*
[c55cbbf]2 * Copyright (c) 2013 Jiri Svoboda
[6428115]3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup ping
30 * @{
31 */
32/** @file ICMP echo utility.
33 */
34
[3b3c689]35#include <async.h>
[6428115]36#include <errno.h>
37#include <fibril_synch.h>
[3495654]38#include <inet/addr.h>
[a62ceaf]39#include <inet/host.h>
[6428115]40#include <inet/inetping.h>
[3b3c689]41#include <io/console.h>
[ccdc63e]42#include <getopt.h>
[8d2dd7f2]43#include <stdbool.h>
[6428115]44#include <stdio.h>
45#include <stdlib.h>
[8d2dd7f2]46#include <stddef.h>
47#include <stdint.h>
[ccdc63e]48#include <str.h>
49#include <str_error.h>
[6428115]50
51#define NAME "ping"
52
[3b3c689]53/** Delay between subsequent ping requests in microseconds */
54#define PING_DELAY (1000 * 1000)
55
[6428115]56/** Ping request timeout in microseconds */
57#define PING_TIMEOUT (1000 * 1000)
58
[ccdc63e]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);
[3b3c689]68
[ccdc63e]69static bool quit = false;
70static FIBRIL_CONDVAR_INITIALIZE(quit_cv);
71static FIBRIL_MUTEX_INITIALIZE(quit_lock);
72
[b7fd2a0]73static errno_t ping_ev_recv(inetping_sdu_t *);
[6428115]74
75static inetping_ev_ops_t ev_ops = {
76 .recv = ping_ev_recv
77};
78
[9749e47]79static inet_addr_t src_addr;
80static inet_addr_t dest_addr;
[3b3c689]81
[ccdc63e]82static bool repeat_forever = false;
83static size_t repeat_count = 1;
84
[9749e47]85static const char *short_options = "46rn:";
[3b3c689]86
[6428115]87static void print_syntax(void)
88{
[9749e47]89 printf("Syntax: %s [<options>] <host>\n", NAME);
90 printf("\t-n <count> Repeat the specified number of times\n");
91 printf("\t-r Repeat forever\n");
92 printf("\t-4|-6 Use IPv4 or IPv6 destination host address\n");
[6428115]93}
94
[ccdc63e]95static void ping_signal_received(received_t value)
[3b3c689]96{
[ccdc63e]97 fibril_mutex_lock(&received_lock);
98 received = value;
99 fibril_mutex_unlock(&received_lock);
100 fibril_condvar_broadcast(&received_cv);
101}
102
103static void ping_signal_quit(void)
104{
105 fibril_mutex_lock(&quit_lock);
106 quit = true;
107 fibril_mutex_unlock(&quit_lock);
108 fibril_condvar_broadcast(&quit_cv);
[3b3c689]109}
110
[b7fd2a0]111static errno_t ping_ev_recv(inetping_sdu_t *sdu)
[6428115]112{
[3e66428]113 char *asrc;
[b7fd2a0]114 errno_t rc = inet_addr_format(&src_addr, &asrc);
[6428115]115 if (rc != EOK)
116 return ENOMEM;
[a35b458]117
[3e66428]118 char *adest;
[a2e3ee6]119 rc = inet_addr_format(&dest_addr, &adest);
[6428115]120 if (rc != EOK) {
121 free(asrc);
122 return ENOMEM;
123 }
[a35b458]124
[6428115]125 printf("Received ICMP echo reply: from %s to %s, seq. no %u, "
126 "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size);
[a35b458]127
[ccdc63e]128 ping_signal_received(RECEIVED_SUCCESS);
[a35b458]129
[6428115]130 free(asrc);
131 free(adest);
132 return EOK;
133}
134
[b7fd2a0]135static errno_t ping_send(uint16_t seq_no)
[3b3c689]136{
137 inetping_sdu_t sdu;
[a35b458]138
[9749e47]139 sdu.src = src_addr;
140 sdu.dest = dest_addr;
[3b3c689]141 sdu.seq_no = seq_no;
142 sdu.data = (void *) "foo";
143 sdu.size = 3;
[a35b458]144
[b7fd2a0]145 errno_t rc = inetping_send(&sdu);
[ccdc63e]146 if (rc != EOK)
[c1694b6b]147 printf("Failed sending echo request: %s: %s.\n",
148 str_error_name(rc), str_error(rc));
[a35b458]149
[ccdc63e]150 return rc;
[3b3c689]151}
152
[b7fd2a0]153static errno_t transmit_fibril(void *arg)
[3b3c689]154{
155 uint16_t seq_no = 0;
[a35b458]156
[ccdc63e]157 while ((repeat_count--) || (repeat_forever)) {
158 fibril_mutex_lock(&received_lock);
159 received = RECEIVED_NONE;
160 fibril_mutex_unlock(&received_lock);
[a35b458]161
[3b3c689]162 (void) ping_send(++seq_no);
[a35b458]163
[ccdc63e]164 fibril_mutex_lock(&received_lock);
[b7fd2a0]165 errno_t rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
[ccdc63e]166 PING_TIMEOUT);
167 received_t recv = received;
168 fibril_mutex_unlock(&received_lock);
[a35b458]169
[ccdc63e]170 if ((rc == ETIMEOUT) || (recv == RECEIVED_NONE))
171 printf("Echo request timed out (seq. no %u)\n", seq_no);
[a35b458]172
[ccdc63e]173 if (recv == RECEIVED_INTERRUPT)
174 break;
[a35b458]175
[ccdc63e]176 if ((repeat_count > 0) || (repeat_forever)) {
177 fibril_mutex_lock(&received_lock);
178 rc = fibril_condvar_wait_timeout(&received_cv, &received_lock,
179 PING_DELAY);
180 recv = received;
181 fibril_mutex_unlock(&received_lock);
[a35b458]182
[ccdc63e]183 if (recv == RECEIVED_INTERRUPT)
184 break;
185 }
[3b3c689]186 }
[a35b458]187
[ccdc63e]188 ping_signal_quit();
[3b3c689]189 return 0;
190}
191
[b7fd2a0]192static errno_t input_fibril(void *arg)
[3b3c689]193{
[ccdc63e]194 console_ctrl_t *con = console_init(stdin, stdout);
[a35b458]195
[3b3c689]196 while (true) {
[ccdc63e]197 cons_event_t ev;
[07b7c48]198 if (!console_get_event(con, &ev))
[3b3c689]199 break;
[a35b458]200
[ccdc63e]201 if ((ev.type == CEV_KEY) && (ev.ev.key.type == KEY_PRESS) &&
202 ((ev.ev.key.mods & (KM_ALT | KM_SHIFT)) == 0) &&
203 ((ev.ev.key.mods & KM_CTRL) != 0)) {
[3b3c689]204 /* Ctrl+key */
[07b7c48]205 if (ev.ev.key.key == KC_Q) {
[ccdc63e]206 ping_signal_received(RECEIVED_INTERRUPT);
207 break;
[3b3c689]208 }
209 }
210 }
[a35b458]211
[3b3c689]212 return 0;
213}
214
[6428115]215int main(int argc, char *argv[])
216{
[c55cbbf]217 char *asrc = NULL;
218 char *adest = NULL;
219 char *sdest = NULL;
[a62ceaf]220 char *host;
221 const char *errmsg;
[9749e47]222 ip_ver_t ip_ver = ip_any;
[a35b458]223
[b7fd2a0]224 errno_t rc = inetping_init(&ev_ops);
[6428115]225 if (rc != EOK) {
[ccdc63e]226 printf("Failed connecting to internet ping service: "
[c1694b6b]227 "%s: %s.\n", str_error_name(rc), str_error(rc));
[c55cbbf]228 goto error;
[6428115]229 }
[a35b458]230
[ccdc63e]231 int c;
232 while ((c = getopt(argc, argv, short_options)) != -1) {
233 switch (c) {
234 case 'r':
235 repeat_forever = true;
236 break;
237 case 'n':
238 rc = str_size_t(optarg, NULL, 10, true, &repeat_count);
239 if (rc != EOK) {
240 printf("Invalid repeat count.\n");
241 print_syntax();
242 goto error;
243 }
244 break;
[9749e47]245 case '4':
246 ip_ver = ip_v4;
247 break;
248 case '6':
249 ip_ver = ip_v6;
250 break;
[ccdc63e]251 default:
252 printf("Unknown option passed.\n");
253 print_syntax();
254 goto error;
255 }
[3b3c689]256 }
[a35b458]257
[ccdc63e]258 if (optind >= argc) {
259 printf("IP address or host name not supplied.\n");
[6428115]260 print_syntax();
[c55cbbf]261 goto error;
[6428115]262 }
[a35b458]263
[a62ceaf]264 host = argv[optind];
[a35b458]265
[a62ceaf]266 /* Look up host */
267 rc = inet_host_plookup_one(host, ip_ver, &dest_addr, NULL, &errmsg);
[6428115]268 if (rc != EOK) {
[a62ceaf]269 printf("Error resolving host '%s' (%s).\n", host, errmsg);
270 goto error;
[6428115]271 }
[a35b458]272
[6428115]273 /* Determine source address */
[9749e47]274 rc = inetping_get_srcaddr(&dest_addr, &src_addr);
[6428115]275 if (rc != EOK) {
[ccdc63e]276 printf("Failed determining source address.\n");
[c55cbbf]277 goto error;
278 }
[a35b458]279
[a2e3ee6]280 rc = inet_addr_format(&src_addr, &asrc);
[c55cbbf]281 if (rc != EOK) {
[ccdc63e]282 printf("Out of memory.\n");
[c55cbbf]283 goto error;
284 }
[a35b458]285
[a2e3ee6]286 rc = inet_addr_format(&dest_addr, &adest);
[c55cbbf]287 if (rc != EOK) {
[ccdc63e]288 printf("Out of memory.\n");
[c55cbbf]289 goto error;
290 }
[a35b458]291
[d5c1051]292 if (asprintf(&sdest, "%s (%s)", host, adest) < 0) {
[a62ceaf]293 printf("Out of memory.\n");
294 goto error;
[6428115]295 }
[a35b458]296
[ccdc63e]297 printf("Sending ICMP echo request from %s to %s (Ctrl+Q to quit)\n",
[c55cbbf]298 asrc, sdest);
[a35b458]299
[ccdc63e]300 fid_t fid = fibril_create(transmit_fibril, NULL);
301 if (fid == 0) {
302 printf("Failed creating transmit fibril.\n");
303 goto error;
[3b3c689]304 }
[a35b458]305
[ccdc63e]306 fibril_add_ready(fid);
[a35b458]307
[ccdc63e]308 fid = fibril_create(input_fibril, NULL);
309 if (fid == 0) {
310 printf("Failed creating input fibril.\n");
[c55cbbf]311 goto error;
[6428115]312 }
[a35b458]313
[ccdc63e]314 fibril_add_ready(fid);
[a35b458]315
[ccdc63e]316 fibril_mutex_lock(&quit_lock);
317 while (!quit)
318 fibril_condvar_wait(&quit_cv, &quit_lock);
319 fibril_mutex_unlock(&quit_lock);
[a35b458]320
[c55cbbf]321 free(asrc);
322 free(adest);
323 free(sdest);
[6428115]324 return 0;
[a35b458]325
[c55cbbf]326error:
327 free(asrc);
328 free(adest);
329 free(sdest);
330 return 1;
[6428115]331}
332
333/** @}
334 */
Note: See TracBrowser for help on using the repository browser.