diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-03 09:12:57 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-03 09:12:57 +0000 |
commit | d4922969a54f83b3c2d7503a9bda2708700869c8 (patch) | |
tree | 6464df644674dec7600a3f82988e4035245e4215 /src/testbed/testbed_api_barriers.c | |
parent | 9b8e106ae9b8187de0092046d2ceaaf4dcd4852b (diff) | |
download | gnunet-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.c | 215 |
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 | */ | ||
248 | struct 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 | */ | ||
292 | static void | ||
293 | destroy_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 | */ | ||
314 | static void | ||
315 | receive_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 | */ | ||
364 | static size_t | ||
365 | transmit_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 | */ | ||
397 | struct GNUNET_TESTBED_BarrierWaitHandle * | ||
398 | GNUNET_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 | */ | ||
453 | void | ||
454 | GNUNET_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 */ |