*/
struct CadetTunnelQueueEntry *qe;
+ /**
+ * Data message we are trying to send.
+ */
+ struct GNUNET_CADET_ChannelAppDataMessage *data_message;
+
/**
* How soon should we retry if we fail to get an ACK?
* Messages in the queue are sorted by this value.
struct GNUNET_TIME_Relative retry_delay;
/**
- * Data message we are trying to send.
+ * Time when we first successfully transmitted the message
+ * (that is, set @e num_transmissions to 1).
*/
- struct GNUNET_CADET_ChannelAppDataMessage *data_message;
+ struct GNUNET_TIME_Absolute first_transmission_time;
+
+ /**
+ * Identifier of the connection that this message took when it
+ * was first transmitted. Only useful if @e num_transmissions is 1.
+ */
+ struct GNUNET_CADET_ConnectionTunnelIdentifier connection_taken;
+
+ /**
+ * How often was this message transmitted? #GNUNET_SYSERR if there
+ * was an error transmitting the message, #GNUNET_NO if it was not
+ * yet transmitted ever, otherwise the number of (re) transmissions.
+ */
+ int num_transmissions;
};
* the queue and tell our client that it can send more.
*
* @param ch the channel that got the PLAINTEXT_DATA_ACK
+ * @param cti identifier of the connection that delivered the message
* @param crm the message that got acknowledged
*/
static void
handle_matching_ack (struct CadetChannel *ch,
+ const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
struct CadetReliableMessage *crm)
{
GNUNET_CONTAINER_DLL_remove (ch->head_sent,
GCT_send_cancel (crm->qe);
crm->qe = NULL;
}
+ if ( (1 == crm->num_transmissions) &&
+ (NULL != cti) &&
+ (0 == memcmp (cti,
+ &crm->connection_taken,
+ sizeof (struct GNUNET_CADET_ConnectionTunnelIdentifier))) )
+ {
+ GCC_latency_observed (cti,
+ GNUNET_TIME_absolute_get_duration (crm->first_transmission_time));
+ }
GNUNET_free (crm->data_message);
GNUNET_free (crm);
send_ack_to_client (ch,
ntohl (crm->data_message->mid.mid),
GCCH_2s (ch));
handle_matching_ack (ch,
+ cti,
crm);
found = GNUNET_YES;
continue;
ntohl (crm->data_message->mid.mid),
GCCH_2s (ch));
handle_matching_ack (ch,
+ cti,
crm);
found = GNUNET_YES;
}
: GNUNET_YES);
return;
}
+ if (NULL == cid)
+ {
+ /* There was an error sending. */
+ crm->num_transmissions = GNUNET_SYSERR;
+ }
+ else if (GNUNET_SYSERR != crm->num_transmissions)
+ {
+ /* Increment transmission counter, and possibly store @a cid
+ if this was the first transmission. */
+ crm->num_transmissions++;
+ if (1 == crm->num_transmissions)
+ {
+ crm->first_transmission_time = GNUNET_TIME_absolute_get ();
+ crm->connection_taken = *cid;
+ }
+ }
if (0 == crm->retry_delay.rel_value_us)
crm->retry_delay = ch->expected_delay;
else
}
+/**
+ * We observed some the given @a latency on the connection
+ * identified by @a cti. (The same connection was taken
+ * in both directions.)
+ *
+ * @param cti connection identifier where we measured latency
+ * @param latency the observed latency
+ */
+void
+GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
+ struct GNUNET_TIME_Relative latency)
+{
+ GNUNET_break (0); // FIXME
+}
+
+
/**
* A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying
* that the end-to-end connection is up. Process it.
/**
* @file cadet/gnunet-service-cadet-new_connection.h
- * @brief
+ * @brief A connection is a live end-to-end messaging mechanism
+ * where the peers are identified by a path and know how
+ * to forward along the route using a connection identifier
+ * for routing the data.
* @author Bartlomiej Polot
* @author Christian Grothoff
*/
const struct GNUNET_CADET_TunnelEncryptedMessage *msg);
+/**
+ * We observed some the given @a latency on the connection
+ * identified by @a cti. (The same connection was taken
+ * in both directions.)
+ *
+ * @param cti connection identifier where we measured latency
+ * @param latency the observed latency
+ */
+void
+GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cti,
+ struct GNUNET_TIME_Relative latency);
+
+
/**
* Return the tunnel associated with this connection.
*