* @file peerinfo/peerinfo_api.c
* @brief API to access peerinfo service
* @author Christian Grothoff
- *
- * TODO:
- * - document NEW API implementation
- * - add timeout for iteration
- * - implement cancellation of iteration
- * - prevent transmit during receive!
*/
#include "platform.h"
#include "gnunet_client_lib.h"
void *cont_cls;
/**
- * When this request times out.
+ * Timeout for the operation.
*/
struct GNUNET_TIME_Absolute timeout;
*/
struct GNUNET_CLIENT_TransmitHandle *th;
+ /**
+ * Set to GNUNET_YES if we are currently receiving replies from the
+ * service.
+ */
+ int in_receive;
+
};
return;
if (h->th != NULL)
return;
+ if (h->in_receive == GNUNET_YES)
+ return;
h->th = GNUNET_CLIENT_notify_transmit_ready (h->client,
tqe->size,
GNUNET_TIME_absolute_get_remaining (tqe->timeout),
*/
void *callback_cls;
+ /**
+ * Our entry in the transmission queue.
+ */
+ struct TransmissionQueueEntry *tqe;
+
+ /**
+ * Task responsible for timeout.
+ */
+ GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
/**
* Timeout for the operation.
*/
struct GNUNET_TIME_Absolute timeout;
+
+ /**
+ * Are we now receiving?
+ */
+ int in_receive;
};
const struct GNUNET_HELLO_Message *hello;
uint16_t ms;
+ ic->h->in_receive = GNUNET_NO;
if (msg == NULL)
{
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"peerinfo");
reconnect (ic->h);
trigger_transmit (ic->h);
- ic->callback (ic->callback_cls, NULL, NULL, 1);
+ if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (ic->h->sched,
+ ic->timeout_task);
+ if (ic->callback != NULL)
+ ic->callback (ic->callback_cls, NULL, NULL, 1);
GNUNET_free (ic);
return;
}
"Received end of list of peers from peerinfo database\n");
#endif
trigger_transmit (ic->h);
- ic->callback (ic->callback_cls, NULL, NULL, 0);
+ if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (ic->h->sched,
+ ic->timeout_task);
+ if (ic->callback != NULL)
+ ic->callback (ic->callback_cls, NULL, NULL, 0);
GNUNET_free (ic);
return;
}
GNUNET_break (0);
reconnect (ic->h);
trigger_transmit (ic->h);
- ic->callback (ic->callback_cls, NULL, NULL, 2);
+ if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (ic->h->sched,
+ ic->timeout_task);
+ if (ic->callback != NULL)
+ ic->callback (ic->callback_cls, NULL, NULL, 2);
GNUNET_free (ic);
return;
}
GNUNET_break (0);
reconnect (ic->h);
trigger_transmit (ic->h);
- ic->callback (ic->callback_cls, NULL, NULL, 2);
+ if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ GNUNET_SCHEDULER_cancel (ic->h->sched,
+ ic->timeout_task);
+ if (ic->callback != NULL)
+ ic->callback (ic->callback_cls, NULL, NULL, 2);
GNUNET_free (ic);
return;
}
"HELLO",
GNUNET_i2s (&im->peer));
#endif
- ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
+ ic->h->in_receive = GNUNET_YES;
+ if (ic->callback != NULL)
+ ic->callback (ic->callback_cls, &im->peer, hello, ntohl (im->trust));
GNUNET_CLIENT_receive (ic->h->client,
&peerinfo_handler,
ic,
GNUNET_free (ic);
return;
}
+ ic->h->in_receive = GNUNET_YES;
+ ic->in_receive = GNUNET_YES;
+ ic->tqe = NULL;
GNUNET_CLIENT_receive (ic->h->client,
&peerinfo_handler,
ic,
}
+/**
+ * Peerinfo iteration request has timed out.
+ *
+ * @param cls the 'struct GNUNET_PEERINFO_NewIteratorContext*'
+ * @param tc scheduler context
+ */
+static void
+signal_timeout (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_PEERINFO_NewIteratorContext *ic = cls;
+
+ ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ ic->callback (ic->callback_cls, NULL, NULL, 1);
+ ic->callback = NULL;
+ if (ic->in_receive)
+ return; /* need to finish processing */
+ GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
+ ic->h->tq_tail,
+ ic->tqe);
+ GNUNET_free (ic->tqe);
+ GNUNET_free (ic);
+}
+
+
/**
* Call a method for each known matching host and change its trust
* value. The callback method will be invoked once for each matching
memcpy (&lpm->peer, peer, sizeof (struct GNUNET_PeerIdentity));
}
ic = GNUNET_malloc (sizeof (struct GNUNET_PEERINFO_NewIteratorContext));
+ ic->h = h;
+ ic->tqe = tqe;
ic->callback = callback;
ic->callback_cls = callback_cls;
ic->timeout = GNUNET_TIME_relative_to_absolute (timeout);
+ ic->timeout_task = GNUNET_SCHEDULER_add_delayed (h->sched,
+ timeout,
+ &signal_timeout,
+ ic);
tqe->timeout = ic->timeout;
tqe->cont = &iterator_start_receive;
tqe->cont_cls = ic;
- /* FIXME: sort DLL by timeout? */
- /* FIXME: add timeout task!? */
+ tqe->timeout = ic->timeout;
GNUNET_CONTAINER_DLL_insert_after (h->tq_head,
h->tq_tail,
h->tq_tail,
void
GNUNET_PEERINFO_iterate_cancel_new (struct GNUNET_PEERINFO_NewIteratorContext *ic)
{
- GNUNET_assert (0);
- // FIXME: not implemented
+ if (ic->timeout_task != GNUNET_SCHEDULER_NO_TASK)
+ {
+ GNUNET_SCHEDULER_cancel (ic->h->sched,
+ ic->timeout_task);
+ ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+ }
+ ic->callback = NULL;
+ if (ic->in_receive)
+ return; /* need to finish processing */
+ GNUNET_CONTAINER_DLL_remove (ic->h->tq_head,
+ ic->h->tq_tail,
+ ic->tqe);
+ GNUNET_free (ic->tqe);
+ GNUNET_free (ic);
}
-
-
/* ***************************** OLD API ****************************** */