Changes in uspace/app/ping/ping.c [0aa70f4:a62ceaf] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/ping/ping.c
r0aa70f4 ra62ceaf 37 37 #include <errno.h> 38 38 #include <fibril_synch.h> 39 #include <net/socket_codes.h>40 #include <inet/dnsr.h>41 39 #include <inet/addr.h> 40 #include <inet/host.h> 42 41 #include <inet/inetping.h> 43 42 #include <io/console.h> 43 #include <getopt.h> 44 44 #include <stdio.h> 45 45 #include <stdlib.h> 46 #include <str.h> 47 #include <str_error.h> 46 48 #include <sys/types.h> 47 49 … … 54 56 #define PING_TIMEOUT (1000 * 1000) 55 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 56 72 static 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);61 73 62 74 static inetping_ev_ops_t ev_ops = { … … 64 76 }; 65 77 66 static addr32_t src; 67 static addr32_t dest; 68 69 static bool ping_repeat = false; 78 static inet_addr_t src_addr; 79 static inet_addr_t dest_addr; 80 81 static bool repeat_forever = false; 82 static size_t repeat_count = 1; 83 84 static const char *short_options = "46rn:"; 70 85 71 86 static void print_syntax(void) 72 87 { 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 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); 82 108 } 83 109 84 110 static int ping_ev_recv(inetping_sdu_t *sdu) 85 111 { 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 92 112 char *asrc; 93 113 int rc = inet_addr_format(&src_addr, &asrc); … … 105 125 "payload size %zu\n", asrc, adest, sdu->seq_no, sdu->size); 106 126 107 if (!ping_repeat) 108 ping_signal_done(); 127 ping_signal_received(RECEIVED_SUCCESS); 109 128 110 129 free(asrc); … … 116 135 { 117 136 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; 122 140 sdu.seq_no = seq_no; 123 141 sdu.data = (void *) "foo"; 124 142 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; 133 150 } 134 151 … … 136 153 { 137 154 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 191 static int input_fibril(void *arg) 192 { 193 console_ctrl_t *con = console_init(stdin, stdout); 194 139 195 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; 163 197 if (!console_get_event(con, &ev)) 164 198 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)) { 169 203 /* Ctrl+key */ 170 204 if (ev.ev.key.key == KC_Q) { 171 ping_signal_ done();172 return 0;205 ping_signal_received(RECEIVED_INTERRUPT); 206 break; 173 207 } 174 208 } 175 209 } 176 210 177 211 return 0; 178 212 } … … 180 214 int main(int argc, char *argv[]) 181 215 { 182 dnsr_hostinfo_t *hinfo = NULL;183 216 char *asrc = NULL; 184 217 char *adest = NULL; 185 218 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(); 217 253 goto error; 218 254 } 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); 227 269 goto error; 228 270 } 229 271 230 272 /* 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 } 239 278 240 279 rc = inet_addr_format(&src_addr, &asrc); 241 280 if (rc != EOK) { 242 printf( NAME ":Out of memory.\n");281 printf("Out of memory.\n"); 243 282 goto error; 244 283 } … … 246 285 rc = inet_addr_format(&dest_addr, &adest); 247 286 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", 264 298 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 301 321 free(asrc); 302 322 free(adest); 303 323 free(sdest); 304 dnsr_hostinfo_destroy(hinfo);305 324 return 0; 306 325 … … 309 328 free(adest); 310 329 free(sdest); 311 dnsr_hostinfo_destroy(hinfo);312 330 return 1; 313 331 }
Note:
See TracChangeset
for help on using the changeset viewer.