+ a_fail(a, "bad-syntax -- add PEER [OPTIONS] ADDR ...");
+ return;
+}
+
+/*----- Ping --------------------------------------------------------------*/
+
+/* --- @a_pong@ --- *
+ *
+ * Arguments: @int rc@ = return code
+ * @void *av@ = admin connection which requested the ping
+ *
+ * Returns: ---
+ *
+ * Use: Collects what happened to a ping message.
+ */
+
+static void a_pong(int rc, void *av)
+{
+ admin *a = av;
+ struct timeval tv;
+ double millis;
+
+ a_lock(a);
+ switch (rc) {
+ case PING_OK:
+ gettimeofday(&tv, 0);
+ tv_sub(&tv, &tv, &a->pingtime);
+ millis = (double)tv.tv_sec * 1000 + (double)tv.tv_usec/1000;
+ a_info(a, "ping-ok %.1f", millis);
+ a_ok(a);
+ break;
+ case PING_TIMEOUT:
+ a_info(a, "ping-timeout");
+ a_ok(a);
+ break;
+ case PING_PEERDIED:
+ a_info(a, "ping-peer-died");
+ a_ok(a);
+ break;
+ default:
+ abort();
+ }
+ a_unlock(a);
+}
+
+/* --- @acmd_ping@, @acmd_eping@ --- *
+ *
+ * Arguments: @admin *a@ = connection which requested the ping
+ * @unsigned ac@ = argument count
+ * @char *av[]@ = pointer to the argument list
+ *
+ * Returns: ---
+ *
+ * Use: Pings a peer.
+ */
+
+static void a_ping(admin *a, unsigned ac, char *av[],
+ const char *cmd, unsigned msg)
+{
+ long t = T_PING;
+ int i;
+ peer *p;
+
+ i = 0;
+ for (;;) {
+ if (!av[i])
+ goto bad_syntax;
+ if (mystrieq(av[i], "-timeout")) {
+ if (!av[++i]) goto bad_syntax;
+ if ((t = a_parsetime(av[i])) < 0) {
+ a_fail(a, "bad-time-spec %s", av[i]);
+ return;
+ }
+ } else if (mystrieq(av[i], "--")) {
+ i++;
+ break;
+ } else
+ break;
+ i++;
+ }
+
+ if (!av[i]) goto bad_syntax;
+ if ((p = p_find(av[i])) == 0) {
+ a_fail(a, "unknown-peer %s", av[i]);
+ return;
+ }
+ gettimeofday(&a->pingtime, 0);
+ if (p_pingsend(p, &a->ping, msg, t, a_pong, a))
+ a_fail(a, "ping-send-failed");
+ return;
+
+bad_syntax:
+ a_fail(a, "bad-syntax -- %s [OPTIONS] PEER", cmd);