* @file transport/gnunet-service-transport_manipulation.c
* @brief transport component manipulation traffic for simulation
* @author Christian Grothoff
- * @author
+ * @author Matthias Wachs
*/
#include "platform.h"
#include "gnunet-service-transport_blacklist.h"
#include "gnunet-service-transport.h"
#include "transport.h"
-static struct GNUNET_CONTAINER_MultiHashMap *peers;
-
#define DELAY 0
#define DISTANCE 1
+
+enum TRAFFIC_METRIC_DIRECTION
+{
+ TM_SEND = 0,
+ TM_RECEIVE = 1,
+ TM_BOTH = 2
+};
+
+struct GST_ManipulationHandle man_handle;
+
+
+struct GST_ManipulationHandle
+{
+ struct GNUNET_CONTAINER_MultiHashMap *peers;
+
+ /**
+ * General inbound delay
+ */
+ struct GNUNET_TIME_Relative delay_recv;
+
+ /**
+ * General outbound delay
+ */
+ struct GNUNET_TIME_Relative delay_send;
+
+ /**
+ * General inbound distance
+ */
+ unsigned long long distance_recv;
+
+ /**
+ * General outbound distance
+ */
+ unsigned long long distance_send;
+
+};
+
+
struct TM_Peer;
+
+
struct DelayQueueEntry
{
struct DelayQueueEntry *prev;
const struct GNUNET_MessageHeader *message)
{
struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message;
+ struct GNUNET_PeerIdentity dummy;
struct GNUNET_ATS_Information *ats;
struct TM_Peer *tmp;
uint32_t type;
uint32_t value;
+ uint16_t direction;
int c;
int c2;
if (0 == ntohs (tm->ats_count))
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+ switch (ntohs(tm->direction)) {
+ case 1:
+ direction = TM_SEND;
+ break;
+ case 2:
+ direction = TM_RECEIVE;
+ break;
+ case 3:
+ direction = TM_BOTH;
+ break;
+ default:
+ break;
+ }
+
+ memset (&dummy, '\0', sizeof (struct GNUNET_PeerIdentity));
+ if (0 == memcmp (&tm->peer, &dummy, sizeof (struct GNUNET_PeerIdentity)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for all peers \n");
+
+ ats = (struct GNUNET_ATS_Information *) &tm[1];
+ for (c = 0; c < ntohs (tm->ats_count); c++)
+ {
+ type = htonl (ats[c].type);
+ value = htonl (ats[c].value);
+
+ switch (type) {
+ case GNUNET_ATS_QUALITY_NET_DELAY:
+ if ((TM_RECEIVE == direction) || (TM_BOTH == direction))
+ man_handle.delay_recv.rel_value = value;
+ if ((TM_SEND == direction) || (TM_BOTH == direction))
+ man_handle.delay_send.rel_value = value;
+ break;
+ case GNUNET_ATS_QUALITY_NET_DISTANCE:
+ if ((TM_RECEIVE == direction) || (TM_BOTH == direction))
+ man_handle.distance_recv = value;
+ if ((TM_SEND == direction) || (TM_BOTH == direction))
+ man_handle.distance_send = value;
+ break;
+ default:
+ break;
+ }
+
+ }
+ return;
+ }
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n",
GNUNET_i2s(&tm->peer));
- if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &tm->peer.hashPubKey)))
+ if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &tm->peer.hashPubKey)))
{
tmp = GNUNET_malloc (sizeof (struct TM_Peer));
tmp->peer = (tm->peer);
tmp->metrics[c][c2] = UINT32_MAX;
}
}
- GNUNET_CONTAINER_multihashmap_put (peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
+ GNUNET_CONTAINER_multihashmap_put (man_handle.peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
}
ats = (struct GNUNET_ATS_Information *) &tm[1];
value = htonl (ats[c].value);
switch (type) {
case GNUNET_ATS_QUALITY_NET_DELAY:
- set_delay (tmp, &tm->peer, ntohs (tm->direction), value);
+ set_delay (tmp, &tm->peer, direction, value);
break;
case GNUNET_ATS_QUALITY_NET_DISTANCE:
- set_distance (tmp, &tm->peer, ntohs (tm->direction), value);
+ set_distance (tmp, &tm->peer, direction, value);
break;
default:
break;
struct DelayQueueEntry *dqe;
struct GNUNET_TIME_Relative delay;
- if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &target->hashPubKey)))
+ if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &target->hashPubKey)))
{
/* Manipulate here */
/* Delay */
return;
}
}
+ else if (man_handle.delay_send.rel_value != 0)
+ {
+ /* We have a delay */
+ delay = man_handle.delay_send;
+ dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
+ dqe->tmp = tmp;
+ dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
+ dqe->cont = cont;
+ dqe->cont_cls = cont_cls;
+ dqe->msg = &dqe[1];
+ dqe->msg_size = msg_size;
+ dqe->timeout = timeout;
+ memcpy (dqe->msg, msg, msg_size);
+ GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe);
+ if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task)
+ tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
+ return;
+ }
+
/* Normal sending */
GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
}
struct GNUNET_TIME_Relative
-GST_manipulation_recv (void *cls, const struct GNUNET_PeerIdentity *peer,
+GST_manipulation_recv (void *cls,
+ const struct GNUNET_PeerIdentity *peer,
const struct GNUNET_MessageHeader *message,
- const struct GNUNET_ATS_Information *ats,
- uint32_t ats_count, struct Session *session,
+ struct Session *session,
const char *sender_address,
uint16_t sender_address_len)
{
struct TM_Peer *tmp;
- int d;
- struct GNUNET_ATS_Information ats_new[ats_count];
- struct GNUNET_TIME_Relative q_delay;
+ //int d;
+ //struct GNUNET_ATS_Information ats_new[ats_count];
+ struct GNUNET_TIME_Relative quota_delay;
struct GNUNET_TIME_Relative m_delay;
+ if (man_handle.delay_recv.rel_value > GNUNET_TIME_UNIT_ZERO.rel_value)
+ m_delay = man_handle.delay_recv; /* Global delay */
+ else
+ m_delay = GNUNET_TIME_UNIT_ZERO;
+
+#if 0
for (d = 0; d < ats_count; d++)
+ {
+ ats_new[d] = ats[d];
+ if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) &&
+ (man_handle.distance_recv > 0))
+ ats_new[d].value = htonl(man_handle.distance_recv); /* Global inbound distance */
+ }
+#endif
- if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey)))
+ if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
{
+#if 0
/* Manipulate distance */
for (d = 0; d < ats_count; d++)
{
(UINT32_MAX != tmp->metrics[TM_RECEIVE][DISTANCE]))
ats_new[d].value = htonl(tmp->metrics[TM_RECEIVE][DISTANCE]);
}
+#endif
/* Manipulate receive delay */
if (UINT32_MAX != tmp->metrics[TM_RECEIVE][DELAY])
- {
- m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY];
- q_delay = GST_receive_callback (cls, peer, message, &ats_new[0], ats_count,
- session, sender_address, sender_address_len);
-
- if (q_delay.rel_value >= m_delay.rel_value)
- {
- return q_delay;
- }
- else
- {
- return m_delay;
- }
- }
- else
- return GST_receive_callback (cls, peer, message, &ats_new[0], ats_count,
- session, sender_address, sender_address_len);
+ m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY]; /* Peer specific delay */
}
- return GST_receive_callback (cls, peer, message, ats, ats_count,
+ quota_delay = GST_receive_callback (cls, peer, message,
session, sender_address, sender_address_len);
+ if (quota_delay.rel_value > m_delay.rel_value)
+ return quota_delay;
+ else
+ return m_delay;
+
}
void
-GST_manipulation_init ()
+GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
{
- peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
+ "transport", "MANIPULATE_DISTANCE_IN", &man_handle.distance_recv))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting inbound distance_in to %u\n",
+ (unsigned long long) man_handle.distance_recv);
+ else
+ man_handle.distance_recv = 0;
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
+ "transport", "MANIPULATE_DISTANCE_OUT", &man_handle.distance_send))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting outbound distance_in to %u\n",
+ (unsigned long long) man_handle.distance_send);
+ else
+ man_handle.distance_send = 0;
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
+ "transport", "MANIPULATE_DELAY_IN", &man_handle.delay_recv))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %llu ms\n",
+ (unsigned long long) man_handle.delay_recv.rel_value);
+ else
+ man_handle.delay_recv.rel_value = 0;
+
+ if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
+ "transport", "MANIPULATE_DELAY_OUT", &man_handle.delay_send))
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %llu ms\n",
+ (unsigned long long) man_handle.delay_send.rel_value);
+ else
+ man_handle.delay_send.rel_value = 0;
+
+ man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
}
int free_tmps (void *cls,
if (NULL != value)
{
struct TM_Peer *tmp = (struct TM_Peer *) value;
- GNUNET_CONTAINER_multihashmap_remove (peers, key, value);
+ GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value);
next = tmp->send_head;
while (NULL != (dqe = next))
{
void
GST_manipulation_stop ()
{
- GNUNET_CONTAINER_multihashmap_iterate (peers, &free_tmps,NULL);
+ GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL);
- GNUNET_CONTAINER_multihashmap_destroy (peers);
- peers = NULL;
+ GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers);
+ man_handle.peers = NULL;
}