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