/** * Destroy a given client peer context * * @param cp client peer context */ static void destroy_clientpeer (struct ClientPeerContext *cp) { struct PendingMessage *pm; cp->destroying = GNUNET_YES; if (NULL != cp->th) { GNUNET_CADET_notify_transmit_ready_cancel (cp->th); cp->th = NULL; } pm = cp->pm_head; while (NULL != pm) { GNUNET_CONTAINER_DLL_remove (cp->pm_head, cp->pm_tail, pm); GNUNET_free (pm->msg); GNUNET_free (pm); pm = cp->pm_head; } if (NULL != cp->ch) { GNUNET_CADET_channel_destroy (cp->ch); cp->ch = NULL; } GNUNET_free (cp); }
/** * Disconnect from cadet services af all peers, call shutdown. * * @param cls Closure (line number from which termination was requested). * @param tc Task Context. */ static void disconnect_cadet_peers (void *cls) { long line = (long) cls; unsigned int i; disconnect_task = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnecting cadet service of peers, called from line %ld\n", line); for (i = 0; i < 2; i++) { GNUNET_TESTBED_operation_done (t_op[i]); } if (NULL != ch) { if (NULL != th) { GNUNET_CADET_notify_transmit_ready_cancel (th); th = NULL; } GNUNET_CADET_channel_destroy (ch); ch = NULL; } if (NULL != incoming_ch) { if (NULL != incoming_th) { GNUNET_CADET_notify_transmit_ready_cancel (incoming_th); incoming_th = NULL; } GNUNET_CADET_channel_destroy (incoming_ch); incoming_ch = NULL; } GNUNET_CADET_TEST_cleanup (test_ctx); GNUNET_SCHEDULER_shutdown (); }
/** * Function called whenever an channel is destroyed. Should clean up * any associated state. * * @param cls closure (set from GNUNET_CADET_connect) * @param channel connection to the other end (henceforth invalid) * @param channel_ctx place where local state associated * with the channel is stored */ static void channel_end (void *cls, const struct GNUNET_CADET_Channel *channel, void *channel_ctx) { long id = (long) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "incoming channel closed at peer %ld\n", id); if (NULL != mth) { GNUNET_CADET_notify_transmit_ready_cancel (mth); mth = NULL; } if (GNUNET_NO == got_data) { GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply ( GNUNET_TIME_UNIT_SECONDS, 2), &do_connect, NULL); } }
/** * Task to gather all statistics. * * @param cls Closure (NULL). */ static void gather_stats_and_exit (void *cls) { long l = (long) cls; disconnect_task = NULL; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "gathering statistics from line %d\n", (int) l); if (NULL != ch) { if (NULL != th) { GNUNET_CADET_notify_transmit_ready_cancel (th); th = NULL; } GNUNET_CADET_channel_destroy (ch); ch = NULL; } stats_op = GNUNET_TESTBED_get_statistics (peers_running, testbed_peers, "cadet", NULL, stats_iterator, stats_cont, cls); }
/** * Function is called whenever a message is received. * * @param cls closure (set from GNUNET_CADET_connect, peer number) * @param channel connection to the other end * @param channel_ctx place to store local state associated with the channel * @param message the actual message * @return GNUNET_OK to keep the connection open, * GNUNET_SYSERR to close it (signal serious error) */ int data_callback (void *cls, struct GNUNET_CADET_Channel *channel, void **channel_ctx, const struct GNUNET_MessageHeader *message) { struct GNUNET_CADET_TransmitHandle **pth; long client = (long) cls; long expected_target_client; uint32_t *data; uint32_t payload; unsigned int counter; ok++; counter = get_expected_target () == client ? data_received : ack_received; GNUNET_CADET_receive_done (channel); if ((ok % 10) == 0) { if (NULL != disconnect_task) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, " reschedule timeout\n"); GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, (void *) __LINE__); } } switch (client) { case 0L: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Root client got a message!\n"); GNUNET_assert (channel == ch); pth = &th; break; case 1L: case 4L: GNUNET_assert (client == peers_requested - 1); GNUNET_assert (channel == incoming_ch); pth = &incoming_th; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Leaf client %ld got a message.\n", client); break; default: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Client %ld not valid.\n", client); GNUNET_assert (0); } GNUNET_log (GNUNET_ERROR_TYPE_INFO, " ok: (%d/%d)\n", ok, ok_goal); data = (uint32_t *) &message[1]; payload = ntohl (*data); if (payload == counter) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, " payload as expected: %u\n", payload); } else { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " payload %u, expected: %u\n", payload, counter); } expected_target_client = get_expected_target (); if (GNUNET_NO == initialized) { initialized = GNUNET_YES; start_time = GNUNET_TIME_absolute_get (); if (SPEED == test) { GNUNET_assert (peers_requested - 1 == client); data_job = GNUNET_SCHEDULER_add_now (&data_task, NULL); return GNUNET_OK; } } counter++; if (client == expected_target_client) /* Normally 4 */ { data_received++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received data %u\n", data_received); if (SPEED != test || (ok_goal - 2) == ok) { /* Send ACK */ GNUNET_assert (NULL == *pth); *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload + ack_sent, &tmt_rdy, (void *) client); return GNUNET_OK; } else { if (data_received < TOTAL_PACKETS) return GNUNET_OK; } } else /* Normally 0 */ { if (SPEED_ACK == test || SPEED == test) { ack_received++; GNUNET_log (GNUNET_ERROR_TYPE_INFO, " received ack %u\n", ack_received); /* send more data */ GNUNET_assert (NULL == *pth); *pth = GNUNET_CADET_notify_transmit_ready (channel, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload + data_sent, &tmt_rdy, (void *) client); if (ack_received < TOTAL_PACKETS && SPEED != test) return GNUNET_OK; if (ok == 2 && SPEED == test) return GNUNET_OK; show_end_data(); } if (test == P2P_SIGNAL) { if (NULL != incoming_th) { GNUNET_CADET_notify_transmit_ready_cancel (incoming_th); incoming_th = NULL; } GNUNET_CADET_channel_destroy (incoming_ch); incoming_ch = NULL; } else { if (NULL != th) { GNUNET_CADET_notify_transmit_ready_cancel (th); th = NULL; } GNUNET_CADET_channel_destroy (ch); ch = NULL; } } return GNUNET_OK; }