Changes in uspace/app/ping/ping.c [9749e47:959d2ec] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/ping/ping.c
r9749e47 r959d2ec 41 41 #include <inet/inetping.h> 42 42 #include <io/console.h> 43 #include <getopt.h>44 43 #include <stdio.h> 45 44 #include <stdlib.h> 46 #include <str.h>47 #include <str_error.h>48 45 #include <sys/types.h> 49 46 … … 56 53 #define PING_TIMEOUT (1000 * 1000) 57 54 58 typedef enum {59 RECEIVED_NONE,60 RECEIVED_SUCCESS,61 RECEIVED_INTERRUPT62 } 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 72 55 static 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); 73 60 74 61 static inetping_ev_ops_t ev_ops = { … … 79 66 static inet_addr_t dest_addr; 80 67 81 static bool repeat_forever = false; 82 static size_t repeat_count = 1; 83 84 static const char *short_options = "46rn:"; 68 static bool ping_repeat = false; 85 69 86 70 static void print_syntax(void) 87 71 { 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 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); 108 81 } 109 82 110 83 static int ping_ev_recv(inetping_sdu_t *sdu) 111 84 { 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); 114 89 if (rc != EOK) 115 90 return ENOMEM; 116 117 char *adest; 118 rc = inet_addr_format(&dest_addr, &adest); 91 92 rc = inet_addr_format(&sdu->dest, &adest); 119 93 if (rc != EOK) { 120 94 free(asrc); 121 95 return ENOMEM; 122 96 } 123 124 97 printf("Received ICMP echo reply: from %s to %s, seq. no %u, " 125 98 "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 129 104 free(asrc); 130 105 free(adest); … … 135 110 { 136 111 inetping_sdu_t sdu; 137 112 int rc; 113 138 114 sdu.src = src_addr; 139 115 sdu.dest = dest_addr; … … 141 117 sdu.data = (void *) "foo"; 142 118 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; 150 127 } 151 128 … … 153 130 { 154 131 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 161 141 (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 188 145 return 0; 189 146 } … … 191 148 static int input_fibril(void *arg) 192 149 { 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 195 156 while (true) { 196 cons_event_t ev;197 157 if (!console_get_event(con, &ev)) 198 158 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) { 203 163 /* Ctrl+key */ 204 164 if (ev.ev.key.key == KC_Q) { 205 ping_signal_ received(RECEIVED_INTERRUPT);206 break;165 ping_signal_done(); 166 return 0; 207 167 } 208 168 } 209 169 } 210 170 211 171 return 0; 212 172 } … … 218 178 char *adest = NULL; 219 179 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) { 258 199 print_syntax(); 259 200 goto error; 260 201 } 261 202 262 203 /* Parse destination address */ 263 rc = inet_addr_parse(argv[ optind], &dest_addr);204 rc = inet_addr_parse(argv[argi], &dest_addr); 264 205 if (rc != EOK) { 265 206 /* Try interpreting as a host name */ 266 rc = dnsr_name2host(argv[ optind], &hinfo, ip_ver);207 rc = dnsr_name2host(argv[argi], &hinfo); 267 208 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 272 213 dest_addr = hinfo->addr; 273 214 } 274 215 275 216 /* Determine source address */ 276 217 rc = inetping_get_srcaddr(&dest_addr, &src_addr); 277 218 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 282 223 rc = inet_addr_format(&src_addr, &asrc); 283 224 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 288 229 rc = inet_addr_format(&dest_addr, &adest); 289 230 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 294 235 if (hinfo != NULL) { 295 236 rc = asprintf(&sdest, "%s (%s)", hinfo->cname, adest); 296 237 if (rc < 0) { 297 printf( "Out of memory.\n");238 printf(NAME ": Out of memory.\n"); 298 239 goto error; 299 240 } … … 302 243 adest = NULL; 303 244 } 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", 306 247 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 329 284 free(asrc); 330 285 free(adest); … … 332 287 dnsr_hostinfo_destroy(hinfo); 333 288 return 0; 334 335 289 error: 336 290 free(asrc);
Note:
See TracChangeset
for help on using the changeset viewer.