+ struct GNUNET_MessageHeader *msg;
+ struct ShutdownContext *shutdown_ctx = cls;
+
+ if (size < sizeof (struct GNUNET_MessageHeader))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ _("Failed to transmit shutdown request to client.\n"));
+ shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR);
+ GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
+ GNUNET_free (shutdown_ctx);
+ return 0; /* client disconnected */
+ }
+
+ GNUNET_CLIENT_receive (shutdown_ctx->sock, &service_shutdown_handler,
+ shutdown_ctx, GNUNET_TIME_UNIT_FOREVER_REL);
+ shutdown_ctx->cancel_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+ (shutdown_ctx->timeout),
+ &service_shutdown_cancel, shutdown_ctx);
+ msg = (struct GNUNET_MessageHeader *) buf;
+ msg->type = htons (GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN);
+ msg->size = htons (sizeof (struct GNUNET_MessageHeader));
+ return sizeof (struct GNUNET_MessageHeader);
+}
+
+
+/**
+ * Request that the service should shutdown.
+ * Afterwards, the connection will automatically be
+ * disconnected. Hence the "sock" should not
+ * be used by the caller after this call
+ * (calling this function frees "sock" after a while).
+ *
+ * @param sock the socket connected to the service
+ * @param timeout how long to wait before giving up on transmission
+ * @param cont continuation to call once the service is really down
+ * @param cont_cls closure for continuation
+ *
+ */
+static void
+arm_service_shutdown (struct GNUNET_CLIENT_Connection *sock,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_CLIENT_ShutdownTask cont, void *cont_cls)
+{
+ struct ShutdownContext *shutdown_ctx;
+
+ shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
+ shutdown_ctx->cont = cont;
+ shutdown_ctx->cont_cls = cont_cls;
+ shutdown_ctx->sock = sock;
+ shutdown_ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ GNUNET_CLIENT_notify_transmit_ready (sock,
+ sizeof (struct GNUNET_MessageHeader),
+ timeout, GNUNET_NO, &write_shutdown,
+ shutdown_ctx);
+}
+
+
+static void
+arm_notify_stop (void *cls, enum GNUNET_ARM_ProcessStatus status)
+{
+ GNUNET_assert ( (status == GNUNET_ARM_PROCESS_DOWN) ||
+ (status == GNUNET_ARM_PROCESS_ALREADY_DOWN) );