/** * Task to request a new data transmission. * * @param cls Closure (peer #). */ static void data_task (void *cls) { struct GNUNET_CADET_Channel *channel; static struct GNUNET_CADET_TransmitHandle **pth; long src; data_job = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Data task\n"); if (GNUNET_YES == test_backwards) { channel = incoming_ch; pth = &incoming_th; src = peers_requested - 1; } else { channel = ch; pth = &th; src = 0; } GNUNET_assert (NULL != channel); 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 *) src); if (NULL == *pth) { unsigned long i = (unsigned long) cls; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Retransmission\n"); if (0 == i) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " in 1 ms\n"); data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS, &data_task, (void *) 1L); } else { i++; GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "in %llu ms\n", (unsigned long long) i); data_job = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, i), &data_task, (void *) i); } } }
/** * Trigger sending next pending message to the given client peer if any. * * @param cp client peer context struct */ static void trigger_send_next_msg (struct ClientPeerContext *cp) { struct PendingMessage *pm; if (NULL == cp->pm_head) return; if (NULL != cp->th) return; pm = cp->pm_head; cp->th = GNUNET_CADET_notify_transmit_ready (cp->ch, GNUNET_YES, GNUNET_TIME_UNIT_FOREVER_REL, ntohs (pm->msg->size), &do_send_msg, cp); }
/** * Connect to other client and send data * * @param cls Closue (unused). * @param tc TaskContext. */ static void do_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_PeerIdentity id; if (NULL != tc && 0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason)) return; GNUNET_TESTING_peer_get_identity (me, &id); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECT BY PORT\n"); ch = GNUNET_CADET_channel_create (cadet_peer_1, NULL, &id, 1, GNUNET_CADET_OPTION_DEFAULT); mth = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, sizeof (struct GNUNET_MessageHeader), &do_send, NULL); }
/** * START THE TESTCASE ITSELF, AS WE ARE CONNECTED TO THE CADET SERVICES. * * Testcase continues when the root receives confirmation of connected peers, * on callback function ch. * * @param cls Closure (unused). */ static void do_test (void *cls) { enum GNUNET_CADET_ChannelOption flags; test_task = NULL; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "do_test\n"); if (NULL != disconnect_task) { GNUNET_SCHEDULER_cancel (disconnect_task); disconnect_task = NULL; } flags = GNUNET_CADET_OPTION_DEFAULT; if (SPEED_REL == test) { test = SPEED; flags |= GNUNET_CADET_OPTION_RELIABLE; } ch = GNUNET_CADET_channel_create (h1, NULL, p_id[1], &port, flags); disconnect_task = GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &gather_stats_and_exit, (void *) __LINE__); if (KEEPALIVE == test) return; /* Don't send any data. */ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending data initializer...\n"); data_received = 0; data_sent = 0; ack_received = 0; ack_sent = 0; th = GNUNET_CADET_notify_transmit_ready (ch, GNUNET_NO, GNUNET_TIME_UNIT_FOREVER_REL, size_payload + 1000, &tmt_rdy, (void *) 0L); }
/** * 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; }