int ping_initialize (flux_t *h, const char *service) { struct flux_match match = FLUX_MATCH_ANY; struct ping_context *p = calloc (1, sizeof (*p)); if (!p) { errno = ENOMEM; goto error; } match.typemask = FLUX_MSGTYPE_REQUEST; if (asprintf (&match.topic_glob, "%s.ping", service) < 0) { errno = ENOMEM; goto error; } if (!(p->mh = flux_msg_handler_create (h, match, ping_request_cb, p))) goto error; flux_msg_handler_allow_rolemask (p->mh, FLUX_ROLE_ALL); flux_msg_handler_start (p->mh); flux_aux_set (h, "flux::ping", p, ping_finalize); free (match.topic_glob); return 0; error: free (match.topic_glob); if (p) ping_finalize (p); return -1; }
cmd_state_t cmd_ping(int argc, char* argv[], void* ctx) { static enum { INIT, PING, WAIT_REPLY } state = INIT; struct ping_info_t *ping_info = &INFO; static struct raw_pcb *pcb; switch (state) { case INIT: if (init_ping_info(argc, argv, ping_info) != 0) { printk("Usage: ping [-c count] [-i interval] " \ "[-s packetsize]\n " \ "[-w deadline] [-q] destination\n"); return CMD_DONE; } if (!(pcb = raw_new(IP_PROTO_ICMP))) { printk("could not allocate pcb\n"); state = INIT; return CMD_DONE; } raw_recv(pcb, ping_recv, ping_info); raw_bind(pcb, IP_ADDR_ANY); printk("PING %s %d(%d) bytes of data\n", ip2str(ping_info->destination), ping_info->data_size, ping_info->size); state = PING; /* fall through */ case PING: if (!netif_is_up(netif_default)) { printk("netif is down\n"); raw_remove(pcb); state = INIT; return CMD_DONE; } if (ping_info->count && ping_info->num_tx == ping_info->count) { ping_finalize(ping_info); raw_remove(pcb); state = INIT; return CMD_DONE; } if (timer_get_ms() < ping_info->last_rx_tm + ping_info->interval) { return CMD_INPROGRESS; } ping_send(pcb, ping_info); state = WAIT_REPLY; return CMD_INPROGRESS; case WAIT_REPLY: if (ping_info->flags & PING_REPLY) { ping_info->flags &= (~PING_REPLY); state = PING; return CMD_INPROGRESS; } if (timer_get_ms() > ping_info->last_tx_tm + ping_info->timeout) { if (!ping_info->quiet) printk("timeout from %s\n", ip2str(ping_info->destination)); state = PING; return CMD_INPROGRESS; } if (ping_info->deadline && timer_get_ms() > ping_info->first_tx_tm + ping_info->deadline * 1000) { ping_finalize(ping_info); raw_remove(pcb); state = INIT; return CMD_DONE; } return CMD_INPROGRESS; } /* unreachable */ assert(0); return CMD_DONE; }