2 This file is part of GNUnet.
3 (C) 2010,2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file transport/gnunet-service-transport_manipulation.c
23 * @brief transport component manipulation traffic for simulation
24 * @author Christian Grothoff
25 * @author Matthias Wachs
28 #include "gnunet-service-transport_blacklist.h"
29 #include "gnunet-service-transport_clients.h"
30 #include "gnunet-service-transport_hello.h"
31 #include "gnunet-service-transport_neighbours.h"
32 #include "gnunet-service-transport_plugins.h"
33 #include "gnunet-service-transport_validation.h"
34 #include "gnunet-service-transport.h"
35 #include "transport.h"
41 enum TRAFFIC_METRIC_DIRECTION
48 struct GST_ManipulationHandle man_handle;
51 struct GST_ManipulationHandle
53 struct GNUNET_CONTAINER_MultiHashMap *peers;
56 * General inbound delay
58 struct GNUNET_TIME_Relative delay_recv;
61 * General outbound delay
63 struct GNUNET_TIME_Relative delay_send;
66 * General inbound distance
68 unsigned long long distance_recv;
71 * General outbound distance
73 unsigned long long distance_send;
82 struct DelayQueueEntry
84 struct DelayQueueEntry *prev;
85 struct DelayQueueEntry *next;
87 struct GNUNET_TIME_Absolute sent_at;
90 struct GNUNET_TIME_Relative timeout;
91 GST_NeighbourSendContinuation cont;
97 struct GNUNET_PeerIdentity peer;
98 uint32_t metrics [TM_BOTH][GNUNET_ATS_QualityPropertiesCount];
99 GNUNET_SCHEDULER_TaskIdentifier send_delay_task;
100 struct DelayQueueEntry *send_head;
101 struct DelayQueueEntry *send_tail;
107 set_delay(struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value)
110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n",
111 "DELAY", GNUNET_i2s(peer),
112 (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value);
114 if (UINT32_MAX == value)
115 val = UINT32_MAX - 1; /* prevent overflow */
117 val = UINT32_MAX; /* disable */
123 tmp->metrics[TM_SEND][DELAY] = val;
124 tmp->metrics[TM_RECEIVE][DELAY] = val;
127 tmp->metrics[TM_SEND][DELAY] = val;
130 tmp->metrics[TM_RECEIVE][DELAY] = val;
139 set_distance (struct TM_Peer *tmp, struct GNUNET_PeerIdentity *peer, int direction, uint32_t value)
142 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set traffic metrics %s for peer `%s' in direction %s to %u\n",
143 "DISTANCE", GNUNET_i2s(peer),
144 (TM_BOTH == direction) ? "BOTH" : (TM_SEND == direction) ? "SEND": "RECEIVE", value);
146 if (UINT32_MAX == value)
147 val = UINT32_MAX - 1; /* prevent overflow */
149 val = UINT32_MAX; /* disable */
155 tmp->metrics[TM_SEND][DISTANCE] = val;
156 tmp->metrics[TM_RECEIVE][DISTANCE] = val;
159 tmp->metrics[TM_SEND][DISTANCE] = val;
162 tmp->metrics[TM_RECEIVE][DISTANCE] = val;
170 GST_manipulation_set_metric (void *cls, struct GNUNET_SERVER_Client *client,
171 const struct GNUNET_MessageHeader *message)
173 struct TrafficMetricMessage *tm = (struct TrafficMetricMessage *) message;
174 struct GNUNET_PeerIdentity dummy;
175 struct GNUNET_ATS_Information *ats;
183 if (0 == ntohs (tm->ats_count))
184 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
186 switch (ntohs(tm->direction)) {
191 direction = TM_RECEIVE;
200 memset (&dummy, '\0', sizeof (struct GNUNET_PeerIdentity));
201 if (0 == memcmp (&tm->peer, &dummy, sizeof (struct GNUNET_PeerIdentity)))
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for all peers \n");
205 ats = (struct GNUNET_ATS_Information *) &tm[1];
206 for (c = 0; c < ntohs (tm->ats_count); c++)
208 type = htonl (ats[c].type);
209 value = htonl (ats[c].value);
212 case GNUNET_ATS_QUALITY_NET_DELAY:
213 if ((TM_RECEIVE == direction) || (TM_BOTH == direction))
214 man_handle.delay_recv.rel_value = value;
215 if ((TM_SEND == direction) || (TM_BOTH == direction))
216 man_handle.delay_send.rel_value = value;
218 case GNUNET_ATS_QUALITY_NET_DISTANCE:
219 if ((TM_RECEIVE == direction) || (TM_BOTH == direction))
220 man_handle.distance_recv = value;
221 if ((TM_SEND == direction) || (TM_BOTH == direction))
222 man_handle.distance_send = value;
232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received traffic metrics for peer `%s'\n",
233 GNUNET_i2s(&tm->peer));
235 if (NULL == (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &tm->peer.hashPubKey)))
237 tmp = GNUNET_malloc (sizeof (struct TM_Peer));
238 tmp->peer = (tm->peer);
239 for (c = 0; c < TM_BOTH; c++)
241 for (c2 = 0; c2 < GNUNET_ATS_QualityPropertiesCount; c2++)
243 tmp->metrics[c][c2] = UINT32_MAX;
246 GNUNET_CONTAINER_multihashmap_put (man_handle.peers, &tm->peer.hashPubKey, tmp, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
249 ats = (struct GNUNET_ATS_Information *) &tm[1];
250 for (c = 0; c < ntohs (tm->ats_count); c++)
252 type = htonl (ats[c].type);
253 value = htonl (ats[c].value);
255 case GNUNET_ATS_QUALITY_NET_DELAY:
256 set_delay (tmp, &tm->peer, direction, value);
258 case GNUNET_ATS_QUALITY_NET_DISTANCE:
259 set_distance (tmp, &tm->peer, direction, value);
266 GNUNET_SERVER_receive_done (client, GNUNET_OK);
270 send_delayed (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
272 struct DelayQueueEntry *dqe = cls;
273 struct DelayQueueEntry *next;
274 struct TM_Peer *tmp = dqe->tmp;
275 struct GNUNET_TIME_Relative delay;
276 tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
277 GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
278 GST_neighbours_send (&tmp->peer, dqe->msg, dqe->msg_size, dqe->timeout, dqe->cont, dqe->cont_cls);
280 next = tmp->send_head;
283 /* More delayed messages */
284 delay = GNUNET_TIME_absolute_get_remaining (next->sent_at);
285 tmp->send_delay_task = GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
292 GST_manipulation_send (const struct GNUNET_PeerIdentity *target, const void *msg,
293 size_t msg_size, struct GNUNET_TIME_Relative timeout,
294 GST_NeighbourSendContinuation cont, void *cont_cls)
297 struct DelayQueueEntry *dqe;
298 struct GNUNET_TIME_Relative delay;
300 if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &target->hashPubKey)))
302 /* Manipulate here */
304 if (UINT32_MAX != tmp->metrics[TM_SEND][DELAY])
306 /* We have a delay */
307 delay.rel_value = tmp->metrics[TM_SEND][DELAY];
308 dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
310 dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
312 dqe->cont_cls = cont_cls;
314 dqe->msg_size = msg_size;
315 dqe->timeout = timeout;
316 memcpy (dqe->msg, msg, msg_size);
317 GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe);
318 if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task)
319 tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
323 else if (man_handle.delay_send.rel_value != 0)
325 /* We have a delay */
326 delay = man_handle.delay_send;
327 dqe = GNUNET_malloc (sizeof (struct DelayQueueEntry) + msg_size);
329 dqe->sent_at = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(), delay);
331 dqe->cont_cls = cont_cls;
333 dqe->msg_size = msg_size;
334 dqe->timeout = timeout;
335 memcpy (dqe->msg, msg, msg_size);
336 GNUNET_CONTAINER_DLL_insert_tail (tmp->send_head, tmp->send_tail, dqe);
337 if (GNUNET_SCHEDULER_NO_TASK == tmp->send_delay_task)
338 tmp->send_delay_task =GNUNET_SCHEDULER_add_delayed (delay, &send_delayed, dqe);
343 GST_neighbours_send (target, msg, msg_size, timeout, cont, cont_cls);
346 struct GNUNET_TIME_Relative
347 GST_manipulation_recv (void *cls,
348 const struct GNUNET_PeerIdentity *peer,
349 const struct GNUNET_MessageHeader *message,
350 struct Session *session,
351 const char *sender_address,
352 uint16_t sender_address_len)
356 //struct GNUNET_ATS_Information ats_new[ats_count];
357 struct GNUNET_TIME_Relative quota_delay;
358 struct GNUNET_TIME_Relative m_delay;
360 if (man_handle.delay_recv.rel_value > GNUNET_TIME_UNIT_ZERO.rel_value)
361 m_delay = man_handle.delay_recv; /* Global delay */
363 m_delay = GNUNET_TIME_UNIT_ZERO;
366 for (d = 0; d < ats_count; d++)
369 if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) &&
370 (man_handle.distance_recv > 0))
371 ats_new[d].value = htonl(man_handle.distance_recv); /* Global inbound distance */
375 if (NULL != (tmp = GNUNET_CONTAINER_multihashmap_get (man_handle.peers, &peer->hashPubKey)))
378 /* Manipulate distance */
379 for (d = 0; d < ats_count; d++)
383 if ((ntohl(ats[d].type) == GNUNET_ATS_QUALITY_NET_DISTANCE) &&
384 (UINT32_MAX != tmp->metrics[TM_RECEIVE][DISTANCE]))
385 ats_new[d].value = htonl(tmp->metrics[TM_RECEIVE][DISTANCE]);
388 /* Manipulate receive delay */
389 if (UINT32_MAX != tmp->metrics[TM_RECEIVE][DELAY])
390 m_delay.rel_value = tmp->metrics[TM_RECEIVE][DELAY]; /* Peer specific delay */
393 quota_delay = GST_receive_callback (cls, peer, message,
394 session, sender_address, sender_address_len);
395 if (quota_delay.rel_value > m_delay.rel_value)
403 GST_manipulation_init (const struct GNUNET_CONFIGURATION_Handle *GST_cfg)
406 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
407 "transport", "MANIPULATE_DISTANCE_IN", &man_handle.distance_recv))
408 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting inbound distance_in to %u\n",
409 (unsigned long long) man_handle.distance_recv);
411 man_handle.distance_recv = 0;
413 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (GST_cfg,
414 "transport", "MANIPULATE_DISTANCE_OUT", &man_handle.distance_send))
415 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setting outbound distance_in to %u\n",
416 (unsigned long long) man_handle.distance_send);
418 man_handle.distance_send = 0;
420 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
421 "transport", "MANIPULATE_DELAY_IN", &man_handle.delay_recv))
422 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying inbound traffic for %llu ms\n",
423 (unsigned long long) man_handle.delay_recv.rel_value);
425 man_handle.delay_recv.rel_value = 0;
427 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_time (GST_cfg,
428 "transport", "MANIPULATE_DELAY_OUT", &man_handle.delay_send))
429 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Delaying outbound traffic for %llu ms\n",
430 (unsigned long long) man_handle.delay_send.rel_value);
432 man_handle.delay_send.rel_value = 0;
434 man_handle.peers = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
437 int free_tmps (void *cls,
438 const struct GNUNET_HashCode * key,
441 struct DelayQueueEntry *dqe;
442 struct DelayQueueEntry *next;
445 struct TM_Peer *tmp = (struct TM_Peer *) value;
446 GNUNET_CONTAINER_multihashmap_remove (man_handle.peers, key, value);
447 next = tmp->send_head;
448 while (NULL != (dqe = next))
451 GNUNET_CONTAINER_DLL_remove (tmp->send_head, tmp->send_tail, dqe);
454 if (GNUNET_SCHEDULER_NO_TASK != tmp->send_delay_task)
456 GNUNET_SCHEDULER_cancel (tmp->send_delay_task);
457 tmp->send_delay_task = GNUNET_SCHEDULER_NO_TASK;
465 GST_manipulation_stop ()
467 GNUNET_CONTAINER_multihashmap_iterate (man_handle.peers, &free_tmps,NULL);
469 GNUNET_CONTAINER_multihashmap_destroy (man_handle.peers);
470 man_handle.peers = NULL;
474 /* end of file gnunet-service-transport_manipulation.c */