aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_barriers.c
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-09-03 09:12:57 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-09-03 09:12:57 +0000
commitd4922969a54f83b3c2d7503a9bda2708700869c8 (patch)
tree6464df644674dec7600a3f82988e4035245e4215 /src/testbed/testbed_api_barriers.c
parent9b8e106ae9b8187de0092046d2ceaaf4dcd4852b (diff)
downloadgnunet-d4922969a54f83b3c2d7503a9bda2708700869c8.tar.gz
gnunet-d4922969a54f83b3c2d7503a9bda2708700869c8.zip
- barrier wait API
Diffstat (limited to 'src/testbed/testbed_api_barriers.c')
-rw-r--r--src/testbed/testbed_api_barriers.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/testbed/testbed_api_barriers.c b/src/testbed/testbed_api_barriers.c
index 23d34ffe8..58f8ba00c 100644
--- a/src/testbed/testbed_api_barriers.c
+++ b/src/testbed/testbed_api_barriers.c
@@ -241,4 +241,219 @@ GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier)
241 barrier_remove (barrier); 241 barrier_remove (barrier);
242} 242}
243 243
244
245/**
246 * Barrier wait handle
247 */
248struct GNUNET_TESTBED_BarrierWaitHandle
249{
250 /**
251 * The name of the barrier
252 */
253 char *name;
254
255 /**
256 * Then configuration used for the client connection
257 */
258 struct GNUNET_CONFIGURATION_Handle *cfg;
259
260 /**
261 * The client connection
262 */
263 struct GNUNET_CLIENT_Connection *conn;
264
265 /**
266 * Transmit handle
267 */
268 struct GNUNET_CLIENT_TransmitHandle *tx;
269
270 /**
271 * The message to transmit with tx
272 */
273 struct GNUNET_MessageHeader *msg;
274
275 /**
276 * The barrier wait callback
277 */
278 GNUNET_TESTBED_barrier_wait_cb cb;
279
280 /**
281 * The closure for the above callback
282 */
283 void *cls;
284};
285
286
287/**
288 * Function to destroy barrier wait handle
289 *
290 * @param h the handle to destroy
291 */
292static void
293destroy_handle (struct GNUNET_TESTBED_BarrierWaitHandle *h)
294{
295 GNUNET_free (h->name);
296 if (NULL != h->tx)
297 GNUNET_CLIENT_notify_transmit_ready_cancel (h->tx);
298 if (NULL != h->conn)
299 GNUNET_CLIENT_disconnect (h->conn);
300 if (NULL != h->msg)
301 GNUNET_free (h->msg);
302 GNUNET_CONFIGURATION_destroy (h->cfg);
303 GNUNET_free (h);
304}
305
306
307/**
308 * Type of a function to call when we receive a message
309 * from the service.
310 *
311 * @param cls closure
312 * @param msg message received, NULL on timeout or fatal error
313 */
314static void
315receive_handler (void *cls, const struct GNUNET_MessageHeader *message)
316{
317 struct GNUNET_TESTBED_BarrierWaitHandle *h = cls;
318 const struct GNUNET_TESTBED_BarrierStatusMsg *msg;
319 uint16_t msize;
320
321 if (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS != ntohs (message->type))
322 {
323 GNUNET_break_op (0);
324 goto fail;
325 }
326 msize = ntohs (message->size);
327 if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg))
328 {
329 GNUNET_break_op (0);
330 goto fail;
331 }
332 msg = (const struct GNUNET_TESTBED_BarrierStatusMsg *) message;
333 switch (ntohs (msg->status))
334 {
335 case BARRIER_STATUS_ERROR:
336 goto fail;
337 case BARRIER_STATUS_INITIALISED:
338 GNUNET_break (0); /* FIXME */
339 goto destroy;
340 case BARRIER_STATUS_CROSSED:
341 h->cb (h->cls, h->name, GNUNET_OK);
342 goto destroy;
343 }
344
345 fail:
346 h->cb (h->cls, h->name, GNUNET_SYSERR);
347
348 destroy:
349 destroy_handle (h);
350}
351
352
353/**
354 * Function called to notify a client about the connection
355 * begin ready to queue more data. "buf" will be
356 * NULL and "size" zero if the connection was closed for
357 * writing in the meantime.
358 *
359 * @param cls closure
360 * @param size number of bytes available in buf
361 * @param buf where the callee should write the message
362 * @return number of bytes written to buf
363 */
364static size_t
365transmit_notify (void *cls, size_t size, void *buf)
366{
367 struct GNUNET_TESTBED_BarrierWaitHandle *h = cls;
368 uint16_t msize;
369
370 h->tx = NULL;
371 if ((0 == size) || (NULL == buf))
372 {
373 destroy_handle (h);
374 return 0;
375 }
376 msize = htons (h->msg->size);
377 GNUNET_assert (msize <= size);
378 (void) memcpy (buf, h->msg, msize);
379 GNUNET_free (h->msg);
380 h->msg = NULL;
381 GNUNET_CLIENT_receive (h->conn, &receive_handler, h, GNUNET_TIME_UNIT_FOREVER_REL);
382 return msize;
383}
384
385
386/**
387 * Wait for a barrier to be crossed. This function should be called by the
388 * peers which have been started by the testbed. If the peer is not started by
389 * testbed this function may return error
390 *
391 * @param name the name of the barrier
392 * @param cb the barrier wait callback
393 * @param cls the closure for the above callback
394 * @return barrier wait handle which can be used to cancel the waiting at
395 * anytime before the callback is called. NULL upon error.
396 */
397struct GNUNET_TESTBED_BarrierWaitHandle *
398GNUNET_TESTBED_barrier_wait (const char *name,
399 GNUNET_TESTBED_barrier_wait_cb cb,
400 void *cls)
401{
402 struct GNUNET_TESTBED_BarrierWait *msg;
403 struct GNUNET_CONFIGURATION_Handle *cfg;
404 struct GNUNET_TESTBED_BarrierWaitHandle *h;
405 char *cfg_filename;
406 size_t name_len;
407 uint16_t msize;
408
409 GNUNET_assert (NULL != cb);
410 GNUNET_assert (NULL != name);
411 cfg_filename = getenv (ENV_TESTBED_CONFIG);
412 if (NULL == cfg_filename)
413 return NULL;
414 cfg = GNUNET_CONFIGURATION_create ();
415 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_filename));
416 {
417 GNUNET_CONFIGURATION_destroy (cfg);
418 return NULL;
419 }
420 h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_BarrierWaitHandle));
421 h->name = GNUNET_strdup (name);
422 h->cfg = cfg;
423 h->conn = GNUNET_CLIENT_connect ("testbed-barrier", h->cfg);
424 h->cb = cb;
425 h->cls = cls;
426 if (NULL == h->conn)
427 {
428 destroy_handle (h);
429 return NULL;
430 }
431 name_len = strlen (name);
432 msize = sizeof (struct GNUNET_TESTBED_BarrierWait) + name_len;
433 msg = GNUNET_malloc (msize);
434 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_WAIT);
435 msg->header.size = htons (msize);
436 (void) memcpy (msg->name, name, name_len);
437 h->msg = &msg->header;
438 h->tx =
439 GNUNET_CLIENT_notify_transmit_ready (h->conn, msize,
440 GNUNET_TIME_UNIT_FOREVER_REL,
441 GNUNET_NO,
442 &transmit_notify,
443 h);
444 return h;
445}
446
447
448/**
449 * Cancel a barrier wait handle
450 *
451 * @param h the barrier wait handle
452 */
453void
454GNUNET_TESTBED_barrier_wait_cancel (struct GNUNET_TESTBED_BarrierWaitHandle *h)
455{
456 destroy_handle (h);
457}
458
244/* end of testbed_api_barriers.c */ 459/* end of testbed_api_barriers.c */