#include "platform.h"
#include "gnunet_util_lib.h"
-#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-client-mgr", __VA_ARGS__)
/**
*/
const struct GNUNET_CLIENT_MANAGER_MessageHandler *handlers;
+ /**
+ * Disconnect callback.
+ */
+ void (*disconnect_cb)(void *);
+
+ /**
+ * Disconnect closure.
+ */
+ void *disconnect_cls;
+
/**
* User context value.
* @see GNUNET_CLIENT_MANAGER_set_user_context()
/**
* Task doing exponential back-off trying to reconnect.
*/
- GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
+ struct GNUNET_SCHEDULER_Task * reconnect_task;
/**
* Time for next connect retry.
* #GNUNET_YES if GNUNET_CLIENT_MANAGER_disconnect() was called
* and we're transmitting the last messages from the queue.
*/
- uint8_t disconnecting;
+ uint8_t is_disconnecting;
};
transmit_next (struct GNUNET_CLIENT_MANAGER_Connection *mgr);
+static void
+schedule_disconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_CLIENT_MANAGER_Connection *mgr = cls;
+ GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO,
+ mgr->disconnect_cb, mgr->disconnect_cls);
+}
+
+
/**
* Transmit next message to service.
*
- * @param cls The struct GNUNET_PSYC_Channel.
- * @param size Number of bytes available in @a buf.
- * @param buf Where to copy the message.
+ * @param cls
+ * struct GNUNET_CLIENT_MANAGER_Connection
+ * @param size
+ * Number of bytes available in @a buf.
+ * @param buf
+ * Where to copy the message.
*
* @return Number of bytes copied to @a buf.
*/
GNUNET_free (mqi);
if (NULL != mgr->tmit_head)
+ {
transmit_next (mgr);
+ }
+ else if (GNUNET_YES == mgr->is_disconnecting)
+ {
+ GNUNET_SCHEDULER_add_now (&schedule_disconnect, mgr);
+ return size;
+ }
if (GNUNET_NO == mgr->in_receive)
{
if (NULL == mgr->tmit_head)
{
- if (GNUNET_YES == mgr->disconnecting)
- GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO);
+ if (GNUNET_YES == mgr->is_disconnecting)
+ GNUNET_CLIENT_MANAGER_disconnect (mgr, GNUNET_NO,
+ mgr->disconnect_cb, mgr->disconnect_cls);
return;
}
/**
* Try again to connect to the service.
*
- * @param cls Channel handle.
- * @param tc Scheduler context.
+ * @param cls
+ * Channel handle.
+ * @param tc
+ * Scheduler context.
*/
static void
-reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+schedule_reconnect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct GNUNET_CLIENT_MANAGER_Connection *mgr = cls;
- mgr->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ mgr->reconnect_task = NULL;
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Connecting to %s service.\n", mgr->service_name);
/**
* Connect to service.
*
- * @param cfg Configuration to use.
- * @param service_name Service name to connect to.
- * @param handlers Message handlers.
+ * @param cfg
+ * Configuration to use.
+ * @param service_name
+ * Service name to connect to.
+ * @param handlers
+ * Message handlers.
*
* @return Client manager connection handle.
*/
mgr->service_name = service_name;
mgr->handlers = handlers;
mgr->reconnect_delay = GNUNET_TIME_UNIT_ZERO;
- mgr->reconnect_task = GNUNET_SCHEDULER_add_now (&reconnect, mgr);
+ mgr->reconnect_task = GNUNET_SCHEDULER_add_now (&schedule_reconnect, mgr);
return mgr;
}
/**
* Disconnect from the service.
*
- * @param mgr Client manager connection.
- * @param transmit_queue Transmit pending messages in queue before disconnecting.
+ * @param mgr
+ * Client manager connection.
+ * @param transmit_queue
+ * Transmit pending messages in queue before disconnecting.
+ * @param disconnect_cb
+ * Function called after disconnected from the service.
+ * @param cls
+ * Closure for @a disconnect_cb.
*/
void
GNUNET_CLIENT_MANAGER_disconnect (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
- int transmit_queue)
+ int transmit_queue,
+ GNUNET_ContinuationCallback disconnect_cb,
+ void *cls)
{
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting (%d)\n", transmit_queue);
+ mgr->disconnect_cb = disconnect_cb;
+ mgr->disconnect_cls = cls;
if (NULL != mgr->tmit_head)
{
if (GNUNET_YES == transmit_queue)
{
- mgr->disconnecting = GNUNET_YES;
+ mgr->is_disconnecting = GNUNET_YES;
transmit_next (mgr);
+ return;
}
else
{
GNUNET_CLIENT_MANAGER_drop_queue (mgr);
}
}
- if (mgr->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
+ if (mgr->reconnect_task != NULL)
{
GNUNET_SCHEDULER_cancel (mgr->reconnect_task);
- mgr->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ mgr->reconnect_task = NULL;
}
if (NULL != mgr->client_tmit)
{
GNUNET_CLIENT_disconnect (mgr->client);
mgr->client = NULL;
}
+ if (NULL != mgr->disconnect_cb)
+ mgr->disconnect_cb (mgr->disconnect_cls);
GNUNET_free (mgr);
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnected.\n");
}
/**
* Reschedule connect to the service using exponential back-off.
*
- * @param mgr Client manager connection.
+ * @param mgr
+ * Client manager connection.
*/
void
GNUNET_CLIENT_MANAGER_reconnect (struct GNUNET_CLIENT_MANAGER_Connection *mgr)
{
- if (GNUNET_SCHEDULER_NO_TASK != mgr->reconnect_task)
+ if (NULL != mgr->reconnect_task)
return;
if (NULL != mgr->client_tmit)
"Scheduling task to reconnect to service in %s.\n",
GNUNET_STRINGS_relative_time_to_string (mgr->reconnect_delay, GNUNET_YES));
mgr->reconnect_task =
- GNUNET_SCHEDULER_add_delayed (mgr->reconnect_delay, &reconnect, mgr);
+ GNUNET_SCHEDULER_add_delayed (mgr->reconnect_delay, &schedule_reconnect, mgr);
mgr->reconnect_delay = GNUNET_TIME_STD_BACKOFF (mgr->reconnect_delay);
}
/**
* Add a message to the end of the transmission queue.
*
- * @param mgr Client manager connection.
- * @param msg Message to transmit. It is free()'d after transmission.
+ * @param mgr
+ * Client manager connection.
+ * @param msg
+ * Message to transmit, should be allocated with GNUNET_malloc() or
+ * GNUNET_new(), as it is freed with GNUNET_free() after transmission.
*/
void
GNUNET_CLIENT_MANAGER_transmit (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
/**
* Add a message to the beginning of the transmission queue.
*
- * @param mgr Client manager connection.
- * @param msg Message to transmit. It is free()'d after transmission.
+ * @param mgr
+ * Client manager connection.
+ * @param msg
+ * Message to transmit, should be allocated with GNUNET_malloc() or
+ * GNUNET_new(), as it is freed with GNUNET_free() after transmission.
*/
void
GNUNET_CLIENT_MANAGER_transmit_now (struct GNUNET_CLIENT_MANAGER_Connection *mgr,
/**
* Drop all queued messages.
*
- * @param mgr Client manager connection.
+ * @param mgr
+ * Client manager connection.
*/
void
GNUNET_CLIENT_MANAGER_drop_queue (struct GNUNET_CLIENT_MANAGER_Connection *mgr)
/**
* Obtain client connection handle.
*
- * @param mgr Client manager connection handle.
+ * @param mgr
+ * Client manager connection.
*
* @return Client connection handle.
*/
* Return user context associated with the given client.
* Note: you should probably use the macro (call without the underscore).
*
- * @param mgr Client manager connection.
- * @param size Number of bytes in user context struct (for verification only).
+ * @param mgr
+ * Client manager connection.
+ * @param size
+ * Number of bytes in user context struct (for verification only).
+ *
* @return User context.
*/
void *
* Set user context to be associated with the given client.
* Note: you should probably use the macro (call without the underscore).
*
- * @param mgr Client manager connection.
- * @param ctx User context.
- * @param size Number of bytes in user context struct (for verification only).
+ * @param mgr
+ * Client manager connection.
+ * @param ctx
+ * User context.
+ * @param size
+ * Number of bytes in user context struct (for verification only).
*/
void
GNUNET_CLIENT_MANAGER_set_user_context_ (struct GNUNET_CLIENT_MANAGER_Connection *mgr,